4 * Contains the base display plugin.
8 * @defgroup views_display_plugins Views' display plugins
10 * Display plugins control how Views interact with the rest of Drupal.
12 * They can handle creating Views from a Drupal page hook; they can
13 * handle creating Views from a Drupal block hook. They can also
14 * handle creating Views from an external module source, such as
15 * a Panels pane, or an insert view, or a CCK field type.
17 * @see hook_views_plugins
21 * The default display plugin handler. Display plugins handle options and
22 * basic mechanisms for different output methods.
24 * @ingroup views_display_plugins
26 class views_plugin_display
extends views_plugin
{
27 var
$handlers = array();
29 function init(&$view, &$display, $options = NULL
) {
31 $this->display
= &$display;
33 // Make some modifications:
34 if (!isset($options)) {
35 $options = $display->display_options
;
38 if ($this->is_default_display() && isset($options['defaults'])) {
39 unset($options['defaults']);
42 $this->unpack_options($this->options
, $options);
48 foreach ($this->handlers as
$type => $handlers) {
49 foreach ($handlers as
$id => $handler) {
50 if (is_object($handler)) {
51 $this->handlers
[$type][$id]->destroy();
56 if (isset($this->default_display
)) {
57 unset($this->default_display
);
62 * Determine if this display is the 'default' display which contains
65 function is_default_display() { return FALSE
; }
68 * Determine if this display uses exposed filters, so the view
69 * will know whether or not to build them.
71 function uses_exposed() {
72 if (!isset($this->has_exposed
)) {
73 foreach (array('field', 'filter') as
$type) {
74 foreach ($this->view
->$type as
$key => $handler) {
75 if ($handler->is_exposed()) {
76 // one is all we need; if we find it, return true.
77 $this->has_exposed
= TRUE
;
82 $this->has_exposed
= FALSE
;
85 return $this->has_exposed
;
89 * Determine if this display should display the exposed
90 * filters widgets, so the view will know whether or not
93 * Regardless of what this function
94 * returns, exposed filters will not be used nor
95 * displayed unless uses_exposed() returns TRUE.
97 function displays_exposed() {
102 * Does the display use AJAX?
104 function use_ajax() {
105 if (!empty($this->definition
['use ajax'])) {
106 return $this->get_option('use_ajax');
112 * Does the display have a pager enabled?
114 function use_pager() {
115 if (!empty($this->definition
['use pager'])) {
116 return $this->get_option('use_pager');
122 * Does the display have a more link enabled?
124 function use_more() {
125 if (!empty($this->definition
['use more'])) {
126 return $this->get_option('use_more');
132 * Does the display have custom link text?
134 function use_more_text() {
135 if (!empty($this->definition
['use more'])) {
136 return $this->get_option('use_more_text');
142 * Can this display accept attachments?
144 function accept_attachments() {
145 return !empty($this->definition
['accept attachments']);
149 * Allow displays to attach to other views.
151 function attach_to($display_id) { }
154 * Static member function to list which sections are defaultable
155 * and what items each section contains.
157 function defaultable_sections($section = NULL
) {
159 'access' => array('access'),
160 'cache' => array('cache'),
161 'title' => array('title'),
162 'header' => array('header', 'header_format', 'header_empty'),
163 'footer' => array('footer', 'footer_format', 'footer_empty'),
164 'empty' => array('empty', 'empty_format'),
165 'use_ajax' => array('use_ajax'),
166 'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
167 'use_pager' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
168 'use_more' => array('use_more', 'use_more_text'),
169 'link_display' => array('link_display'),
170 'distinct' => array('distinct'),
171 'exposed_block' => array('exposed_block'),
173 // Force these to cascade properly.
174 'style_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
175 'style_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
176 'row_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
177 'row_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
179 // These guys are special
180 'relationships' => array('relationships'),
181 'fields' => array('fields'),
182 'sorts' => array('sorts'),
183 'arguments' => array('arguments'),
184 'filters' => array('filters'),
187 if (!empty($sections[$section])) {
188 return $sections[$section];
197 * Set default options.
199 * Displays put their options in a different place than everything else; also
200 * displays spread their options out. We don't want to set defaults for
201 * items that are normally defaulted elsewhere.
203 function _set_option_defaults(&$storage, $options, $level = 0) {
204 foreach ($options as
$option => $definition) {
205 // If defaulted to elsewhere and we're not the default display, skip.
206 if ($level == 0 && !$this->is_default_display() && !empty($options['defaults']['default'][$option])) {
210 if (isset($definition['contains']) && is_array($definition['contains'])) {
211 $storage[$option] = array();
212 $this->_set_option_defaults($storage[$option], $definition['contains'], $level++);
215 $storage[$option] = isset($definition['default']) ?
$definition['default'] : NULL
;
220 function option_definition() {
228 'header_format' => TRUE
,
229 'header_empty' => TRUE
,
231 'footer_format' => TRUE
,
232 'footer_empty' => TRUE
,
234 'empty_format' => TRUE
,
237 'items_per_page' => TRUE
,
240 'pager_element' => TRUE
,
242 'use_more_text' => TRUE
,
244 'exposed_block' => TRUE
,
246 'link_display' => TRUE
,
248 'style_plugin' => TRUE
,
249 'style_options' => TRUE
,
250 'row_plugin' => TRUE
,
251 'row_options' => TRUE
,
253 'relationships' => TRUE
,
260 'relationships' => array(
261 'default' => array(),
262 'export' => 'export_item',
265 'default' => array(),
266 'export' => 'export_item',
269 'default' => array(),
270 'export' => 'export_item',
272 'arguments' => array(
273 'default' => array(),
274 'export' => 'export_item',
277 'default' => array(),
278 'export' => 'export_item',
282 'type' => array('default' => 'none'),
287 'type' => array('default' => 'none'),
292 'translatable' => TRUE
,
296 'translatable' => TRUE
,
298 'header_format' => array(
299 'default' => FILTER_FORMAT_DEFAULT
,
301 'header_empty' => array(
306 'translatable' => TRUE
,
308 'footer_format' => array(
309 'default' => FILTER_FORMAT_DEFAULT
,
311 'footer_empty' => array(
316 'translatable' => TRUE
,
318 'empty_format' => array(
319 'default' => FILTER_FORMAT_DEFAULT
,
324 'items_per_page' => array(
330 'use_pager' => array(
333 'pager_element' => array(
339 'use_more_text' => array(
341 'translatable' => TRUE
,
343 'link_display' => array(
350 'style_plugin' => array(
351 'default' => 'default',
353 'style_options' => array(
354 'default' => array(),
356 'row_plugin' => array(
357 'default' => 'fields',
359 'row_options' => array(
360 'default' => array(),
363 'exposed_block' => array(
368 if ($this->is_default_display()) {
369 unset($options['defaults']);
375 * Check to see if the display has a 'path' field.
377 * This is a pure function and not just a setting on the definition
378 * because some displays (such as a panel pane) may have a path based
379 * upon configuration.
381 * By default, displays do not have a path.
383 function has_path() { return FALSE
; }
386 * Check to see if the display has some need to link to another display.
388 * For the most part, displays without a path will use a link display. However,
389 * sometimes displays that have a path might also need to link to another display.
390 * This is true for feeds.
392 function uses_link_display() { return !$this->has_path(); }
395 * Check to see which display to use when creating links within
396 * a view using this display.
398 function get_link_display() {
399 $display_id = $this->get_option('link_display');
400 // If unknown, pick the first one.
401 if (empty($display_id) || empty($this->view
->display
[$display_id])) {
402 foreach ($this->view
->display as
$display_id => $display) {
403 if (!empty($display->handler
) && $display->handler
->has_path()) {
411 // fall-through returns NULL
415 * Return the base path to use for this display.
417 * This can be overridden for displays that do strange things
420 function get_path() {
421 if ($this->has_path()) {
422 return $this->get_option('path');
425 $display_id = $this->get_link_display();
426 if ($display_id && !empty($this->view
->display
[$display_id]) && is_object($this->view
->display
[$display_id]->handler
)) {
427 return $this->view
->display
[$display_id]->handler
->get_path();
432 * Check to see if the display needs a breadcrumb
434 * By default, displays do not need breadcrumbs
436 function uses_breadcrumb() { return FALSE
; }
439 * Determine if a given option is set to use the default display or the
443 * TRUE for the default display
445 function is_defaulted($option) {
446 return !$this->is_default_display() && !empty($this->default_display
) && !empty($this->options
['defaults'][$option]);
450 * Intelligently get an option either from this display or from the
451 * default display, if directed to do so.
453 function get_option($option) {
454 if ($this->is_defaulted($option)) {
455 return $this->default_display
->get_option($option);
458 if (array_key_exists($option, $this->options
)) {
459 return $this->options
[$option];
464 * Determine if the display's style uses fields.
466 function uses_fields() {
467 $plugin = $this->get_plugin();
469 return $plugin->uses_fields();
474 * Get the display or row plugin, if it exists.
476 function get_plugin($type = 'style', $name = NULL
) {
478 $name = $this->get_option($type .
'_plugin');
481 $plugin = views_get_plugin($type, $name);
483 $options = $this->get_option($type .
'_options');
484 $plugin->init($this->view
, $this->display
, $options);
490 * Get the access plugin
492 function get_access_plugin($name = NULL
) {
494 $access = $this->get_option('access');
495 $name = $access['type'];
498 $plugin = views_get_plugin('access', $name);
500 $plugin->init($this->view
, $this->display
);
506 * Get the cache plugin
508 function get_cache_plugin($name = NULL
) {
510 $cache = $this->get_option('cache');
511 $name = $cache['type'];
514 $plugin = views_get_plugin('cache', $name);
516 $plugin->init($this->view
, $this->display
);
522 * Get the handler object for a single handler.
524 function &get_handler($type, $id) {
525 if (!isset($this->handlers
[$type])) {
526 $this->get_handlers($type);
529 if (isset($this->handlers
[$type][$id])) {
530 return $this->handlers
[$type][$id];
533 // So we can return a reference.
539 * Get a full array of handlers for $type. This caches them.
541 function get_handlers($type) {
542 if (!isset($this->handlers
[$type])) {
543 $this->handlers
[$type] = array();
544 $types = views_object_types();
545 $plural = $types[$type]['plural'];
546 foreach ($this->get_option($plural) as
$id => $info) {
547 $handler = views_get_handler($info['table'], $info['field'], $type);
549 $handler->init($this->view
, $info);
550 $this->handlers
[$type][$id] = &$handler;
553 // Prevent reference problems.
558 return $this->handlers
[$type];
562 * Intelligently set an option either from this display or from the
563 * default display, if directed to do so.
565 function set_option($option, $value) {
566 if ($this->is_defaulted($option)) {
567 return $this->default_display
->set_option($option, $value);
570 // Set this in two places: On the handler where we'll notice it
571 // but also on the display object so it gets saved. This should
572 // only be a temporary fix.
573 $this->display
->display_options
[$option] = $value;
574 return $this->options
[$option] = $value;
578 * Set an option and force it to be an override.
580 function override_option($option, $value) {
581 $this->set_override($option, FALSE
);
582 $this->set_option($option, $value);
586 * Because forms may be split up into sections, this provides
587 * an easy URL to exactly the right section. Don't override this.
589 function option_link($text, $section, $class = '', $title = '') {
590 if (!empty($class)) {
591 $text = '<span>' .
$text .
'</span>';
595 $text = t('Broken field');
602 return l($text, 'admin/build/views/nojs/display/' .
$this->view
->name .
'/' .
$this->display
->id .
'/' .
$section, array('attributes' => array('class' => 'views-ajax-link ' .
$class, 'title' => $title), 'html' => TRUE
));
606 * Provide the default summary for options in the views UI.
608 * This output is returned as an array.
610 function options_summary(&$categories, &$options) {
611 $categories['basic'] = array(
612 'title' => t('Basic settings'),
615 $options['display_title'] = array(
616 'category' => 'basic',
617 'title' => t('Name'),
618 'value' => check_plain($this->display
->display_title
),
619 'desc' => t('Change the name of this display.'),
622 $title = strip_tags($this->get_option('title'));
627 $options['title'] = array(
628 'category' => 'basic',
629 'title' => t('Title'),
631 'desc' => t('Change the title that this display will use.'),
634 $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin'));
635 $style_title = empty($style_plugin['title']) ?
t('Missing style plugin') : $style_plugin['title'];
639 $options['style_plugin'] = array(
640 'category' => 'basic',
641 'title' => t('Style'),
642 'value' => $style_title,
643 'desc' => t('Change the style plugin.'),
646 // This adds a 'Settings' link to the style_options setting if the style has options.
647 if (!empty($style_plugin['uses options'])) {
648 $options['style_plugin']['links']['style_options'] = t('Change settings for this style');
651 if (!empty($style_plugin['uses row plugin'])) {
652 $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin'));
653 $row_title = empty($row_plugin['title']) ?
t('Missing style plugin') : $row_plugin['title'];
655 $options['row_plugin'] = array(
656 'category' => 'basic',
657 'title' => t('Row style'),
658 'value' => $row_title,
659 'desc' => t('Change the row plugin.'),
661 // This adds a 'Settings' link to the row_options setting if the row style has options.
662 if (!empty($row_plugin['uses options'])) {
663 $options['row_plugin']['links']['row_options'] = t('Change settings for this style');
666 if (!empty($this->definition
['use ajax'])) {
667 $options['use_ajax'] = array(
668 'category' => 'basic',
669 'title' => t('Use AJAX'),
670 'value' => $this->get_option('use_ajax') ?
t('Yes') : t('No'),
671 'desc' => t('Change whether or not this display will use AJAX.'),
675 if (!empty($this->definition
['use pager'])) {
676 $options['use_pager'] = array(
677 'category' => 'basic',
678 'title' => t('Use pager'),
679 'value' => $this->get_option('use_pager') ?
($this->get_option('use_pager') === 'mini' ?
t('Mini') : t('Yes')) : t('No'),
680 'desc' => t("Change this display's pager setting."),
684 $items = intval($this->get_option('items_per_page'));
685 $options['items_per_page'] = array(
686 'category' => 'basic',
687 'title' => $this->use_pager() ?
t('Items per page') : t('Items to display'),
688 'value' => $items ?
$items : t('Unlimited'),
689 'desc' => t('Change how many items to display.'),
692 if (!empty($this->definition
['use more'])) {
693 $options['use_more'] = array(
694 'category' => 'basic',
695 'title' => t('More link'),
696 'value' => $this->get_option('use_more') ?
t('Yes') : t('No'),
697 'desc' => t('Specify whether this display will provide a "more" link.'),
701 $options['distinct'] = array(
702 'category' => 'basic',
703 'title' => t('Distinct'),
704 'value' => $this->get_option('distinct') ?
t('Yes') : t('No'),
705 'desc' => t('Display only distinct items, without duplicates.'),
708 $access_plugin = $this->get_access_plugin();
709 if (!$access_plugin) {
710 // default to the no access control plugin.
711 $access_plugin = views_get_plugin('access', 'none');
714 $access_str = $access_plugin->summary_title();
716 $options['access'] = array(
717 'category' => 'basic',
718 'title' => t('Access'),
719 'value' => $access_str,
720 'desc' => t('Specify access control type for this display.'),
723 if (!empty($access_plugin->definition
['uses options'])) {
724 $options['access']['links']['access_options'] = t('Change settings for this access type.');
727 $cache_plugin = $this->get_cache_plugin();
728 if (!$cache_plugin) {
729 // default to the no cache control plugin.
730 $cache_plugin = views_get_plugin('cache', 'none');
733 $cache_str = $cache_plugin->summary_title();
735 $options['cache'] = array(
736 'category' => 'basic',
737 'title' => t('Caching'),
738 'value' => $cache_str,
739 'desc' => t('Specify caching type for this display.'),
742 if (!empty($cache_plugin->definition
['uses options'])) {
743 $options['cache']['links']['cache_options'] = t('Change settings for this caching type.');
746 if ($this->uses_link_display()) {
747 // Only show the 'link display' if there is more than one option.
749 foreach ($this->view
->display as
$display_id => $display) {
750 if (is_object($display->handler
) && $display->handler
->has_path()) {
759 $display_id = $this->get_link_display();
760 $link_display = empty($this->view
->display
[$display_id]) ?
t('None') : check_plain($this->view
->display
[$display_id]->display_title
);
761 $options['link_display'] = array(
762 'category' => 'basic',
763 'title' => t('Link display'),
764 'value' => $link_display,
765 'desc' => t('Specify which display this display will link to.'),
770 $options['exposed_block'] = array(
771 'category' => 'basic',
772 'title' => t('Exposed form in block'),
773 'value' => $this->get_option('exposed_block') ?
t('Yes') : t('No'),
774 'desc' => t('Allow the exposed form to appear in a block instead of the view.'),
777 foreach (array('header' => t('Header'), 'footer' => t('Footer'), 'empty' => t('Empty text')) as
$type => $name) {
778 if (!$this->get_option($type)) {
782 // A lot of code to get the name of the filter format.
783 $fmt_string = $this->get_option($type .
'_format');
784 if (empty($fmt_string)) {
785 $fmt_string = FILTER_FORMAT_DEFAULT
;
787 $format_val = filter_resolve_format($fmt_string);
788 $format = filter_formats($format_val);
790 $field = check_plain($format->name
);
793 $field = t('Unknown/missing format');
797 $options[$type] = array(
798 'category' => 'basic',
801 'desc' => t("Change this display's !name.", array('!name' => strtolower($name))),
805 $options['analyze-theme'] = array(
806 'category' => 'basic',
807 'title' => t('Theme'),
808 'value' => t('Information'),
809 'desc' => t('Get information on how to theme this display'),
814 * Provide the default form for setting options.
816 function options_form(&$form, &$form_state) {
817 if ($this->defaultable_sections($form_state['section'])) {
818 $this->add_override_button($form, $form_state, $form_state['section']);
820 $form['#title'] = check_plain($this->display
->display_title
) .
': ';
822 // Set the 'section' to hilite on the form.
823 // If it's the item we're looking at is pulling from the default display,
824 // reflect that. Don't use is_defaulted since we want it to show up even
825 // on the default display.
826 if (!empty($this->options
['defaults'][$form_state['section']])) {
827 $form['#section'] = 'default-' .
$form_state['section'];
830 $form['#section'] = $this->display
->id .
'-' .
$form_state['section'];
833 switch ($form_state['section']) {
834 case
'display_title':
835 $form['#title'] .
= t('The name of this display');
836 $form['display_title'] = array(
837 '#type' => 'textfield',
838 '#description' => t('This title will appear only in the administrative interface for the View.'),
839 '#default_value' => $this->display
->display_title
,
843 $form['#title'] .
= t('The title of this view');
844 $form['title'] = array(
845 '#type' => 'textfield',
846 '#description' => t('This title will be displayed with the view, wherever titles are normally displayed; i.e, as the page title, block title, etc.'),
847 '#default_value' => $this->get_option('title'),
851 $form['#title'] .
= t('Use AJAX when available to load this view');
852 $form['description'] = array(
853 '#prefix' => '<div class="description form-item">',
854 '#suffix' => '</div>',
855 '#value' => t('If set, this view will use an AJAX mechanism for paging, table sorting and exposed filters. This means the entire page will not refresh. It is not recommended that you use this if this view is the main content of the page as it will prevent deep linking to specific pages, but it is very useful for side content.'),
857 $form['use_ajax'] = array(
859 '#options' => array(1 => t('Yes'), 0 => t('No')),
860 '#default_value' => $this->get_option('use_ajax') ?
1 : 0,
864 $form['#title'] .
= t('Use a pager for this view');
865 $form['use_pager'] = array(
867 '#options' => array(TRUE
=> t('Full pager'), 'mini' => t('Mini pager'), 0 => t('No')),
868 '#default_value' => $this->get_option('use_pager'),
870 $form['pager_element'] = array(
871 '#type' => 'textfield',
872 '#title' => t('Pager element'),
873 '#description' => t("Unless you're experiencing problems with pagers related to this view, you should leave this at 0. If using multiple pagers on one page you may need to set this number to a higher value so as not to conflict within the ?page= array. Large values will add a lot of commas to your URLs, so avoid if possible."),
874 '#default_value' => intval($this->get_option('pager_element')),
877 case
'items_per_page':
878 $form['#title'] .
= $this->use_pager() ?
t('Items per page') : t('Items to display');
880 $form['items_per_page'] = array(
881 '#type' => 'textfield',
882 '#description' => t('The number of items to display per page. Enter 0 for no limit.'),
883 '#default_value' => intval($this->get_option('items_per_page')),
885 $form['offset'] = array(
886 '#type' => 'textfield',
887 '#title' => t('Offset'),
888 '#description' => t('The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed. Offset can not be used if items to display is 0; instead use a very large number there.'),
889 '#default_value' => intval($this->get_option('offset')),
893 $form['#title'] .
= t('Add a more link to the bottom of the display.');
894 $form['use_more'] = array(
895 '#type' => 'checkbox',
896 '#title' => t('Create more link'),
897 '#description' => t("This will add a more link to the bottom of this view, which will link to the page view. If you have more than one page view, the link will point to the display specified in 'Link display' above."),
898 '#default_value' => $this->get_option('use_more'),
900 $form['#title'] .
= t('Text to use for the more link.');
901 $form['use_more_text'] = array(
902 '#type' => 'textfield',
903 '#title' => t('More link text'),
904 '#description' => t("The text to display for the more link."),
905 '#default_value' => $this->get_option('use_more_text'),
909 $form['#title'] .
= t('Display only distinct items, without duplicates.');
910 $form['distinct'] = array(
911 '#type' => 'checkbox',
912 '#title' => t('Distinct'),
913 '#description' => t('This will make the view display only distinct items. If there are multiple identical items, each will be displayed only once. You can use this to try and remove duplicates from a view, though it does not always work. Note that this can slow queries down, so use it with caution.'),
914 '#default_value' => $this->get_option('distinct'),
918 $form['#title'] .
= t('Access restrictions');
919 $form['access'] = array(
920 '#prefix' => '<div class="clear-block">',
921 '#suffix' => '</div>',
925 $access = $this->get_option('access');
926 $form['access']['type'] = array(
928 '#options' => views_fetch_plugin_names('access'),
929 '#default_value' => $access['type'],
932 $access_plugin = views_fetch_plugin_data('access', $access['type']);
933 if (!empty($access_plugin['uses options'])) {
934 $form['markup'] = array(
935 '#prefix' => '<div class="form-item description">',
936 '#suffix' => '</div>',
937 '#value' => t('You may also adjust the !settings for the currently selected access restriction by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'access_options'))),
942 case
'access_options':
943 $access = $this->get_option('access');
944 $plugin = $this->get_access_plugin();
945 $form['#title'] .
= t('Access options');
947 $form['#help_topic'] = $plugin->definition
['help topic'];
949 $form['access_options'] = array(
952 $form['access_options']['type'] = array(
954 '#value' => $access['type'],
956 $plugin->options_form($form['access_options'], $form_state);
960 $form['#title'] .
= t('Caching');
961 $form['cache'] = array(
962 '#prefix' => '<div class="clear-block">',
963 '#suffix' => '</div>',
967 $cache = $this->get_option('cache');
968 $form['cache']['type'] = array(
970 '#options' => views_fetch_plugin_names('cache'),
971 '#default_value' => $cache['type'],
974 $cache_plugin = views_fetch_plugin_data('cache', $cache['type']);
975 if (!empty($cache_plugin['uses options'])) {
976 $form['markup'] = array(
977 '#prefix' => '<div class="form-item description">',
978 '#suffix' => '</div>',
979 '#value' => t('You may also adjust the !settings for the currently selected cache mechanism by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'cache_options'))),
983 case
'cache_options':
984 $cache = $this->get_option('cache');
985 $plugin = $this->get_cache_plugin();
986 $form['#title'] .
= t('Caching options');
988 $form['#help_topic'] = $plugin->definition
['help topic'];
990 $form['cache_options'] = array(
993 $form['cache_options']['type'] = array(
995 '#value' => $cache['type'],
997 $plugin->options_form($form['cache_options'], $form_state);
1001 $form['#title'] .
= t('Header');
1002 $form['header_empty'] = array(
1003 '#type' => 'checkbox',
1004 '#title' => t('Display even if view has no result'),
1005 '#default_value' => $this->get_option('header_empty'),
1007 $form['header'] = array(
1008 '#type' => 'textarea',
1009 '#default_value' => $this->get_option('header'),
1011 '#description' => t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional.'),
1014 $form['header_format'] = filter_form($this->get_option('header_format'), NULL
, array('header_format'));
1017 $form['#title'] .
= t('Footer');
1018 $form['footer_empty'] = array(
1019 '#type' => 'checkbox',
1020 '#title' => t('Display even if view has no result'),
1021 '#default_value' => $this->get_option('footer_empty'),
1023 $form['footer'] = array(
1024 '#type' => 'textarea',
1025 '#default_value' => $this->get_option('footer'),
1027 '#description' => t('Text to display beneath the view. May contain an explanation or links or whatever you like. Optional.'),
1030 $form['footer_format'] = filter_form($this->get_option('footer_format'), NULL
, array('footer_format'));
1033 $form['#title'] .
= t('Empty text');
1034 $form['empty'] = array(
1035 '#type' => 'textarea',
1036 '#default_value' => $this->get_option('empty'),
1038 '#description' => t('Text to display if the view has no results. Optional.'),
1041 $form['empty_format'] = filter_form($this->get_option('empty_format'), NULL
, array('empty_format'));
1043 case
'style_plugin':
1044 $form['#title'] .
= t('How should this view be styled');
1045 $form['#help_topic'] = 'style';
1046 $form['style_plugin'] = array(
1047 '#type' => 'radios',
1048 '#options' => views_fetch_plugin_names('style', $this->get_style_type(), array($this->view
->base_table
)),
1049 '#default_value' => $this->get_option('style_plugin'),
1050 '#description' => t('If the style you choose has settings, be sure to click the settings button that will appear next to it in the View summary.'),
1053 $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin'));
1054 if (!empty($style_plugin['uses options'])) {
1055 $form['markup'] = array(
1056 '#prefix' => '<div class="form-item description">',
1057 '#suffix' => '</div>',
1058 '#value' => t('You may also adjust the !settings for the currently selected style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'style_options'))),
1063 case
'style_options':
1064 $form['#title'] .
= t('Style options');
1066 $type = 'style_plugin';
1067 $name = $this->get_option('style_plugin');
1070 if (!isset($name)) {
1071 $name = $this->get_option('row_plugin');
1073 // if row, $style will be empty.
1074 if (empty($style)) {
1075 $form['#title'] .
= t('Row style options');
1076 $type = 'row_plugin';
1078 $plugin = $this->get_plugin(empty($style) ?
'row' : 'style');
1080 if (isset($plugin->definition
['help topic'])) {
1081 $form['#help_topic'] = $plugin->definition
['help topic'];
1083 $form[$form_state['section']] = array(
1086 $plugin->options_form($form[$form_state['section']], $form_state);
1090 $form['#title'] .
= t('How should each row in this view be styled');
1091 $form['#help_topic'] = 'style-row';
1092 $form['row_plugin'] = array(
1093 '#type' => 'radios',
1094 '#options' => views_fetch_plugin_names('row', $this->get_style_type(), array($this->view
->base_table
)),
1095 '#default_value' => $this->get_option('row_plugin'),
1098 $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin'));
1099 if (!empty($row_plugin['uses options'])) {
1100 $form['markup'] = array(
1101 '#prefix' => '<div class="form-item description">',
1102 '#suffix' => '</div>',
1103 '#value' => t('You may also adjust the !settings for the currently selected row style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'row_options'))),
1108 case
'link_display':
1109 $form['#title'] .
= t('Which display to use for path');
1110 foreach ($this->view
->display as
$display_id => $display) {
1111 if ($display->handler
->has_path()) {
1112 $options[$display_id] = $display->display_title
;
1115 $form['link_display'] = array(
1116 '#type' => 'radios',
1117 '#options' => $options,
1118 '#description' => t("Which display to use to get this display's path for things like summary links, rss feed links, more links, etc."),
1119 '#default_value' => $this->get_link_display(),
1122 case
'analyze-theme':
1123 $form['#title'] .
= t('Theming information');
1124 $form['#help_topic'] = 'analyze-theme';
1126 if (isset($_POST['theme'])) {
1127 $this->view
->theme
= $_POST['theme'];
1129 else if (empty($this->view
->theme
)) {
1130 $this->view
->theme
= variable_get('theme_default', 'garland');
1133 global $custom_theme;
1134 $custom_theme = $this->view
->theme
;
1138 // Get theme functions for the display. Note that some displays may
1139 // not have themes. The 'feed' display, for example, completely
1140 // delegates to the style.
1141 if (!empty($this->definition
['theme'])) {
1142 $funcs[] = $this->option_link(t('Display output'), 'analyze-theme-display') .
': ' .
$this->format_themes($this->theme_functions());
1143 $themes = $this->additional_theme_functions();
1145 foreach ($themes as
$theme) {
1146 $funcs[] = $this->option_link(t('Alternative display output'), 'analyze-theme-display') .
': ' .
$this->format_themes($theme);
1151 $plugin = $this->get_plugin();
1153 $funcs[] = $this->option_link(t('Style output'), 'analyze-theme-style') .
': ' .
$this->format_themes($plugin->theme_functions(), $plugin->additional_theme_functions());
1154 $themes = $plugin->additional_theme_functions();
1156 foreach ($themes as
$theme) {
1157 $funcs[] = $this->option_link(t('Alternative style'), 'analyze-theme-style') .
': ' .
$this->format_themes($theme);
1161 if ($plugin->uses_row_plugin()) {
1162 $row_plugin = $this->get_plugin('row');
1164 $funcs[] = $this->option_link(t('Row style output'), 'analyze-theme-row') .
': ' .
$this->format_themes($row_plugin->theme_functions());
1165 $themes = $row_plugin->additional_theme_functions();
1167 foreach ($themes as
$theme) {
1168 $funcs[] = $this->option_link(t('Alternative row style'), 'analyze-theme-row') .
': ' .
$this->format_themes($theme);
1174 if ($plugin->uses_fields()) {
1175 foreach ($this->get_handlers('field') as
$id => $handler) {
1176 $funcs[] = $this->option_link(t('Field @field (ID: @id)', array('@field' => $handler->ui_name(), '@id' => $id)), 'analyze-theme-field') .
': ' .
$this->format_themes($handler->theme_functions());
1181 $form['important'] = array(
1182 '#prefix' => '<div class="form-item description">',
1183 '#suffix' => '</div>',
1184 '#value' => '<p>' .
t('This section lists all possible templates for the display plugin and for the style plugins, ordered roughly from the least specific to the most specific. The active template for each plugin -- which is the most specific template found on the system -- is highlighted in bold.') .
'</p>',
1187 foreach (list_themes() as
$key => $theme) {
1188 $options[$key] = $theme->info
['name'];
1191 $form['box'] = array(
1192 '#prefix' => '<div class="container-inline">',
1193 '#suffix' => '</div>',
1195 $form['box']['theme'] = array(
1196 '#type' => 'select',
1197 '#options' => $options,
1198 '#default_value' => $this->view
->theme
,
1201 $form['box']['change'] = array(
1202 '#type' => 'submit',
1203 '#value' => t('Change theme'),
1204 '#submit' => array('views_ui_edit_display_form_change_theme'),
1207 $form['analysis'] = array(
1208 '#prefix' => '<div class="form-item">',
1209 '#suffix' => '</div>',
1210 '#value' => theme('item_list', $funcs),
1213 $form['rescan_button'] = array(
1214 '#prefix' => '<div class="form-item">',
1215 '#suffix' => '</div>',
1217 $form['rescan_button']['button'] = array(
1218 '#type' => 'submit',
1219 '#value' => t('Rescan template files'),
1220 '#submit' => array('views_ui_config_item_form_rescan'),
1222 $form['rescan_button']['markup'] = array(
1223 '#prefix' => '<div class="description">',
1224 '#suffix' => '</div>',
1225 '#value' => t("<strong>Important!</strong> When adding, removing, or renaming template files, it is necessary to make Drupal aware of the changes by making it rescan the files on your system. By clicking this button you clear Drupal's theme registry and thereby trigger this rescanning process. The highlighted templates above will then reflect the new state of your system."),
1228 $form_state['ok_button'] = TRUE
;
1230 case
'analyze-theme-display':
1231 $form['#title'] .
= t('Theming information (display)');
1232 $output = '<p>' .
t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) .
'</p>';
1234 if (empty($this->definition
['theme'])) {
1235 $output .
= t('This display has no theming information');
1238 $output .
= '<p>' .
t('This is the default theme template used for this display.') .
'</p>';
1239 $output .
= '<pre>' .
check_plain(file_get_contents('./' .
$this->definition
['theme path'] .
'/' .
strtr($this->definition
['theme'], '_', '-') .
'.tpl.php')) .
'</pre>';
1242 if (!empty($this->definition
['additional themes'])) {
1243 foreach ($this->definition
['additional themes'] as
$theme => $type) {
1244 $output .
= '<p>' .
t('This is an alternative template for this display.') .
'</p>';
1245 $output .
= '<pre>' .
check_plain(file_get_contents('./' .
$this->definition
['theme path'] .
'/' .
strtr($theme, '_', '-') .
'.tpl.php')) .
'</pre>';
1249 $form['analysis'] = array(
1250 '#prefix' => '<div class="form-item">',
1251 '#suffix' => '</div>',
1252 '#value' => $output,
1255 $form_state['ok_button'] = TRUE
;
1257 case
'analyze-theme-style':
1258 $form['#title'] .
= t('Theming information (style)');
1259 $output = '<p>' .
t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) .
'</p>';
1261 $plugin = $this->get_plugin();
1263 if (empty($plugin->definition
['theme'])) {
1264 $output .
= t('This display has no style theming information');
1267 $output .
= '<p>' .
t('This is the default theme template used for this style.') .
'</p>';
1268 $output .
= '<pre>' .
check_plain(file_get_contents('./' .
$plugin->definition
['theme path'] .
'/' .
strtr($plugin->definition
['theme'], '_', '-') .
'.tpl.php')) .
'</pre>';
1271 if (!empty($plugin->definition
['additional themes'])) {
1272 foreach ($plugin->definition
['additional themes'] as
$theme => $type) {
1273 $output .
= '<p>' .
t('This is an alternative template for this style.') .
'</p>';
1274 $output .
= '<pre>' .
check_plain(file_get_contents('./' .
$plugin->definition
['theme path'] .
'/' .
strtr($theme, '_', '-') .
'.tpl.php')) .
'</pre>';
1278 $form['analysis'] = array(
1279 '#prefix' => '<div class="form-item">',
1280 '#suffix' => '</div>',
1281 '#value' => $output,
1284 $form_state['ok_button'] = TRUE
;
1286 case
'analyze-theme-row':
1287 $form['#title'] .
= t('Theming information (row style)');
1288 $output = '<p>' .
t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) .
'</p>';
1290 $plugin = $this->get_plugin('row');
1292 if (empty($plugin->definition
['theme'])) {
1293 $output .
= t('This display has no row style theming information');
1296 $output .
= '<p>' .
t('This is the default theme template used for this row style.') .
'</p>';
1297 $output .
= '<pre>' .
check_plain(file_get_contents('./' .
$plugin->definition
['theme path'] .
'/' .
strtr($plugin->definition
['theme'], '_', '-') .
'.tpl.php')) .
'</pre>';
1300 if (!empty($plugin->definition
['additional themes'])) {
1301 foreach ($plugin->definition
['additional themes'] as
$theme => $type) {
1302 $output .
= '<p>' .
t('This is an alternative template for this row style.') .
'</p>';
1303 $output .
= '<pre>' .
check_plain(file_get_contents('./' .
$plugin->definition
['theme path'] .
'/' .
strtr($theme, '_', '-') .
'.tpl.php')) .
'</pre>';
1307 $form['analysis'] = array(
1308 '#prefix' => '<div class="form-item">',
1309 '#suffix' => '</div>',
1310 '#value' => $output,
1313 $form_state['ok_button'] = TRUE
;
1315 case
'analyze-theme-field':
1316 $form['#title'] .
= t('Theming information (row style)');
1317 $output = '<p>' .
t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) .
'</p>';
1319 $output .
= '<p>' .
t('This is the default theme template used for this row style.') .
'</p>';
1321 // Field templates aren't registered the normal way...and they're always
1322 // this one, anyhow.
1323 $output .
= '<pre>' .
check_plain(file_get_contents(drupal_get_path('module', 'views') .
'/theme/views-view-field.tpl.php')) .
'</pre>';
1325 $form['analysis'] = array(
1326 '#prefix' => '<div class="form-item">',
1327 '#suffix' => '</div>',
1328 '#value' => $output,
1330 $form_state['ok_button'] = TRUE
;
1333 case
'exposed_block':
1334 $form['#title'] .
= t('Put the exposed form in a block');
1335 $form['description'] = array(
1336 '#prefix' => '<div class="description form-item">',
1337 '#suffix' => '</div>',
1338 '#value' => t('If set, any exposed widgets will not appear with this view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you.'),
1340 $form['exposed_block'] = array(
1341 '#type' => 'radios',
1342 '#options' => array(1 => t('Yes'), 0 => t('No')),
1343 '#default_value' => $this->get_option('exposed_block') ?
1 : 0,
1350 * Format a list of theme templates for output by the theme info helper.
1352 function format_themes($themes) {
1353 $registry = theme_get_registry();
1355 // Run through the theme engine variables, if necessary
1356 global $theme_engine;
1357 $extension = '.tpl.php';
1358 if (isset($theme_engine)) {
1359 $extension_function = $theme_engine .
'_extension';
1360 if (function_exists($extension_function)) {
1361 $extension = $extension_function();
1367 foreach ($themes as
$theme) {
1368 $template = strtr($theme, '_', '-') .
$extension;
1369 if (!$picked && !empty($registry[$theme])) {
1370 $template_path = isset($registry[$theme]['path']) ?
$registry[$theme]['path'] .
'/' : './';
1371 if (file_exists($template_path .
$template)) {
1372 $hint = t('File found in folder @template-path', array('@template-path' => $template_path));
1373 $template = '<strong title="'.
$hint .
'">' .
$template .
'</strong>';
1376 $template = '<strong class="error">' .
$template .
' ' .
t('(File not found, in folder @template-path)', array('@template-path' => $template_path)) .
'</strong>';
1380 $fixed[] = $template;
1383 return implode(', ', array_reverse($fixed));
1387 * Validate the options form.
1389 function options_validate(&$form, &$form_state) {
1390 switch ($form_state['section']) {
1391 case
'style_options':
1394 // if row, $style will be empty.
1395 $plugin = $this->get_plugin(empty($style) ?
'row' : 'style');
1397 $plugin->options_validate($form[$form_state['section']], $form_state);
1400 case
'access_options':
1401 $plugin = $this->get_access_plugin();
1403 $plugin->options_validate($form['access_options'], $form_state);
1406 case
'cache_options':
1407 $plugin = $this->get_cache_plugin();
1409 $plugin->options_validate($form['cache_options'], $form_state);
1416 * Perform any necessary changes to the form values prior to storage.
1417 * There is no need for this function to actually store the data.
1419 function options_submit(&$form, &$form_state) {
1420 // Not sure I like this being here, but it seems (?) like a logical place.
1421 $cache_plugin = $this->get_cache_plugin();
1422 if ($cache_plugin) {
1423 $cache_plugin->cache_flush();
1426 $section = $form_state['section'];
1428 case
'display_title':
1429 $this->display
->display_title
= $form_state['values']['display_title'];
1432 $access = $this->get_option('access');
1433 if ($access['type'] != $form_state['values']['access']['type']) {
1434 $plugin = views_get_plugin('access', $form_state['values']['access']['type']);
1436 $access = array('type' => $form_state['values']['access']['type']);
1437 $plugin->option_defaults($access);
1438 $this->set_option('access', $access);
1439 if (!empty($plugin->definition
['uses options'])) {
1440 views_ui_add_form_to_stack('display', $this->view
, $this->display
->id
, array('access_options'));
1446 case
'access_options':
1447 $plugin = views_get_plugin('access', $form_state['values'][$section]['type']);
1449 $plugin->options_submit($form['access_options'], $form_state);
1450 $this->set_option('access', $form_state['values'][$section]);
1454 $cache = $this->get_option('cache');
1455 if ($cache['type'] != $form_state['values']['cache']['type']) {
1456 $plugin = views_get_plugin('cache', $form_state['values']['cache']['type']);
1458 $cache = array('type' => $form_state['values']['cache']['type']);
1459 $plugin->option_defaults($cache);
1460 $this->set_option('cache', $cache);
1461 if (!empty($plugin->definition
['uses options'])) {
1462 views_ui_add_form_to_stack('display', $this->view
, $this->display
->id
, array('cache_options'));
1468 case
'cache_options':
1469 $plugin = views_get_plugin('cache', $form_state['values'][$section]['type']);
1471 $plugin->options_submit($form['cache_options'], $form_state);
1472 $this->set_option('cache', $form_state['values'][$section]);
1476 case
'link_display':
1477 $this->set_option($section, $form_state['values'][$section]);
1480 $this->set_option($section, (bool
)$form_state['values'][$section]);
1483 $this->set_option($section, $form_state['values'][$section]);
1484 $this->set_option('pager_element', intval($form_state['values']['pager_element']));
1486 case
'items_per_page':
1487 $this->set_option($section, intval($form_state['values'][$section]));
1488 $this->set_option('offset', intval($form_state['values']['offset']));
1491 $this->set_option($section, intval($form_state['values'][$section]));
1492 $this->set_option('use_more_text', $form_state['values']['use_more_text']);
1494 $this->set_option($section, $form_state['values'][$section]);
1497 // This if prevents resetting options to default if they don't change
1499 if ($this->get_option($section) != $form_state['values'][$section]) {
1500 $plugin = views_get_plugin('row', $form_state['values'][$section]);
1502 $this->set_option($section, $form_state['values'][$section]);
1503 $this->set_option('row_options', array());
1505 // send ajax form to options page if we use it.
1506 if (!empty($plugin->definition
['uses options'])) {
1507 views_ui_add_form_to_stack('display', $this->view
, $this->display
->id
, array('row_options'));
1512 case
'style_plugin':
1513 // This if prevents resetting options to default if they don't change
1515 if ($this->get_option($section) != $form_state['values'][$section]) {
1516 $plugin = views_get_plugin('style', $form_state['values'][$section]);
1518 $this->set_option($section, $form_state['values'][$section]);
1519 $this->set_option('style_options', array());
1520 // send ajax form to options page if we use it.
1521 if (!empty($plugin->definition
['uses options'])) {
1522 views_ui_add_form_to_stack('display', $this->view
, $this->display
->id
, array('style_options'));
1527 case
'style_options':
1530 // if row, $style will be empty.
1531 $plugin = $this->get_plugin(empty($style) ?
'row' : 'style');
1533 $plugin->options_submit($form[$section], $form_state);
1535 $this->set_option($section, $form_state['values'][$section]);
1540 $this->set_option($section, $form_state['values'][$section]);
1541 $this->set_option($section .
'_format', $form_state['values'][$section .
'_format']);
1542 if ($section != 'empty') {
1543 $this->set_option($section .
'_empty', $form_state['values'][$section .
'_empty']);
1546 case
'exposed_block':
1547 $this->set_option($section, (bool
) $form_state['values'][$section]);
1553 * Add an override button for a given section, allowing the user to
1554 * change whether this info is stored on the default display or on
1555 * the current display.
1557 function add_override_button(&$form, &$form_state, $section) {
1558 if ($this->is_default_display()) {
1562 $form['override'] = array(
1563 '#prefix' => '<div class="views-override clear-block">',
1564 '#suffix' => '</div>',
1566 if ($this->is_defaulted($section)) {
1567 $form['override']['button'] = array(
1568 '#type' => 'submit',
1569 '#value' => t('Override'),
1570 '#submit' => array('views_ui_edit_display_form_override'),
1572 $form['override']['markup'] = array(
1573 '#prefix' => '<div class="description">',
1574 '#value' => theme('advanced_help_topic', 'views', 'overrides') .
t('Status: using default values.'),
1575 '#suffix' => '</div>',
1578 $form_state['update_name'] = t('Update default display');
1581 $form['override']['button'] = array(
1582 '#type' => 'submit',
1583 '#value' => t('Use default'),
1584 '#submit' => array('views_ui_edit_display_form_override'),
1586 $form['override']['markup'] = array(
1587 '#prefix' => '<div class="description">',
1588 '#value' => theme('advanced_help_topic', 'views', 'overrides') .
t('Status: using overridden values.'),
1589 '#suffix' => '</div>',
1592 $form_state['update_name'] = NULL
;
1597 * If override/revert was clicked, perform the proper toggle.
1599 function options_override($form, &$form_state) {
1600 $this->set_override($form_state['section']);
1604 * Flip the override setting for the given section.
1606 function set_override($section, $new_state = NULL
) {
1607 $options = $this->defaultable_sections($section);
1612 if (!isset($new_state)) {
1613 $new_state = empty($this->options
['defaults'][$section]);
1616 // For each option that is part of this group, fix our settings.
1617 foreach ($options as
$option) {
1619 // Revert to defaults.
1620 unset($this->options
[$option]);
1621 unset($this->display
->display_options
[$option]);
1624 // copy existing values into our display.
1625 $this->options
[$option] = $this->get_option($option);
1626 $this->display
->display_options
[$option] = $this->options
[$option];
1628 $this->options
['defaults'][$option] = $new_state;
1629 $this->display
->display_options
['defaults'][$option] = $new_state;
1634 * Inject anything into the query that the display handler needs.
1637 // Make the query distinct if the option was set.
1638 if ($this->get_option('distinct')) {
1639 $this->view
->query
->set_distinct();
1644 * Not all display plugins will support filtering
1646 function render_filters() { }
1649 * Render the 'more' link
1651 function render_more_link() {
1652 if ($this->use_more() && $this->view
->total_rows
> $this->view
->pager
['items_per_page']) {
1653 $path = $this->get_path();
1655 $path = $this->view
->get_url(NULL
, $path);
1656 $url_options = array();
1657 if (!empty($this->view
->exposed_raw_input
)) {
1658 $url_options['query'] = $this->view
->exposed_raw_input
;
1660 $theme = views_theme_functions('views_more', $this->view
, $this->display
);
1661 $path = check_url(url($path, $url_options));
1662 return theme($theme, $path, $this->use_more_text());
1668 * Render a text area, using the proper format.
1670 function render_textarea($area) {
1671 static
$formats = array();
1673 $value = $this->get_option($area);
1674 // Check to make sure the filter format exists; if not, we don't
1675 // display anything.
1676 $format = filter_resolve_format($this->get_option($area .
'_format'));
1678 if (!array_key_exists($format, $formats)) {
1679 $formats[$format] = db_result(db_query("SELECT name FROM {filter_formats} WHERE format = %d", $format));
1682 if (!$formats[$format]) {
1687 return check_markup($value, $format, FALSE
);
1692 * Render the header of the view.
1694 function render_header() {
1695 if (!empty($this->view
->result
) || $this->get_option('header_empty')) {
1696 return $this->render_textarea('header');
1701 * Render the footer of the view.
1703 function render_footer() {
1704 if (!empty($this->view
->result
) || $this->get_option('footer_empty')) {
1705 return $this->render_textarea('footer');
1710 * Render the empty text of the view.
1712 function render_empty() { return $this->render_textarea('empty'); }
1714 * If this display creates a block, implement one of these.
1716 function hook_block($op = 'list', $delta = 0, $edit = array()) { return array(); }
1719 * If this display creates a page with a menu item, implement it here.
1721 function hook_menu() { return array(); }
1724 * Render this display.
1727 return theme($this->theme_functions(), $this->view
);
1731 * Determine if the user has access to this display of the view.
1733 function access($account = NULL
) {
1734 if (!isset($account)) {
1740 if (user_access('access all views', $account)) {
1744 $plugin = $this->get_access_plugin();
1746 return $plugin->access($account);
1749 // fallback to all access if no plugin.
1754 * Set up any variables on the view prior to execution. These are separated
1755 * from execute because they are extremely common and unlikely to be
1756 * overridden on an individual display.
1758 function pre_execute() {
1759 $this->view
->set_use_ajax($this->use_ajax());
1760 // Copy pager information from the display.
1761 $this->view
->set_use_pager($this->use_pager());
1762 $this->view
->set_pager_element($this->get_option('pager_element'));
1763 $this->view
->set_items_per_page($this->get_option('items_per_page'));
1764 $this->view
->set_offset($this->get_option('offset'));
1765 if ($this->use_more()) {
1766 $this->view
->get_total_rows
= TRUE
;
1771 * When used externally, this is how a view gets run and returns
1772 * data in the format required.
1774 * The base class cannot be executed.
1776 function execute() { }
1779 * Fully render the display for the purposes of a live preview or
1780 * some other AJAXy reason.
1782 function preview() { return $this->view
->render(); }
1785 * Displays can require a certain type of style plugin. By default, they will
1788 function get_style_type() { return 'normal'; }
1791 * Make sure the display and all associated handlers are valid.
1794 * Empty array if the display is valid; an array of error strings if it is not.
1796 function validate() {
1798 // Make sure displays that use fields HAVE fields.
1799 if ($this->uses_fields()) {
1801 foreach ($this->get_handlers('field') as
$field) {
1802 if (empty($field->options
['exclude'])) {
1808 $errors[] = t('Display "@display" uses fields but there are none defined for it or all are excluded.', array('@display' => $this->display
->display_title
));
1812 if ($this->has_path() && !$this->get_option('path')) {
1813 $errors[] = t('Display "@display" uses a path but the path is undefined.', array('@display' => $this->display
->display_title
));
1816 // Validate style plugin
1817 $style = $this->get_plugin();
1818 if (empty($style)) {
1819 $errors[] = t('Display "@display" has an invalid style plugin.', array('@display' => $this->display
->display_title
));
1822 $result = $style->validate();
1823 if (!empty($result) && is_array($result)) {
1824 $errors = array_merge($errors, $result);
1828 // Validate handlers
1829 foreach (views_object_types() as
$type => $info) {
1830 foreach ($this->get_handlers($type) as
$handler) {
1831 $result = $handler->validate();
1832 if (!empty($result) && is_array($result)) {
1833 $errors = array_merge($errors, $result);
1842 * Provide the block system with any exposed widget blocks for this display.
1844 function get_special_blocks() {
1845 $delta = '-exp-' .
$this->view
->name .
'-' .
$this->display
->id
;
1846 $desc = t('Exposed form: @view-@display_id', array('@view' => $this->view
->name
, '@display_id' => $this->display
->id
));
1856 * Render any special blocks provided for this display.
1858 function view_special_blocks($type) {
1859 if ($type == '-exp') {
1860 // avoid interfering with the admin forms.
1861 if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views') {
1864 $this->view
->init_handlers();
1866 'content' => $this->view
->render_exposed_form(TRUE
),