How to hook_views_tables_alter()
First of all, this only applies to Views1 & Drupal 5 - there's probably a similar function in views2 however.
The setup: A timestamp ($node->created) was being selected in a View. The only options for formatting it are as Short, Long, Medium, Time Ago, or Custom. With custom you can enter any string that can be interpreted by php's date() function, and have that format apply.
The problem: The site that used a different format as its standard for displaying date and time, let's say "D F j, Y \a\t g:i A". We had created a function in template.php called site_format_date() that accepted a timestamp, and returned the date nicely formatted that way. All for reuseability! Now all the dates in the code (and template files, and theme function overrides) we write can call that function. And when Mrs. Editor decides that she really would like it to be something completely different, we can change it in one place and be done!
The table problem: What a pain to have to go to each View that uses a time or date, and select the "custom" format, and enter into the textbox the format we want to use. Now when someone wants to change the site-wide format, we'll have to go back to each view and update all the format fields! Argh!
So what we're trying to do, is somehow add our own custom format as one of the options for displaying a timestamp, in addition to the basic ones Drupal and Views provides us. Unfortunately, those choices are created by a call to views_handler_field_dates(), which just returns a fixed array of those 5 choices, and there's no way to get your own in there.
hook_views_tables_alter() to the rescue! This hook lets you modify how the Views module understands the tables in the Drupal database. Most of the core tables are added by .inc files in the views module, and many contrib modules have their own views.inc file. Using this hook you have the opportunity to change anything you like about how views works with modules, and do it safely without hacking any modules.
The fields I wanted to affect (the created and changed timestamp) are node fields. You can see them defined in path/to/views/modules/views_node.inc. I'm trying affect how the fields are handled (as opposed to filters, arguments, sorts, or anything else). By checking the .inc file I can see the keys I want to affect are simply called 'created' and 'changed'. Putting that all together, here is my complete hook function :
function hook_views_tables_alter(&$tabledata) { $tabledata['node']['fields']['created']['handler']['my_custom_format_date'] = t('As My Custom Date'); $tabledata['node']['fields']['changed']['handler']['my_custom_format_date'] = t('As My Custom Date'); }
Now when I can choose "As My Custom Date" to format the timestamps! Views will automatically call my_custom_format_date() for me, and I just pass the data right along to our sitewide date formatter.
function my_custom_format_date($fieldinfo, $fielddata, $value, $data) { return $value ? site_format_date($value) : theme('views_nodate');}
If figuring out the syntax of the array to modify was a little confusing (views syntax? confusing? never!) try this little snippet first:
function hook_views_tables_alter(&$tabledata) { drupal_set_message(print_r($tabledata, TRUE));}
and you'll get a very long printout of how every table interacts with the Views module. With some searching and little luck, you should be able to find the section you want to modify. Lots of great views1 and views2 documentation is available, but it gets a little hairy! Unfortunately there's not a lot of documentation that I could find on this very powerful hook! I discovered it while poking through the views.module code and found 1 Drupal issue at http://drupal.org/node/142383. (This was the issue that actually enabled the hook to work properly as of about July 2007).
Remind me to add some pictures to this post!