7 * An array of preprocessors to fill variables for templates and helper
8 * functions to make theming easier.
12 * Provide a full array of possible themes to try for a given hook.
15 * The hook to use. This is the base theme/template name.
17 * The view being rendered.
19 * The display being rendered, if applicable.
21 function _views_theme_functions($hook, $view, $display = NULL
) {
25 $themes[] = $hook .
'__' .
$view->name .
'__' .
$display->id
;
26 $themes[] = $hook .
'__' .
$display->id
;
27 if ($display->id
!= $display->display_plugin
) {
28 $themes[] = $hook .
'__' .
$view->name .
'__' .
$display->display_plugin
;
29 $themes[] = $hook .
'__' .
$display->display_plugin
;
32 $themes[] = $hook .
'__' .
$view->name
;
39 * Preprocess the primary theme implementation for a view.
41 function template_preprocess_views_view(&$vars) {
42 $view = $vars['view'];
44 $vars['rows'] = !empty($view->result
) ?
$view->style_handler
->render($view->result
) : '';
46 $vars['css_name'] = views_css_safe($view->name
);
47 $vars['name'] = $view->name
;
48 $vars['display_id'] = $view->current_display
;
51 $vars['empty'] = $view->display_handler
->render_empty();
52 if (!$view->display_handler
->get_option('header_empty')) {
55 if (!$view->display_handler
->get_option('footer_empty')) {
64 $vars['exposed'] = !empty($view->exposed_widgets
) ?
$view->exposed_widgets
: '';
65 if (!isset($vars['header'])) {
66 $vars['header'] = $view->display_handler
->render_header();
68 if (!isset($vars['footer'])) {
69 $vars['footer'] = $view->display_handler
->render_footer();
71 $vars['more'] = $view->display_handler
->render_more_link();
72 $vars['feed_icon'] = !empty($view->feed_icon
) ?
$view->feed_icon
: '';
74 $vars['attachment_before'] = !empty($view->attachment_before
) ?
$view->attachment_before
: '';
75 $vars['attachment_after'] = !empty($view->attachment_after
) ?
$view->attachment_after
: '';
79 $exposed_input = isset($view->exposed_data_raw
) ?
$view->exposed_data_raw
: NULL
;
80 if (!empty($view->pager
['use_pager'])) {
81 $pager_type = ($view->pager
['use_pager'] === 'mini' ?
'views_mini_pager' : 'pager');
82 $vars['pager'] = theme($pager_type, $exposed_input, $view->pager
['items_per_page'], $view->pager
['element']);
85 // if administrator, add some links. These used to be tabs, but this is better.
86 if (user_access('administer views')) {
87 $vars['admin_links_raw'] = array(
90 'alt' => t("Edit this view"),
91 'href' => "admin/build/views/edit/$view->name",
92 'fragment' => 'views-tab-' .
$view->current_display
,
93 'query' => drupal_get_destination(),
96 'title' => t('Export'),
97 'alt' => t("Export this view"),
98 'href' => "admin/build/views/export/$view->name",
101 'title' => t('Clone'),
102 'alt' => t("Create a copy of this view"),
103 'href' => "admin/build/views/clone/$view->name",
106 $vars['admin_links'] = theme('links', $vars['admin_links_raw']);
107 views_add_css('views');
110 $vars['admin_links'] = '';
111 $vars['admin_links_raw'] = array();
114 // If using AJAX, send identifying data about this view.
115 if ($view->use_ajax
) {
118 'ajax_path' => url('views/ajax'),
119 'ajaxViews' => array(
121 'view_name' => $view->name
,
122 'view_display_id' => $view->current_display
,
123 'view_args' => implode('/', $view->args
),
124 'view_path' => $_GET['q'],
130 drupal_add_js($settings, 'setting');
131 views_add_js('ajax_view');
136 * Preprocess theme function to print a single record from a row, with fields
138 function template_preprocess_views_view_fields(&$vars) {
139 $view = $vars['view'];
141 // Loop through the fields for this view.
143 foreach ($view->field as
$id => $field) {
144 if (!empty($field['handler']) && is_object($field['handler'])) {
145 $object = new
stdClass();
147 $object->content
= $field['handler']->theme($vars['row']);
148 if (isset($field['handler']->field_alias
) && isset($vars['row']->{$field['handler']->field_alias
})) {
149 $object->raw
= $vars['row']->{$field['handler']->field_alias
};
152 $object->raw
= NULL
; // make sure it exists to reduce NOTICE
154 $object->inline
= !empty($vars['options']['inline'][$id]);
155 $object->inline_html
= $object->inline ?
'span' : 'div';
156 if (!empty($vars['options']['separator']) && $inline && $object->inline
&& $object->content
) {
157 $object->separator
= filter_xss_admin($vars['options']['separator']);
160 $inline = $object->inline
;
162 $object->handler
= $field['handler'];
163 $object->class = views_css_safe($id);
164 $object->label
= check_plain($field['handler']->label());
165 $vars['fields'][$id] = $object;
172 * Display a single views field.
174 * Interesting bits of info:
175 * $field->field_alias says what the raw value in $row will be. Reach it like
176 * this: @code { $row->{$field->field_alias} @endcode
178 function theme_views_view_field($view, $field, $row) {
179 return $field->render($row);
183 * Preprocess theme function to print a single record from a row, with fields
185 function template_preprocess_views_view_summary(&$vars) {
186 $view = $vars['view'];
187 $argument = $view->argument
[$view->build_info
['summary_level']]['handler'];
189 $url_options = array();
191 if (!empty($view->exposed_raw_input
)) {
192 $url_options['query'] = $view->exposed_raw_input
;
194 foreach ($vars['rows'] as
$id => $row) {
195 $vars['rows'][$id]->link = $argument->summary_name($row);
197 $args[$argument->position
] = $argument->summary_argument($row);
199 $vars['rows'][$id]->url
= url($view->get_url($args), $url_options);
200 $vars['rows'][$id]->count = intval($row->{$argument->count_alias
});
205 * Display a view as a table style.
207 function template_preprocess_views_view_table(&$vars) {
208 $view = $vars['view'];
209 $result = $view->result
;
210 $options = $view->style_handler
->options
;
211 $handler = $view->style_handler
;
213 $fields = $view->field
;
214 $columns = $handler->sanitize_columns($options['columns'], $fields);
216 $active = !empty($handler->active
) ?
$handler->active
: '';
217 $order = !empty($handler->order
) ?
$handler->order
: 'asc';
219 $query = tablesort_get_querystring();
221 $query = '&' .
$query;
224 foreach ($columns as
$field => $column) {
225 // render the header labels
226 if ($field == $column) {
227 $label = check_plain(!empty($fields[$field]['handler']) ?
$fields[$field]['handler']->label() : '');
228 if (empty($options['info'][$field]['sortable'])) {
229 $vars['header'][$field] = $label;
232 // @todo -- make this a setting
235 if ($active == $field && $order == 'asc') {
239 $image = theme('tablesort_indicator', $initial);
240 $title = t('sort by @s', array('@s' => $label));
241 $link_options = array(
243 'attributes' => array('title' => $title),
244 'query' => 'order=' .
urlencode($field) .
'&sort=' .
$initial .
$query,
246 $vars['header'][$field] = l($label .
$image, $_GET['q'], $link_options);
250 // Create a second variable so we can easily find what fields we have and what the
251 // CSS classes should be.
252 $vars['fields'][$field] = views_css_safe($field);
253 if ($active == $field) {
254 $vars['fields'][$field] .
= ' active';
257 // Render each field into its appropriate column.
258 foreach ($result as
$num => $row) {
259 if (!empty($fields[$field]['handler']) && is_object($fields[$field]['handler'])) {
260 $handler = &$fields[$field]['handler'];
261 $field_output = $handler->theme($row);
263 // Don't bother with separators and stuff if the field does not show up.
264 if (!isset($field_output) && isset($vars['rows'][$num][$column])) {
268 // Place the field into the column, along with an optional separator.
269 if (isset($vars['rows'][$num][$column])) {
270 if (!empty($options['info'][$column]['separator'])) {
271 $vars['rows'][$num][$column] .
= filter_xss_admin($options['info'][$column]['separator']);
275 $vars['rows'][$num][$column] = '';
278 $vars['rows'][$num][$column] .
= $field_output;
283 $vars['class'] = 'views-table';
284 if (!empty($options['sticky'])) {
285 drupal_add_js('misc/tableheader.js');
286 $vars['class'] .
= " sticky-enabled";
291 * Display a view as a grid style.
293 function template_preprocess_views_view_grid(&$vars) {
294 $view = $vars['view'];
295 $result = $view->result
;
296 $options = $view->style_handler
->options
;
297 $handler = $view->style_handler
;
299 $columns = $options['columns'];
303 if ($options['alignment'] == 'horizontal') {
305 foreach ($vars['rows'] as
$count => $item) {
307 if (($count + 1) %
$columns == 0) {
317 $num_rows = floor(count($vars['rows']) / $columns);
318 // The remainders are the 'odd' columns that are slightly longer.
319 $remainders = count($vars['rows']) %
$columns;
322 foreach ($vars['rows'] as
$count => $item) {
323 $rows[$row][$col] = $item;
326 if (!$remainders && $row == $num_rows) {
330 else if ($remainders && $row == $num_rows + 1) {
337 $vars['rows'] = $rows;
341 * Preprocess an RSS feed
343 function template_preprocess_views_view_rss(&$vars) {
347 $view = &$vars['view'];
348 $options = &$vars['options'];
349 $items = &$vars['rows'];
351 $style = &$view->style_handler
;
353 if (!empty($options['mission_description'])) {
354 $description = variable_get('site_mission', '');
357 $description = $options['description'];
360 // Figure out which display which has a path we're using for this feed. If there isn't
361 // one, use the global $base_url
362 $link_display = $view->display_handler
->get_link_display();
365 // Compare the link to the default home page; if it's the default home page, just use $base_url.
366 if (empty($vars['link'])) {
367 $vars['link'] = $base_url;
370 $vars['namespaces'] = drupal_attributes($style->namespaces
);
371 $vars['channel'] = format_rss_channel($view->get_title(), $vars['link'], $description, $items, $language->language
);
373 drupal_set_header('Content-Type: application/rss+xml; charset=utf-8');
377 * Default theme function for all filter forms.
379 function template_preprocess_views_exposed_form(&$vars) {
380 views_add_css('views');
381 $form = &$vars['form'];
383 // Put all single checkboxes together in the last spot.
386 if (!empty($form['q'])) {
387 $vars['q'] = drupal_render($form['q']);
390 $vars['widgets'] = array();
391 foreach ($form['#info'] as
$id => $info) {
392 // Set aside checkboxes.
393 if (isset($form[$info['value']]['#type']) && $form[$info['value']]['#type'] == 'checkbox') {
394 $checkboxes .
= drupal_render($form[$info['value']]);
397 $widget = new stdClass
;
398 // set up defaults so that there's always something there.
399 $widget->label
= $widget->operator
= $widget->widget
= NULL
;
401 if (!empty($info['label'])) {
402 $widget->label
= $info['label'];
404 if (!empty($info['operator'])) {
405 $widget->operator
= drupal_render($form[$info['operator']]);
407 $widget->widget
= drupal_render($form[$info['value']]);
408 $vars['widgets'][$id] = $widget;
411 // Wrap up all the checkboxes we set aside into a widget.
413 $widget = new stdClass
;
414 // set up defaults so that there's always something there.
415 $widget->label
= $widget->operator
= $widget->widget
= NULL
;
416 $widget->widget
= $checkboxes;
417 $vars['widgets']['checkboxes'] = $widget;
420 // Don't render these:
421 unset($form['form_id']);
422 unset($form['form_build_id']);
423 unset($form['form_token']);
425 // This includes the submit button.
426 $vars['button'] = drupal_render($form);
429 function theme_views_mini_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
430 global $pager_page_array, $pager_total;
432 // Calculate various markers within this pager piece:
433 // Middle is used to "center" pages around the current page.
434 $pager_middle = ceil($quantity / 2);
435 // current is the page we are currently paged to
436 $pager_current = $pager_page_array[$element] + 1;
437 // max is the maximum page number
438 $pager_max = $pager_total[$element];
439 // End of marker calculations.
442 $li_previous = theme('pager_previous', (isset($tags[1]) ?
$tags[1] : t('‹‹')), $limit, $element, 1, $parameters);
443 $li_next = theme('pager_next', (isset($tags[3]) ?
$tags[3] : t('››')), $limit, $element, 1, $parameters);
445 if ($pager_total[$element] > 1) {
447 'class' => 'pager-previous',
448 'data' => $li_previous,
452 'class' => 'pager-current',
453 'data' => t('@current of @max', array('@current' => $pager_current, '@max' => $pager_max)),
457 'class' => 'pager-next',
460 return theme('item_list', $items, NULL
, 'ul', array('class' => 'pager'));
465 * @defgroup views_templates Views' template files
467 * All views templates can be overridden with a variety of names, using
468 * the view, the display ID of the view, the display type of the view,
469 * or some combination thereof.
471 * For each view, there will be a minimum of two templates used. The first
472 * is used for all views: views-view.tpl.php.
474 * The second template is determined by the style selected for the view. Note
475 * that certain aspects of the view can also change which style is used; for
476 * example, arguments which provide a summary view might change the style to
477 * one of the special summary styles.
479 * The default style for all views is views-view-unformatted.tpl.php
481 * Many styles will then farm out the actual display of each row to a row
482 * style; the default row style is views-view-fields.tpl.php.
484 * Here is an example of all the templates that will be tried in the following
487 * View, named foobar. Style: unformatted. Row style: Fields. Display: Page.
489 * - views-view--page--foobar.tpl.php
490 * - views-view--page.tpl.php
491 * - views-view--foobar.tpl.php
492 * - views-view.tpl.php
494 * - views-view-unformatted--page--foobar.tpl.php
495 * - views-view-unformatted--page.tpl.php
496 * - views-view-unformatted--foobar.tpl.php
497 * - views-view-unformatted.tpl.php
499 * - views-view-fields--page--foobar.tpl.php
500 * - views-view-fields--page.tpl.php
501 * - views-view-fields--foobar.tpl.php
502 * - views-view-fields.tpl.php
504 * Important! When adding a new template to your theme, be sure to flush the
505 * theme registry cache! Simply visit admin/build/themes.
507 * @see _views_theme_functions