Add a replacement pattern token for a Views field rewrite results
Views fields offer the opportunity to "Rewrite results: Rewrite the output of this field". The option further specifies "Enable to override the output of this field with custom text or replacement tokens." It then provides a textarea with the instruction: "The text to display for this field. You may include HTML. You may enter data from this view as per the 'Replacement patterns' below." The replacement patterns, in turn, have the introduction: "The following tokens are available for this field. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields. If you would like to have the characters '[' and ']' please use the html entity codes '%5B' or '%5D' or they will get replaced with empty space."
Suppose you wanted a different token based on a field's data than the handful provided in Views' rewrite results option when displaying a field? Check out the code example below.
What if you want to make use of the normal output of a field and a special token? If you can do the rewrite in that field, both the normal field and your special token will be available as replacement patterns. But if the rewrite must be done later, you can add the same field to a view more than once. The results of previous fields, even if they are hidden from output, are themselves available as replacement patterns (tokens).
We wanted a new replacement pattern to be able to link to a Facet API enhanced view that was using Facet API pretty paths to cleanly give taxonomy term based filters a presence in the URL. That means we wanted taxonomy term fields to be able to give a token based on part of their automatic alias exactly as the Facet API pretty paths module does.
Here's how:
In our module's .info file (cultura_archive.info in this example) list the file with the field handler class so that it will be registered:
files[] = cultura_archive_views_handler_field_term_path.inc
The trick is to extend the field handler class; for a Views field that is a normal Drupal field the class to extend will be the exquisitely named views_handler_field_field(). Because your extending a class, you only need to redefine the methods you care about (but you do need to incorporate the normal function of those methods). The methods to care about for replacement patterns are document_self_tokens() and add_self_tokens(). Here's the entirety of that file in our example:
<?php
/**
* Extend taxonomy term field handler with tokens for pretty paths.
*
* @ingroup views_field_handlers
*/
class cultura_archive_views_handler_field_term_path extends views_handler_field_field {
function
document_self_tokens(&$tokens) {
$field = $this->field_info;
foreach ($field['columns'] as $id => $column) {
$tokens['[' . $this->options['id'] . '-' . $id . ']'] = t('Raw @column', array('@column' => $id));
$tokens['[' . $this->options['id'] . '-' . 'term-pretty-path]'] = t('Term pretty path');
$tokens['[' . $this->options['id'] . '-' . 'vocabulary-pretty-path]'] = t('Vocabulary pretty path');
}
}
function
add_self_tokens(&$tokens, $item) {
$field = $this->field_info;
foreach ($field['columns'] as $id => $column) {
// Use filter_xss_admin because it's user data and we can't be sure it is safe.
// We know nothing about the data, though, so we can't really do much else.
if (isset($item['raw'])) {
// If $item['raw'] is an array then we can use as is, if it's an object
// we cast it to an array, if it's neither, we can't use it.
$raw = is_array($item['raw']) ? $item['raw'] :
(is_object($item['raw']) ? (array)$item['raw'] : NULL);
}
if (isset($raw) && isset($raw[$id]) && is_scalar($raw[$id])) {
$path_string = cultura_archive_term_pretty_path($raw[$id]);
$path = explode('/', $path_string);
$tokens['[' . $this->options['id'] . '-term-pretty-path]'] = $path[1];
$tokens['[' . $this->options['id'] . '-vocabulary-pretty-path]'] = $path[0];
}
else {
// Take sure that empty values are replaced as well.
$tokens['[' . $this->options['id'] . '-term-pretty-path]'] = '';
$tokens['[' . $this->options['id'] . '-vocabulary-pretty-path]'] = '';
}
}
}
}
/**
* Return the vocabulary and term pretty paths for a taxonomy term.
*
* @param integer $tid
* @return string path
*/
function cultura_archive_term_pretty_path($tid) {
$path = path_load(array('source' => 'taxonomy/term/' . $tid));
return $path['alias'];
}
?>
And an implementation of hook_views_data_alter() in your .module file, set the field handler for one or more fields (here we iterate through a half-dozen) to the class you just defined.
<?php
/**
* Implements hook_views_data_alter().
*/
function cultura_archive_views_data_alter(&$data) {
$taxonomy_term_fields = array(
'cultura_host_school',
'cultura_guest_school',
'cultura_host_language',
'cultura_guest_language',
'cultura_semester',
'cultura_year',
);
foreach ($taxonomy_term_fields as $field) {
$data['field_data_' . $field][$field]['field']['handler'] = 'cultura_archive_views_handler_field_term_path';
}
}
?>
Pretty clean, and most important you have a nice little replacement pattern in your view and won't be tempted to try to do some awful PHP there.
Comments
Post new comment