Newer
Older
<?php
/**
* @file
* Preprocessors and helper functions to make theming easier.
*/
use Drupal\Core\Template\Attribute;
Tim Plunkett
committed
use Drupal\views\ViewExecutable;
/**
* Provide a full array of possible themes to try for a given hook.
*
* @param $hook
* The hook to use. This is the base theme/template name.
* @param $view
* The view being rendered.
* @param $display
* The display being rendered, if applicable.
*/
Tim Plunkett
committed
function _views_theme_functions($hook, ViewExecutable $view, $display = NULL) {
Angie Byron
committed
$themes[] = $hook . '__' . $view->storage->id() . '__' . $display['id'];
Daniel Wehner
committed
$themes[] = $hook . '__' . $display['id'];
Daniel Wehner
committed
// Add theme suggestions for each single tag.
Angie Byron
committed
foreach (drupal_explode_tags($view->storage->get('tag')) as $tag) {
$themes[] = $hook . '__' . preg_replace('/[^a-z0-9]/', '_', strtolower($tag));
}
Daniel Wehner
committed
if ($display['id'] != $display['display_plugin']) {
Angie Byron
committed
$themes[] = $hook . '__' . $view->storage->id() . '__' . $display['display_plugin'];
Daniel Wehner
committed
$themes[] = $hook . '__' . $display['display_plugin'];
Angie Byron
committed
$themes[] = $hook . '__' . $view->storage->id();
$themes[] = $hook;
return $themes;
}
/**
* Preprocess the primary theme implementation for a view.
*/
function template_preprocess_views_view(&$vars) {
global $base_path;
$view = $vars['view'];
catch
committed
$vars['rows'] = (!empty($view->result) || $view->style_plugin->even_empty()) ? $view->style_plugin->render($view->result) : '';
// Force a render array so CSS/JS can be added.
if (!is_array($vars['rows'])) {
$vars['rows'] = array('#markup' => $vars['rows']);
}
Angie Byron
committed
$vars['css_name'] = drupal_clean_css_identifier($view->storage->id());
$vars['id'] = $view->storage->id();
$vars['display_id'] = $view->current_display;
// Basic classes
Damian Lee
committed
$vars['css_class'] = '';
Tim Plunkett
committed
$vars['attributes']['class'] = array();
$vars['attributes']['class'][] = 'view';
Angie Byron
committed
$vars['attributes']['class'][] = 'view-' . drupal_clean_css_identifier($vars['id']);
$vars['attributes']['class'][] = 'view-id-' . $vars['id'];
Tim Plunkett
committed
$vars['attributes']['class'][] = 'view-display-id-' . $vars['display_id'];
Daniel Wehner
committed
$css_class = $view->display_handler->getOption('css_class');
if (!empty($css_class)) {
$vars['css_class'] = preg_replace('/[^a-zA-Z0-9- ]/', '-', $css_class);
Tim Plunkett
committed
$vars['attributes']['class'][] = $vars['css_class'];
$empty = empty($view->result);
Daniel Wehner
committed
$vars['header'] = $view->display_handler->renderArea('header', $empty);
$vars['footer'] = $view->display_handler->renderArea('footer', $empty);
catch
committed
$vars['empty'] = $empty ? $view->display_handler->renderArea('empty', $empty) : FALSE;
$vars['exposed'] = !empty($view->exposed_widgets) ? $view->exposed_widgets : '';
Daniel Wehner
committed
$vars['more'] = $view->display_handler->renderMoreLink();
$vars['feed_icon'] = !empty($view->feed_icon) ? $view->feed_icon : '';
$vars['pager'] = '';
// @todo: Figure out whether this belongs into views_ui_preprocess_views_view.
// Render title for the admin preview.
Damian Lee
committed
$vars['title'] = !empty($view->views_ui_context) ? filter_xss_admin($view->getTitle()) : '';
Daniel Wehner
committed
if ($view->display_handler->renderPager()) {
$exposed_input = isset($view->exposed_raw_input) ? $view->exposed_raw_input : NULL;
Damian Lee
committed
$vars['pager'] = $view->renderPager($exposed_input);
Dries Buytaert
committed
if (!empty($view->attachment_before)) {
$vars['attachment_before'] = $view->attachment_before;
}
else {
$vars['attachment_before'] = array();
}
if (!empty($view->attachment_after)) {
$vars['attachment_after'] = $view->attachment_after;
}
else {
$vars['attachment_after'] = array();
}
// Add contextual links to the view. We need to attach them to the dummy
// $view_array variable, since contextual_preprocess() requires that they be
// attached to an array (not an object) in order to process them. For our
// purposes, it doesn't matter what we attach them to, since once they are
// processed by contextual_preprocess() they will appear in the $title_suffix
// variable (which we will then render in views-view.tpl.php).
views_add_contextual_links($vars['view_array'], 'view', $view, $view->current_display);
// Attachments are always updated with the outer view, never by themselves,
// so they do not have dom ids.
if (empty($view->is_attachment)) {
// Our JavaScript needs to have some means to find the HTML belonging to this
// view.
//
// It is true that the DIV wrapper has classes denoting the name of the view
// and its display ID, but this is not enough to unequivocally match a view
// with its HTML, because one view may appear several times on the page. So
// we set up a hash with the current time, $dom_id, to issue a "unique" identifier for
// each view. This identifier is written to both Drupal.settings and the DIV
// wrapper.
$vars['dom_id'] = $view->dom_id;
Tim Plunkett
committed
$vars['attributes']['class'][] = 'view-dom-id-' . $vars['dom_id'];
}
// If using AJAX, send identifying data about this view.
if ($view->ajaxEnabled() && empty($view->is_attachment) && empty($view->live_preview)) {
$settings = array(
'views' => array(
'ajax_path' => url('views/ajax'),
'ajaxViews' => array(
'views_dom_id:' . $vars['dom_id'] => array(
Angie Byron
committed
'view_name' => $view->storage->id(),
'view_display_id' => $view->current_display,
'view_args' => check_plain(implode('/', $view->args)),
'view_path' => check_plain(current_path()),
Damian Lee
committed
'view_base_path' => $view->getPath(),
'view_dom_id' => $vars['dom_id'],
// To fit multiple views on a page, the programmer may have
// overridden the display's pager_element.
Daniel Wehner
committed
'pager_element' => isset($view->pager) ? $view->pager->get_pager_id() : 0,
catch
committed
$view->element['#attached']['js'][] = array('type' => 'setting', 'data' => $settings);
$view->element['#attached']['library'][] = array('views', 'views.ajax');
}
// If form fields were found in the View, reformat the View output as a form.
if (views_view_has_form_elements($view)) {
// Copy the rows so as not to modify them by reference when rendering.
$rows = $vars['rows'];
$rows = drupal_render($rows);
catch
committed
$output = !empty($rows) ? $rows : $vars['empty'];
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
$form = drupal_get_form(views_form_id($view), $view, $output);
// The form is requesting that all non-essential views elements be hidden,
// usually because the rendered step is not a view result.
if ($form['show_view_elements']['#value'] == FALSE) {
$vars['header'] = '';
$vars['exposed'] = '';
$vars['pager'] = '';
$vars['footer'] = '';
$vars['more'] = '';
$vars['feed_icon'] = '';
}
$vars['rows'] = $form;
}
}
/**
* Preprocess theme function to print a single record from a row, with fields
*/
function template_preprocess_views_view_fields(&$vars) {
$view = $vars['view'];
// Loop through the fields for this view.
$previous_inline = FALSE;
$vars['fields'] = array(); // ensure it's at least an empty array.
foreach ($view->field as $id => $field) {
// render this even if set to exclude so it can be used elsewhere.
$field_output = $view->style_plugin->get_field($view->row_index, $id);
$empty = $field->is_value_empty($field_output, $field->options['empty_zero']);
if (empty($field->options['exclude']) && (!$empty || (empty($field->options['hide_empty']) && empty($vars['options']['hide_empty'])))) {
$object = new stdClass();
$object->handler = &$view->field[$id];
$object->inline = !empty($vars['options']['inline'][$id]);
$object->element_type = $object->handler->element_type(TRUE, !$vars['options']['default_field_elements'], $object->inline);
if ($object->element_type) {
$attributes = array();
if ($object->handler->options['element_default_classes']) {
$attributes['class'][] = 'field-content';
}
if ($classes = $object->handler->element_classes($view->row_index)) {
$attributes['class'][] = $classes;
$attributes = new Attribute($attributes);
$pre .= $attributes;
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
$field_output = $pre . '>' . $field_output . '</' . $object->element_type . '>';
}
// Protect ourself somewhat for backward compatibility. This will prevent
// old templates from producing invalid HTML when no element type is selected.
if (empty($object->element_type)) {
$object->element_type = 'span';
}
$object->content = $field_output;
if (isset($view->field[$id]->field_alias) && isset($vars['row']->{$view->field[$id]->field_alias})) {
$object->raw = $vars['row']->{$view->field[$id]->field_alias};
}
else {
$object->raw = NULL; // make sure it exists to reduce NOTICE
}
if (!empty($vars['options']['separator']) && $previous_inline && $object->inline && $object->content) {
$object->separator = filter_xss_admin($vars['options']['separator']);
}
$object->class = drupal_clean_css_identifier($id);
$previous_inline = $object->inline;
$object->inline_html = $object->handler->element_wrapper_type(TRUE, TRUE);
if ($object->inline_html === '' && $vars['options']['default_field_elements']) {
$object->inline_html = $object->inline ? 'span' : 'div';
}
// Set up the wrapper HTML.
$object->wrapper_prefix = '';
$object->wrapper_suffix = '';
if ($object->inline_html) {
$attributes = array();
if ($object->handler->options['element_default_classes']) {
$attributes['class'][] = 'views-field';
$attributes['class'][] = 'views-field-' . $object->class;
}
if ($classes = $object->handler->element_wrapper_classes($view->row_index)) {
$attributes['class'][] = $classes;
$attributes = new Attribute($attributes);
$object->wrapper_prefix = '<' . $object->inline_html;
$object->wrapper_prefix .= $attributes;
$object->wrapper_prefix .= '>';
$object->wrapper_suffix = '</' . $object->inline_html . '>';
}
// Set up the label for the value and the HTML to make it easier
// on the template.
$object->label = check_plain($view->field[$id]->label());
$object->label_html = '';
if ($object->label) {
$object->label_html .= $object->label;
if ($object->handler->options['element_label_colon']) {
$object->label_html .= ': ';
}
$object->element_label_type = $object->handler->element_label_type(TRUE, !$vars['options']['default_field_elements']);
if ($object->element_label_type) {
$attributes = array();
if ($object->handler->options['element_default_classes']) {
$attributes['class'][] = 'views-label';
$attributes['class'][] = 'views-label-' . $object->class;
}
$element_label_class = $object->handler->element_label_classes($view->row_index);
if ($element_label_class) {
$attributes['class'][] = $element_label_class;
$attributes = new Attribute($attributes);
$pre = '<' . $object->element_label_type;
$pre .= $attributes;
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
$pre .= '>';
$object->label_html = $pre . $object->label_html . '</' . $object->element_label_type . '>';
}
}
$vars['fields'][$id] = $object;
}
}
}
/**
* Process a single grouping within a view.
*/
function template_preprocess_views_view_grouping(&$vars) {
$vars['content'] = $vars['view']->style_plugin->render_grouping_sets($vars['rows'], $vars['grouping_level']);
}
/**
* Display a single views field.
*
* Interesting bits of info:
* $field->field_alias says what the raw value in $row will be. Reach it like
* this: @code { $row->{$field->field_alias} @endcode
*/
function theme_views_view_field($vars) {
$view = $vars['view'];
$field = $vars['field'];
$row = $vars['row'];
return $vars['output'];
}
/**
* Process a single field within a view.
*
* This preprocess function isn't normally run, as a function is used by
* default, for performance. However, by creating a template, this
* preprocess should get picked up.
*/
function template_preprocess_views_view_field(&$vars) {
$vars['output'] = $vars['field']->advanced_render($vars['row']);
}
/**
* Preprocess theme function to print a single record from a row, with fields
*/
function template_preprocess_views_view_summary(&$vars) {
$view = $vars['view'];
$argument = $view->argument[$view->build_info['summary_level']];
$vars['row_classes'] = array();
$url_options = array();
if (!empty($view->exposed_raw_input)) {
$url_options['query'] = $view->exposed_raw_input;
}
$active_urls = drupal_map_assoc(array(
url(current_path(), array('alias' => TRUE)), // force system path
url(current_path()), // could be an alias
));
// Collect all arguments foreach row, to be able to alter them for example by the validator.
// This is not done per single argument value, because this could cause performance problems.
$row_args = array();
foreach ($vars['rows'] as $id => $row) {
$row_args[$id] = $argument->summary_argument($row);
}
$argument->process_summary_arguments($row_args);
foreach ($vars['rows'] as $id => $row) {
$vars['rows'][$id]->link = $argument->summary_name($row);
$args = $view->args;
$args[$argument->position] = $row_args[$id];
$base_path = NULL;
if (!empty($argument->options['summary_options']['base_path'])) {
$base_path = $argument->options['summary_options']['base_path'];
}
Damian Lee
committed
$vars['rows'][$id]->url = url($view->getUrl($args, $base_path), $url_options);
$vars['rows'][$id]->count = intval($row->{$argument->count_alias});
$vars['row_classes'][$id] = array();
if (isset($active_urls[$vars['rows'][$id]->url])) {
$vars['row_classes'][$id]['class'][] = 'active';
$vars['row_classes'][$id] = new Attribute($vars['row_classes'][$id]);
}
}
/**
* Template preprocess theme function to print summary basically
* unformatted.
*/
function template_preprocess_views_view_summary_unformatted(&$vars) {
$view = $vars['view'];
$argument = $view->argument[$view->build_info['summary_level']];
$vars['row_classes'] = array();
$url_options = array();
if (!empty($view->exposed_raw_input)) {
$url_options['query'] = $view->exposed_raw_input;
}
$count = 0;
$active_urls = drupal_map_assoc(array(
url(current_path(), array('alias' => TRUE)), // force system path
url(current_path()), // could be an alias
));
// Collect all arguments foreach row, to be able to alter them for example by the validator.
// This is not done per single argument value, because this could cause performance problems.
$row_args = array();
foreach ($vars['rows'] as $id => $row) {
$row_args[$id] = $argument->summary_argument($row);
}
$argument->process_summary_arguments($row_args);
foreach ($vars['rows'] as $id => $row) {
// only false on first time:
if ($count++) {
$vars['rows'][$id]->separator = filter_xss_admin($vars['options']['separator']);
}
$vars['rows'][$id]->link = $argument->summary_name($row);
$args = $view->args;
$args[$argument->position] = $row_args[$id];
$base_path = NULL;
if (!empty($argument->options['summary_options']['base_path'])) {
$base_path = $argument->options['summary_options']['base_path'];
}
Damian Lee
committed
$vars['rows'][$id]->url = url($view->getUrl($args, $base_path), $url_options);
$vars['rows'][$id]->count = intval($row->{$argument->count_alias});
$vars['row_classes'][$id] = array();
if (isset($active_urls[$vars['rows'][$id]->url])) {
$vars['row_classes'][$id]['class'][] = 'active';
$vars['row_classes'][$id] = new Attribute($vars['row_classes'][$id]);
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
}
}
/**
* Display a view as a table style.
*/
function template_preprocess_views_view_table(&$vars) {
$view = $vars['view'];
// We need the raw data for this grouping, which is passed in as $vars['rows'].
// However, the template also needs to use for the rendered fields. We
// therefore swap the raw data out to a new variable and reset $vars['rows']
// so that it can get rebuilt.
// Store rows so that they may be used by further preprocess functions.
$result = $vars['result'] = $vars['rows'];
$vars['rows'] = array();
$vars['field_classes'] = array();
$vars['header'] = array();
$options = $view->style_plugin->options;
$handler = $view->style_plugin;
$default_row_class = isset($options['default_row_class']) ? $options['default_row_class'] : TRUE;
$row_class_special = isset($options['row_class_special']) ? $options['row_class_special'] : TRUE;
$fields = &$view->field;
$columns = $handler->sanitize_columns($options['columns'], $fields);
$active = !empty($handler->active) ? $handler->active : '';
$order = !empty($handler->order) ? $handler->order : 'asc';
// A boolean variable which stores whether the table has a responsive class.
$responsive = FALSE;
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
$query = tablesort_get_query_parameters();
if (isset($view->exposed_raw_input)) {
$query += $view->exposed_raw_input;
}
foreach ($columns as $field => $column) {
// Create a second variable so we can easily find what fields we have and what the
// CSS classes should be.
$vars['fields'][$field] = drupal_clean_css_identifier($field);
if ($active == $field) {
$vars['fields'][$field] .= ' active';
}
// render the header labels
if ($field == $column && empty($fields[$field]->options['exclude'])) {
$label = check_plain(!empty($fields[$field]) ? $fields[$field]->label() : '');
if (empty($options['info'][$field]['sortable']) || !$fields[$field]->click_sortable()) {
$vars['header'][$field] = $label;
}
else {
$initial = !empty($options['info'][$field]['default_sort_order']) ? $options['info'][$field]['default_sort_order'] : 'asc';
if ($active == $field) {
$initial = ($order == 'asc') ? 'desc' : 'asc';
}
$title = t('sort by @s', array('@s' => $label));
if ($active == $field) {
$label .= theme('tablesort_indicator', array('style' => $initial));
}
$query['order'] = $field;
$query['sort'] = $initial;
$link_options = array(
'html' => TRUE,
'attributes' => array('title' => $title),
'query' => $query,
);
$vars['header'][$field] = l($label, current_path(), $link_options);
$vars['header_classes'][$field] = array();
if ($fields[$field]->options['element_default_classes']) {
$vars['header_classes'][$field]['class'][] = 'views-field';
$vars['header_classes'][$field]['class'][] = 'views-field-' . $vars['fields'][$field];
$vars['header_classes'][$field] = new Attribute($vars['header_classes'][$field]);
$class = $fields[$field]->element_label_classes(0);
if ($class) {
$vars['header_classes'][$field]['class'][] = $class;
// Add responsive header classes.
if (!empty($options['info'][$field]['responsive'])) {
$vars['header_classes'][$field]['class'][] = $options['info'][$field]['responsive'];
$responsive = TRUE;
}
// Add a CSS align class to each field if one was set
if (!empty($options['info'][$field]['align'])) {
$vars['header_classes'][$field]['class'][] = drupal_clean_css_identifier($options['info'][$field]['align']);
}
// Add a header label wrapper if one was selected.
if ($vars['header'][$field]) {
$element_label_type = $fields[$field]->element_label_type(TRUE, TRUE);
if ($element_label_type) {
$vars['header'][$field] = '<' . $element_label_type . '>' . $vars['header'][$field] . '</' . $element_label_type . '>';
}
}
}
// Add a CSS align class to each field if one was set
if (!empty($options['info'][$field]['align'])) {
$vars['fields'][$field] .= ' ' . drupal_clean_css_identifier($options['info'][$field]['align']);
}
// Render each field into its appropriate column.
foreach ($result as $num => $row) {
// Add field classes
$vars['field_classes'][$field][$num] = array();
if ($fields[$field]->options['element_default_classes']) {
$vars['field_classes'][$field][$num]['class'][] = 'views-field';
$vars['field_classes'][$field][$num]['class'][] = 'views-field-' . $vars['fields'][$field];
$vars['field_classes'][$field][$num] = new Attribute($vars['field_classes'][$field][$num]);
if ($classes = $fields[$field]->element_classes($num)) {
$vars['field_classes'][$field][$num]['class'][] = $classes;
// Add responsive header classes.
if (!empty($options['info'][$field]['responsive'])) {
$vars['field_classes'][$field][$num]['class'][] = $options['info'][$field]['responsive'];
}
if (!empty($fields[$field]) && empty($fields[$field]->options['exclude'])) {
Dries Buytaert
committed
$field_output = $handler->get_field($num, $field);
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
$element_type = $fields[$field]->element_type(TRUE, TRUE);
if ($element_type) {
$field_output = '<' . $element_type . '>' . $field_output . '</' . $element_type . '>';
}
// Don't bother with separators and stuff if the field does not show up.
if (empty($field_output) && !empty($vars['rows'][$num][$column])) {
continue;
}
// Place the field into the column, along with an optional separator.
if (!empty($vars['rows'][$num][$column])) {
if (!empty($options['info'][$column]['separator'])) {
$vars['rows'][$num][$column] .= filter_xss_admin($options['info'][$column]['separator']);
}
}
else {
$vars['rows'][$num][$column] = '';
}
$vars['rows'][$num][$column] .= $field_output;
}
}
// Remove columns if the option is hide empty column is checked and the field is not empty.
if (!empty($options['info'][$field]['empty_column'])) {
$empty = TRUE;
foreach ($vars['rows'] as $num => $columns) {
$empty &= empty($columns[$column]);
}
if ($empty) {
foreach ($vars['rows'] as $num => &$column_items) {
unset($column_items[$column]);
unset($vars['header'][$column]);
}
}
}
}
// Hide table header if all labels are empty.
if (!array_filter($vars['header'])) {
$vars['header'] = array();
}
$count = 0;
$vars['row_classes'] = array();
Daniel Wehner
committed
$vars['row_classes'][$num] = array();
$vars['row_classes'][$num]['class'][] = ($count++ % 2 == 0) ? 'odd' : 'even';
if ($num === 0) {
$vars['row_classes'][$num]['class'][] = 'views-row-first';
}
elseif ($num === (count($vars['rows']) - 1)) {
$vars['row_classes'][$num]['class'][] = 'views-row-last';
}
}
if ($row_class = $handler->get_row_class($num)) {
$vars['row_classes'][$num]['class'][] = $row_class;
$vars['row_classes'][$num] = new Attribute($vars['row_classes'][$num]);
$vars['attributes']['class'][] = 'views-table';
Dries Buytaert
committed
$vars['attributes']['class'][] = 'views-view-table';
if (empty($vars['rows']) && !empty($options['empty_table'])) {
$build = $view->display_handler->renderArea('empty');
$vars['rows'][0][0] = drupal_render($build);
$vars['row_classes'][0] = new Attribute();
// Calculate the amounts of rows with output.
$vars['field_classes'][0][0] = new Attribute(array(
'colspan' => count($vars['header']),
'class' => 'views-empty',
));
catch
committed
$vars['view']->element['#attached']['library'][] = array('system', 'drupal.tableheader');
Tim Plunkett
committed
$vars['attributes']['class'][] = "sticky-enabled";
$vars['attributes']['class'][] = 'cols-' . count($vars['header']);
if (!empty($handler->options['summary'])) {
$vars['attributes_array'] = array('summary' => $handler->options['summary']);
}
// If the table has headers and it should react responsively to columns hidden
// with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
// and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
if (count($vars['header']) && $responsive) {
catch
committed
$vars['view']->element['#attached']['library'][] = array('system', 'drupal.tableresponsive');
// Add 'responsive-enabled' class to the table to identify it for JS.
// This is needed to target tables constructed by this function.
$vars['attributes']['class'][] = 'responsive-enabled';
}
}
/**
* Display a view as a grid style.
*/
function template_preprocess_views_view_grid(&$vars) {
$view = $vars['view'];
$result = $view->result;
$options = $view->style_plugin->options;
$handler = $view->style_plugin;
$default_row_class = isset($options['default_row_class']) ? $options['default_row_class'] : TRUE;
$row_class_special = isset($options['row_class_special']) ? $options['row_class_special'] : TRUE;
$columns = $options['columns'];
Tim Plunkett
committed
$vars['attributes']['class'][] = 'views-view-grid cols-' . $columns;
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
$rows = array();
$row_indexes = array();
if ($options['alignment'] == 'horizontal') {
$row = array();
$col_count = 0;
$row_count = 0;
$count = 0;
foreach ($vars['rows'] as $row_index => $item) {
$count++;
$row[] = $item;
$row_indexes[$row_count][$col_count] = $row_index;
$col_count++;
if ($count % $columns == 0) {
$rows[] = $row;
$row = array();
$col_count = 0;
$row_count++;
}
}
if ($row) {
// Fill up the last line only if it's configured, but this is default.
if (!empty($handler->options['fill_single_line']) && count($rows)) {
for ($i = 0; $i < ($columns - $col_count); $i++) {
$row[] = '';
}
}
$rows[] = $row;
}
}
else {
$num_rows = floor(count($vars['rows']) / $columns);
// The remainders are the 'odd' columns that are slightly longer.
$remainders = count($vars['rows']) % $columns;
$row = 0;
$col = 0;
foreach ($vars['rows'] as $count => $item) {
$rows[$row][$col] = $item;
$row_indexes[$row][$col] = $count;
$row++;
if (!$remainders && $row == $num_rows) {
$row = 0;
$col++;
}
elseif ($remainders && $row == $num_rows + 1) {
$row = 0;
$col++;
$remainders--;
}
}
for ($i = 0; $i < count($rows[0]); $i++) {
// This should be string so that's okay :)
if (!isset($rows[count($rows) - 1][$i])) {
$rows[count($rows) - 1][$i] = '';
}
}
}
// Apply the row classes
foreach ($rows as $row_number => $row) {
$row_classes = array();
if ($default_row_class) {
$row_classes['class'][] = 'row-' . ($row_number + 1);
}
if ($row_class_special) {
if ($row_number == 0) {
$row_classes['class'][] = 'row-first';
}
if (count($rows) == ($row_number + 1)) {
$row_classes['class'][] = 'row-last';
$row_classes = new Attribute($row_classes);
foreach ($rows[$row_number] as $column_number => $item) {
$vars['column_classes'][$row_number][$column_number] = array();
$vars['column_classes'][$row_number][$column_number]['class'][] = 'col-' . ($column_number + 1);
}
if ($row_class_special) {
if ($column_number == 0) {
$vars['column_classes'][$row_number][$column_number]['class'][] = 'col-first';
}
elseif (count($rows[$row_number]) == ($column_number + 1)) {
$vars['column_classes'][$row_number][$column_number]['class'][] = 'col-last';
}
}
if (isset($row_indexes[$row_number][$column_number]) && $column_class = $view->style_plugin->get_row_class($row_indexes[$row_number][$column_number])) {
$vars['column_classes'][$row_number][$column_number]['class'][] = $column_class;
$vars['column_classes'][$row_number][$column_number] = new Attribute($vars['column_classes'][$row_number][$column_number]);
}
}
$vars['rows'] = $rows;
if (!empty($handler->options['summary'])) {
$vars['attributes_array'] = array('summary' => $handler->options['summary']);
}
// If the table has headers and it should react responsively to columns hidden
// with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
// and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
if (count($vars['header']) && $responsive) {
catch
committed
$vars['view']->element['#attached']['library'][] = array('system', 'drupal.tableresponsive');
// Add 'responsive-enabled' class to the table to identify it for JS.
// This is needed to target tables constructed by this function.
$vars['attributes']['class'][] = 'responsive-enabled';
}
}
/**
* Display the simple view of rows one after another
*/
function template_preprocess_views_view_unformatted(&$vars) {
$view = $vars['view'];
$rows = $vars['rows'];
$style = $view->style_plugin;
$options = $style->options;
Tim Plunkett
committed
$vars['row_classes'] = array();
$vars['classes'] = array();
$default_row_class = isset($options['default_row_class']) ? $options['default_row_class'] : FALSE;
$row_class_special = isset($options['row_class_special']) ? $options['row_class_special'] : FALSE;
// Set up striping values.
$count = 0;
$max = count($rows);
foreach ($rows as $id => $row) {
$vars['row_classes'][$id] = array();
$vars['row_classes'][$id]['class'][] = 'views-row';
$vars['row_classes'][$id]['class'][] = 'views-row-' . $count;
$vars['row_classes'][$id]['class'][] = 'views-row-' . ($count % 2 ? 'odd' : 'even');
$vars['row_classes'][$id]['class'][] = 'views-row-first';
$vars['row_classes'][$id]['class'][] = 'views-row-last';
}
}
if ($row_class = $view->style_plugin->get_row_class($id)) {
$vars['row_classes'][$id]['class'][] = $row_class;
$vars['row_classes'][$id] = new Attribute($vars['row_classes'][$id]);
}
}
/**
* Display the view as an HTML list element
*/
function template_preprocess_views_view_list(&$vars) {
$handler = $vars['view']->style_plugin;
// Fetch classes from handler options.
$class = explode(' ', $handler->options['class']);
Tim Plunkett
committed
$class = array_map('drupal_clean_css_identifier', $class);
// Fetch wrapper classes from handler options.
$wrapper_class = explode(' ', $handler->options['wrapper_class']);
Tim Plunkett
committed
$wrapper_class = array_map('drupal_clean_css_identifier', $wrapper_class);
// Initialize a new attribute class for $class.
$attributes = new Attribute(array('class' => $class));
// Initialize a new attribute class for $wrapper_class.
if ($wrapper_class) {
$wrapper_class = new Attribute(array('class' => $wrapper_class));
$vars['wrapper_prefix'] = '<div' . $wrapper_class . '>';
$vars['wrapper_suffix'] = '</div>';
}
$vars['list_type_prefix'] = '<' . $handler->options['type'] . $attributes . '>';
$vars['list_type_suffix'] = '</' . $handler->options['type'] . '>';
template_preprocess_views_view_unformatted($vars);
}
/**
* Preprocess an RSS feed
*/
function template_preprocess_views_view_rss(&$vars) {
global $base_url;
$view = &$vars['view'];
$options = &$vars['options'];
$items = &$vars['rows'];
$style = &$view->style_plugin;
Bram Goffings
committed
$config = config('system.site');
// The RSS 2.0 "spec" doesn't indicate HTML can be used in the description.
// We strip all HTML tags, but need to prevent double encoding from properly
// escaped source data (such as & becoming &amp;).
$vars['description'] = check_plain(decode_entities(strip_tags($style->get_description())));
Daniel Wehner
committed
if ($view->display_handler->getOption('sitename_title')) {
Dries Buytaert
committed
$title = $config->get('name');
Bram Goffings
committed
if ($slogan = $config->get('slogan')) {
$title .= ' - ' . $slogan;
}
}
else {
Damian Lee
committed
$title = $view->getTitle();
}
$vars['title'] = check_plain($title);
// Figure out which display which has a path we're using for this feed. If there isn't
// one, use the global $base_url
Daniel Wehner
committed
$link_display_id = $view->display_handler->getLinkDisplay();
if ($link_display_id && $display = $view->displayHandlers->get($link_display_id)) {
$path = $view->displayHandlers->get($link_display_id)->getPath();
Damian Lee
committed
$path = $view->getUrl(NULL, $path);
$url_options = array('absolute' => TRUE);
if (!empty($view->exposed_raw_input)) {
$url_options['query'] = $view->exposed_raw_input;
}
// Compare the link to the default home page; if it's the default home page, just use $base_url.
Bram Goffings
committed
if ($path == $config->get('page.front')) {
$path = '';
}
$vars['link'] = check_url(url($path, $url_options));
}
$vars['langcode'] = check_plain(language(LANGUAGE_TYPE_INTERFACE)->langcode);
$vars['namespaces'] = new Attribute($style->namespaces);
$vars['items'] = $items;
$vars['channel_elements'] = format_xml_elements($style->channel_elements);
// During live preview we don't want to output the header since the contents
// of the feed are being displayed inside a normal HTML page.
if (empty($vars['view']->live_preview)) {
Daniel Wehner
committed
$vars['view']->getResponse()->headers->set('Content-Type', 'application/rss+xml; charset=utf-8');
* Prepares variables for views RSS item templates.
*
* Default template: views-view-row-rss.html.twig.
*
* @param array $vars
* An associative array containing:
* - row: The raw results rows.
*/
function template_preprocess_views_view_row_rss(&$vars) {
$item = $vars['row'];
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
$vars['title'] = check_plain($item->title);
$vars['link'] = check_url($item->link);
$vars['description'] = check_plain($item->description);
$vars['item_elements'] = empty($item->elements) ? '' : format_xml_elements($item->elements);
}
/**
* Default theme function for all filter forms.
*/
function template_preprocess_views_exposed_form(&$vars) {
$form = &$vars['form'];
// Put all single checkboxes together in the last spot.
$checkboxes = '';
if (!empty($form['q'])) {
$vars['q'] = drupal_render($form['q']);
}
$vars['widgets'] = array();
foreach ($form['#info'] as $id => $info) {
// Set aside checkboxes.
if (isset($form[$info['value']]['#type']) && $form[$info['value']]['#type'] == 'checkbox') {
$checkboxes .= drupal_render($form[$info['value']]);
continue;
}
Dries Buytaert
committed
$widget = new stdClass();
// set up defaults so that there's always something there.
Damian Lee
committed
$widget->label = $widget->operator = $widget->widget = $widget->description = NULL;
$widget->id = isset($form[$info['value']]['#id']) ? $form[$info['value']]['#id'] : '';
Damian Lee
committed
if (!empty($info['label'])) {
$widget->label = check_plain($info['label']);
}
if (!empty($info['operator'])) {
$widget->operator = drupal_render($form[$info['operator']]);
}
Damian Lee
committed
$widget->widget = drupal_render($form[$info['value']]);
Damian Lee
committed
if (!empty($info['description'])) {
$widget->description = check_plain($info['description']);
}
$vars['widgets'][$id] = $widget;
}
// Wrap up all the checkboxes we set aside into a widget.
if ($checkboxes) {
Dries Buytaert
committed
$widget = new stdClass();
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// set up defaults so that there's always something there.
$widget->label = $widget->operator = $widget->widget = NULL;
$widget->id = 'checkboxes';
$widget->widget = $checkboxes;
$vars['widgets']['checkboxes'] = $widget;
}
if (isset($form['sort_by'])) {
$vars['sort_by'] = drupal_render($form['sort_by']);
$vars['sort_order'] = drupal_render($form['sort_order']);
}
if (isset($form['items_per_page'])) {
$vars['items_per_page'] = drupal_render($form['items_per_page']);
}
if (isset($form['offset'])) {
$vars['offset'] = drupal_render($form['offset']);
}
if (isset($form['reset'])) {
$vars['reset_button'] = drupal_render($form['reset']);
}
// This includes the submit button.
$vars['button'] = drupal_render_children($form);
}
/**
* Theme function for a View with form elements: replace the placeholders.