[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/views/plugins/ -> views_plugin_display.inc (source)

   1  <?php
   2  // $Id: views_plugin_display.inc,v 1.27.2.13 2010/06/17 02:46:53 merlinofchaos Exp $
   3  /**
   4   * @file
   5   * Contains the base display plugin.
   6   */
   7  
   8  /**
   9   * @defgroup views_display_plugins Views' display plugins
  10   * @{
  11   * Display plugins control how Views interact with the rest of Drupal.
  12   *
  13   * They can handle creating Views from a Drupal page hook; they can
  14   * handle creating Views from a Drupal block hook. They can also
  15   * handle creating Views from an external module source, such as
  16   * a Panels pane, or an insert view, or a CCK field type.
  17   *
  18   * @see hook_views_plugins
  19   */
  20  
  21  /**
  22   * The default display plugin handler. Display plugins handle options and
  23   * basic mechanisms for different output methods.
  24   *
  25   * @ingroup views_display_plugins
  26   */
  27  class views_plugin_display extends views_plugin {
  28    var $handlers = array();
  29  
  30    function init(&$view, &$display, $options = NULL) {
  31      $this->view = &$view;
  32      $this->display = &$display;
  33  
  34      // Make some modifications:
  35      if (!isset($options)) {
  36        $options = $display->display_options;
  37      }
  38  
  39      if ($this->is_default_display() && isset($options['defaults'])) {
  40        unset($options['defaults']);
  41      }
  42  
  43      $this->unpack_options($this->options, $options);
  44    }
  45  
  46    function destroy() {
  47      parent::destroy();
  48  
  49      foreach ($this->handlers as $type => $handlers) {
  50        foreach ($handlers as $id => $handler) {
  51          if (is_object($handler)) {
  52            $this->handlers[$type][$id]->destroy();
  53          }
  54        }
  55      }
  56  
  57      if (isset($this->default_display)) {
  58        unset($this->default_display);
  59      }
  60    }
  61  
  62    /**
  63     * Determine if this display is the 'default' display which contains
  64     * fallback settings
  65     */
  66    function is_default_display() { return FALSE; }
  67  
  68    /**
  69     * Determine if this display uses exposed filters, so the view
  70     * will know whether or not to build them.
  71     */
  72    function uses_exposed() {
  73      if (!isset($this->has_exposed)) {
  74        foreach (array('field', 'filter') as $type) {
  75          foreach ($this->view->$type as $key => $handler) {
  76            if ($handler->is_exposed()) {
  77              // one is all we need; if we find it, return true.
  78              $this->has_exposed = TRUE;
  79              return TRUE;
  80            }
  81          }
  82        }
  83        $this->has_exposed = FALSE;
  84      }
  85  
  86      return $this->has_exposed;
  87    }
  88  
  89    /**
  90     * Determine if this display should display the exposed
  91     * filters widgets, so the view will know whether or not
  92     * to render them.
  93     *
  94     * Regardless of what this function
  95     * returns, exposed filters will not be used nor
  96     * displayed unless uses_exposed() returns TRUE.
  97     */
  98    function displays_exposed() {
  99      return TRUE;
 100    }
 101  
 102    /**
 103     * Does the display use AJAX?
 104     */
 105    function use_ajax() {
 106      if (!empty($this->definition['use ajax'])) {
 107        return $this->get_option('use_ajax');
 108      }
 109      return FALSE;
 110    }
 111  
 112    /**
 113     * Does the display have a pager enabled?
 114     */
 115    function use_pager() {
 116      if (!empty($this->definition['use pager'])) {
 117        return $this->get_option('use_pager');
 118      }
 119      return FALSE;
 120    }
 121  
 122    /**
 123     * Does the display render the pager if it has it enabled?
 124     */
 125    function render_pager() {
 126      return $this->use_pager();
 127    }
 128  
 129    /**
 130     * Does the display have a more link enabled?
 131     */
 132    function use_more() {
 133      if (!empty($this->definition['use more'])) {
 134        return $this->get_option('use_more');
 135      }
 136      return FALSE;
 137    }
 138  
 139    /**
 140     * Should the enabled display more link be shown when no more items?
 141     */
 142    function use_more_always() {
 143      if (!empty($this->definition['use more'])) {
 144        return $this->get_option('use_more_always');
 145      }
 146      return FALSE;
 147    }
 148  
 149    /**
 150     * Does the display have custom link text?
 151     */
 152    function use_more_text() {
 153      if (!empty($this->definition['use more'])) {
 154        return $this->get_option('use_more_text');
 155      }
 156      return FALSE;
 157    }
 158  
 159    /**
 160     * Can this display accept attachments?
 161     */
 162    function accept_attachments() {
 163      return !empty($this->definition['accept attachments']);
 164    }
 165  
 166    /**
 167     * Allow displays to attach to other views.
 168     */
 169    function attach_to($display_id) { }
 170  
 171    /**
 172     * Static member function to list which sections are defaultable
 173     * and what items each section contains.
 174     */
 175    function defaultable_sections($section = NULL) {
 176      $sections = array(
 177        'access' => array('access'),
 178        'cache' => array('cache'),
 179        'title' => array('title'),
 180        'css_class' => array('css_class'),
 181        'header' => array('header', 'header_format', 'header_empty'),
 182        'footer' => array('footer', 'footer_format', 'footer_empty'),
 183        'empty' => array('empty', 'empty_format'),
 184        'use_ajax' => array('use_ajax'),
 185        'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
 186        'use_pager' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
 187        'use_more' => array('use_more', 'use_more_always', 'use_more_text'),
 188        'link_display' => array('link_display'),
 189        'distinct' => array('distinct'),
 190        'exposed_block' => array('exposed_block'),
 191  
 192        // Force these to cascade properly.
 193        'style_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
 194        'style_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
 195        'row_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
 196        'row_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
 197  
 198        // These guys are special
 199        'relationships' => array('relationships'),
 200        'fields' => array('fields'),
 201        'sorts' => array('sorts'),
 202        'arguments' => array('arguments'),
 203        'filters' => array('filters'),
 204      );
 205      if ($section) {
 206        if (!empty($sections[$section])) {
 207          return $sections[$section];
 208        }
 209      }
 210      else {
 211        return $sections;
 212      }
 213    }
 214  
 215    /**
 216     * Set default options.
 217     *
 218     * Displays put their options in a different place than everything else; also
 219     * displays spread their options out. We don't want to set defaults for
 220     * items that are normally defaulted elsewhere.
 221     */
 222    function _set_option_defaults(&$storage, $options, $level = 0) {
 223      foreach ($options as $option => $definition) {
 224        // If defaulted to elsewhere and we're not the default display, skip.
 225        if ($level == 0 && !$this->is_default_display() && !empty($options['defaults']['default'][$option])) {
 226          continue;
 227        }
 228  
 229        if (isset($definition['contains']) && is_array($definition['contains'])) {
 230          $storage[$option] = array();
 231          $this->_set_option_defaults($storage[$option], $definition['contains'], $level++);
 232        }
 233        else {
 234          $storage[$option] = isset($definition['default']) ? $definition['default'] : NULL;
 235        }
 236      }
 237    }
 238  
 239    function option_definition() {
 240      $options = array(
 241        'defaults' => array(
 242          'default' => array(
 243            'access' => TRUE,
 244            'cache' => TRUE,
 245            'title' => TRUE,
 246            'css_class' => TRUE,
 247            'header' => TRUE,
 248            'header_format' => TRUE,
 249            'header_empty' => TRUE,
 250            'footer' => TRUE,
 251            'footer_format' => TRUE,
 252            'footer_empty' => TRUE,
 253            'empty' => TRUE,
 254            'empty_format' => TRUE,
 255  
 256            'use_ajax' => TRUE,
 257            'items_per_page' => TRUE,
 258            'offset' => TRUE,
 259            'use_pager' => TRUE,
 260            'pager_element'  => TRUE,
 261            'use_more' => TRUE,
 262            'use_more_always' => TRUE,
 263            'use_more_text' => TRUE,
 264            'distinct' => TRUE,
 265            'exposed_block' => TRUE,
 266  
 267            'link_display' => TRUE,
 268  
 269            'style_plugin' => TRUE,
 270            'style_options' => TRUE,
 271            'row_plugin' => TRUE,
 272            'row_options' => TRUE,
 273  
 274            'relationships' => TRUE,
 275            'fields' => TRUE,
 276            'sorts' => TRUE,
 277            'arguments' => TRUE,
 278            'filters' => TRUE,
 279          ),
 280        ),
 281        'relationships' => array(
 282          'default' => array(),
 283          'export' => 'export_item',
 284        ),
 285        'fields' => array(
 286          'default' => array(),
 287          'export' => 'export_item',
 288        ),
 289        'sorts' => array(
 290          'default' => array(),
 291          'export' => 'export_item',
 292        ),
 293        'arguments' => array(
 294          'default' => array(),
 295          'export' => 'export_item',
 296        ),
 297        'filters' => array(
 298          'default' => array(),
 299          'export' => 'export_item',
 300        ),
 301        'access' => array(
 302          'contains' => array(
 303            'type' => array('default' => 'none'),
 304           ),
 305        ),
 306        'cache' => array(
 307          'contains' => array(
 308            'type' => array('default' => 'none'),
 309           ),
 310        ),
 311        'title' => array(
 312          'default' => '',
 313          'translatable' => TRUE,
 314        ),
 315        'css_class' => array(
 316          'default' => '',
 317          'translatable' => FALSE,
 318        ),
 319        'header' => array(
 320          'default' => '',
 321          'translatable' => TRUE,
 322        ),
 323        'header_format' => array(
 324          'default' => FILTER_FORMAT_DEFAULT,
 325        ),
 326        'header_empty' => array(
 327          'default' => FALSE,
 328        ),
 329        'footer' => array(
 330          'default' => '',
 331          'translatable' => TRUE,
 332        ),
 333        'footer_format' => array(
 334          'default' => FILTER_FORMAT_DEFAULT,
 335        ),
 336        'footer_empty' => array(
 337          'default' => FALSE,
 338        ),
 339        'empty' => array(
 340          'default' => '',
 341          'translatable' => TRUE,
 342        ),
 343        'empty_format' => array(
 344          'default' => FILTER_FORMAT_DEFAULT,
 345        ),
 346        'use_ajax' => array(
 347          'default' => FALSE,
 348        ),
 349        'items_per_page' => array(
 350          'default' => 10,
 351        ),
 352        'offset' => array(
 353          'default' => 0,
 354        ),
 355        'use_pager' => array(
 356          'default' => FALSE,
 357        ),
 358        'pager_element' => array(
 359          'default' => 0,
 360        ),
 361        'use_more' => array(
 362          'default' => FALSE,
 363        ),
 364        'use_more_always' => array(
 365          'default' => FALSE,
 366        ),
 367        'use_more_text' => array(
 368          'default' => 'more',
 369          'translatable' => TRUE,
 370        ),
 371        'link_display' => array(
 372          'default' => '',
 373        ),
 374        'distinct' => array(
 375          'default' => FALSE,
 376        ),
 377  
 378        'style_plugin' => array(
 379          'default' => 'default',
 380        ),
 381        'style_options' => array(
 382          'default' => array(),
 383        ),
 384        'row_plugin' => array(
 385          'default' => 'fields',
 386        ),
 387        'row_options' => array(
 388          'default' => array(),
 389        ),
 390  
 391        'exposed_block' => array(
 392          'default' => FALSE,
 393        ),
 394      );
 395  
 396      if ($this->is_default_display()) {
 397        unset($options['defaults']);
 398      }
 399      return $options;
 400    }
 401  
 402    /**
 403     * Check to see if the display has a 'path' field.
 404     *
 405     * This is a pure function and not just a setting on the definition
 406     * because some displays (such as a panel pane) may have a path based
 407     * upon configuration.
 408     *
 409     * By default, displays do not have a path.
 410     */
 411    function has_path() { return FALSE; }
 412  
 413    /**
 414     * Check to see if the display has some need to link to another display.
 415     *
 416     * For the most part, displays without a path will use a link display. However,
 417     * sometimes displays that have a path might also need to link to another display.
 418     * This is true for feeds.
 419     */
 420    function uses_link_display() { return !$this->has_path(); }
 421  
 422    /**
 423     * Check to see which display to use when creating links within
 424     * a view using this display.
 425     */
 426    function get_link_display() {
 427      $display_id = $this->get_option('link_display');
 428      // If unknown, pick the first one.
 429      if (empty($display_id) || empty($this->view->display[$display_id])) {
 430        foreach ($this->view->display as $display_id => $display) {
 431          if (!empty($display->handler) && $display->handler->has_path()) {
 432            return $display_id;
 433          }
 434        }
 435      }
 436      else {
 437        return $display_id;
 438      }
 439      // fall-through returns NULL
 440    }
 441  
 442    /**
 443     * Return the base path to use for this display.
 444     *
 445     * This can be overridden for displays that do strange things
 446     * with the path.
 447     */
 448    function get_path() {
 449      if ($this->has_path()) {
 450        return $this->get_option('path');
 451      }
 452  
 453      $display_id = $this->get_link_display();
 454      if ($display_id && !empty($this->view->display[$display_id]) && is_object($this->view->display[$display_id]->handler)) {
 455        return $this->view->display[$display_id]->handler->get_path();
 456      }
 457    }
 458  
 459    /**
 460     * Check to see if the display needs a breadcrumb
 461     *
 462     * By default, displays do not need breadcrumbs
 463     */
 464    function uses_breadcrumb() { return FALSE; }
 465  
 466    /**
 467     * Determine if a given option is set to use the default display or the
 468     * current display
 469     *
 470     * @return
 471     *   TRUE for the default display
 472     */
 473    function is_defaulted($option) {
 474      return !$this->is_default_display() && !empty($this->default_display) && !empty($this->options['defaults'][$option]);
 475    }
 476  
 477    /**
 478     * Intelligently get an option either from this display or from the
 479     * default display, if directed to do so.
 480     */
 481    function get_option($option) {
 482      if ($this->is_defaulted($option)) {
 483        return $this->default_display->get_option($option);
 484      }
 485  
 486      if (array_key_exists($option, $this->options)) {
 487        return $this->options[$option];
 488      }
 489    }
 490  
 491    /**
 492     * Determine if the display's style uses fields.
 493     */
 494    function uses_fields() {
 495      $plugin = $this->get_plugin();
 496      if ($plugin) {
 497        return $plugin->uses_fields();
 498      }
 499    }
 500  
 501    /**
 502     * Get the display or row plugin, if it exists.
 503     */
 504    function get_plugin($type = 'style', $name = NULL) {
 505      if (!$name) {
 506        $name = $this->get_option($type . '_plugin');
 507      }
 508  
 509      $plugin = views_get_plugin($type, $name);
 510      if ($plugin) {
 511        $options = $this->get_option($type . '_options');
 512        $plugin->init($this->view, $this->display, $options);
 513        return $plugin;
 514      }
 515    }
 516  
 517    /**
 518     * Get the access plugin
 519     */
 520    function get_access_plugin($name = NULL) {
 521      if (!$name) {
 522        $access = $this->get_option('access');
 523        $name = $access['type'];
 524      }
 525  
 526      $plugin = views_get_plugin('access', $name);
 527      if ($plugin) {
 528        $plugin->init($this->view, $this->display);
 529        return $plugin;
 530      }
 531    }
 532  
 533    /**
 534     * Get the cache plugin
 535     */
 536    function get_cache_plugin($name = NULL) {
 537      if (!$name) {
 538        $cache = $this->get_option('cache');
 539        $name = $cache['type'];
 540      }
 541  
 542      $plugin = views_get_plugin('cache', $name);
 543      if ($plugin) {
 544        $plugin->init($this->view, $this->display);
 545        return $plugin;
 546      }
 547    }
 548  
 549    /**
 550     * Get the handler object for a single handler.
 551     */
 552    function &get_handler($type, $id) {
 553      if (!isset($this->handlers[$type])) {
 554        $this->get_handlers($type);
 555      }
 556  
 557      if (isset($this->handlers[$type][$id])) {
 558        return $this->handlers[$type][$id];
 559      }
 560  
 561      // So we can return a reference.
 562      $null = NULL;
 563      return $null;
 564    }
 565  
 566    /**
 567     * Get a full array of handlers for $type. This caches them.
 568     */
 569    function get_handlers($type) {
 570      if (!isset($this->handlers[$type])) {
 571        $this->handlers[$type] = array();
 572        $types = views_object_types();
 573        $plural = $types[$type]['plural'];
 574        foreach ($this->get_option($plural) as $id => $info) {
 575          if ($info['id'] != $id) {
 576            $info['id'] = $id;
 577          }
 578  
 579          $handler = views_get_handler($info['table'], $info['field'], $type);
 580          if ($handler) {
 581            $handler->init($this->view, $info);
 582            $this->handlers[$type][$id] = &$handler;
 583          }
 584  
 585          // Prevent reference problems.
 586          unset($handler);
 587        }
 588      }
 589  
 590      return $this->handlers[$type];
 591    }
 592  
 593    /**
 594     * Retrieve a list of fields for the current display with the
 595     *  relationship associated if it exists.
 596     */
 597    function get_field_labels() {
 598      $options = array();
 599      foreach ($this->get_handlers('relationship') as $relationship => $handler) {
 600        if ($label = $handler->label()) {
 601          $relationships[$relationship] = $label;
 602        }
 603        else {
 604          $relationships[$relationship] = $handler->ui_name();
 605        }
 606      }
 607  
 608      foreach ($this->get_handlers('field') as $id => $handler) {
 609        if ($label = $handler->label()) {
 610          $options[$id] = $label;
 611        }
 612        else {
 613          $options[$id] = $handler->ui_name();
 614        }
 615        if (!empty($handler->options['relationship']) && !empty($relationships[$handler->options['relationship']])) {
 616          $options[$id] = '(' . $relationships[$handler->options['relationship']] . ') ' . $options[$id];
 617        }
 618      }
 619      return $options;
 620    }
 621  
 622    /**
 623     * Intelligently set an option either from this display or from the
 624     * default display, if directed to do so.
 625     */
 626    function set_option($option, $value) {
 627      if ($this->is_defaulted($option)) {
 628        return $this->default_display->set_option($option, $value);
 629      }
 630  
 631      // Set this in two places: On the handler where we'll notice it
 632      // but also on the display object so it gets saved. This should
 633      // only be a temporary fix.
 634      $this->display->display_options[$option] = $value;
 635      return $this->options[$option] = $value;
 636    }
 637  
 638    /**
 639     * Set an option and force it to be an override.
 640     */
 641    function override_option($option, $value) {
 642      $this->set_override($option, FALSE);
 643      $this->set_option($option, $value);
 644    }
 645  
 646    /**
 647     * Because forms may be split up into sections, this provides
 648     * an easy URL to exactly the right section. Don't override this.
 649     */
 650    function option_link($text, $section, $class = '', $title = '') {
 651      if (!empty($class)) {
 652        $text = '<span>' . $text . '</span>';
 653      }
 654  
 655      if (!trim($text)) {
 656        $text = t('Broken field');
 657      }
 658  
 659      if (empty($title)) {
 660        $title = $text;
 661      }
 662  
 663      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));
 664    }
 665  
 666    /**
 667     * Provide the default summary for options in the views UI.
 668     *
 669     * This output is returned as an array.
 670     */
 671    function options_summary(&$categories, &$options) {
 672      $categories['basic'] = array(
 673        'title' => t('Basic settings'),
 674      );
 675  
 676      $options['display_title'] = array(
 677        'category' => 'basic',
 678        'title' => t('Name'),
 679        'value' => check_plain($this->display->display_title),
 680        'desc' => t('Change the name of this display.'),
 681      );
 682  
 683      $title = strip_tags($this->get_option('title'));
 684      if (!$title) {
 685        $title = t('None');
 686      }
 687  
 688      $options['title'] = array(
 689        'category' => 'basic',
 690        'title' => t('Title'),
 691        'value' => $title,
 692        'desc' => t('Change the title that this display will use.'),
 693      );
 694  
 695      $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin'));
 696      $style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin['title'];
 697  
 698      $style = '';
 699  
 700      $options['style_plugin'] = array(
 701        'category' => 'basic',
 702        'title' => t('Style'),
 703        'value' => $style_title,
 704        'desc' => t('Change the style plugin.'),
 705      );
 706  
 707      // This adds a 'Settings' link to the style_options setting if the style has options.
 708      if (!empty($style_plugin['uses options'])) {
 709        $options['style_plugin']['links']['style_options'] = t('Change settings for this style');
 710      }
 711  
 712      if (!empty($style_plugin['uses row plugin'])) {
 713        $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin'));
 714        $row_title = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin['title'];
 715  
 716        $options['row_plugin'] = array(
 717          'category' => 'basic',
 718          'title' => t('Row style'),
 719          'value' => $row_title,
 720          'desc' => t('Change the row plugin.'),
 721        );
 722        // This adds a 'Settings' link to the row_options setting if the row style has options.
 723        if (!empty($row_plugin['uses options'])) {
 724          $options['row_plugin']['links']['row_options'] = t('Change settings for this style');
 725        }
 726      }
 727      if (!empty($this->definition['use ajax'])) {
 728        $options['use_ajax'] = array(
 729          'category' => 'basic',
 730          'title' => t('Use AJAX'),
 731          'value' => $this->get_option('use_ajax') ? t('Yes') : t('No'),
 732          'desc' => t('Change whether or not this display will use AJAX.'),
 733        );
 734      }
 735  
 736      if (!empty($this->definition['use pager'])) {
 737        $options['use_pager'] = array(
 738          'category' => 'basic',
 739          'title' => t('Use pager'),
 740          'value' => $this->get_option('use_pager') ? ($this->get_option('use_pager') === 'mini' ? t('Mini') : t('Yes')) : t('No'),
 741          'desc' => t("Change this display's pager setting."),
 742        );
 743      }
 744  
 745      $items = intval($this->get_option('items_per_page'));
 746      $options['items_per_page'] = array(
 747        'category' => 'basic',
 748        'title' => $this->use_pager() ? t('Items per page') : t('Items to display'),
 749        'value' => $items ? $items : t('Unlimited'),
 750        'desc' => t('Change how many items to display.'),
 751      );
 752  
 753      if (!empty($this->definition['use more'])) {
 754        $options['use_more'] = array(
 755          'category' => 'basic',
 756          'title' => t('More link'),
 757          'value' => $this->get_option('use_more') ? t('Yes') : t('No'),
 758          'desc' => t('Specify whether this display will provide a "more" link.'),
 759        );
 760      }
 761  
 762      $options['distinct'] = array(
 763        'category' => 'basic',
 764        'title' => t('Distinct'),
 765        'value' => $this->get_option('distinct') ? t('Yes') : t('No'),
 766        'desc' => t('Display only distinct items, without duplicates.'),
 767      );
 768  
 769      $access_plugin = $this->get_access_plugin();
 770      if (!$access_plugin) {
 771        // default to the no access control plugin.
 772        $access_plugin = views_get_plugin('access', 'none');
 773      }
 774  
 775      $access_str = $access_plugin->summary_title();
 776  
 777      $options['access'] = array(
 778        'category' => 'basic',
 779        'title' => t('Access'),
 780        'value' => $access_str,
 781        'desc' => t('Specify access control type for this display.'),
 782      );
 783  
 784      if (!empty($access_plugin->definition['uses options'])) {
 785        $options['access']['links']['access_options'] = t('Change settings for this access type.');
 786      }
 787  
 788      $cache_plugin = $this->get_cache_plugin();
 789      if (!$cache_plugin) {
 790        // default to the no cache control plugin.
 791        $cache_plugin = views_get_plugin('cache', 'none');
 792      }
 793  
 794      $cache_str = $cache_plugin->summary_title();
 795  
 796      $options['cache'] = array(
 797        'category' => 'basic',
 798        'title' => t('Caching'),
 799        'value' => $cache_str,
 800        'desc' => t('Specify caching type for this display.'),
 801      );
 802  
 803      if (!empty($cache_plugin->definition['uses options'])) {
 804        $options['cache']['links']['cache_options'] = t('Change settings for this caching type.');
 805      }
 806  
 807      if ($this->uses_link_display()) {
 808        // Only show the 'link display' if there is more than one option.
 809        $count = 0;
 810        foreach ($this->view->display as $display_id => $display) {
 811          if (is_object($display->handler) && $display->handler->has_path()) {
 812            $count++;
 813          }
 814          if ($count > 1) {
 815            break;
 816          }
 817        }
 818  
 819        if ($count > 1) {
 820          $display_id = $this->get_link_display();
 821          $link_display = empty($this->view->display[$display_id]) ? t('None') : check_plain($this->view->display[$display_id]->display_title);
 822          $options['link_display'] = array(
 823            'category' => 'basic',
 824            'title' => t('Link display'),
 825            'value' => $link_display,
 826            'desc' => t('Specify which display this display will link to.'),
 827          );
 828        }
 829      }
 830  
 831      $options['exposed_block'] = array(
 832        'category' => 'basic',
 833        'title' => t('Exposed form in block'),
 834        'value' => $this->get_option('exposed_block') ? t('Yes') : t('No'),
 835        'desc' => t('Allow the exposed form to appear in a block instead of the view.'),
 836      );
 837  
 838      foreach (array('header' => t('Header'), 'footer' => t('Footer'), 'empty' => t('Empty text')) as $type => $name) {
 839        if (!$this->get_option($type)) {
 840          $field = t('None');
 841        }
 842        else {
 843          // A lot of code to get the name of the filter format.
 844          $fmt_string = $this->get_option($type . '_format');
 845          if (empty($fmt_string)) {
 846            $fmt_string = FILTER_FORMAT_DEFAULT;
 847          }
 848          $format_val = filter_resolve_format($fmt_string);
 849          $format = filter_formats($format_val);
 850          if ($format) {
 851            $field = check_plain($format->name);
 852          }
 853          else {
 854            $field = t('Unknown/missing format');
 855          }
 856        }
 857  
 858        $options[$type] = array(
 859          'category' => 'basic',
 860          'title' => $name,
 861          'value' => $field,
 862          'desc' => t("Change this display's !name.", array('!name' => strtolower($name))),
 863        );
 864      }
 865  
 866      $css_class = check_plain(trim($this->get_option('css_class')));
 867      if (!$css_class) {
 868        $css_class = t('None');
 869      }
 870  
 871      $options['css_class'] = array(
 872        'category' => 'basic',
 873        'title' => t('CSS class'),
 874        'value' => $css_class,
 875        'desc' => t('Change the CSS class name(s) that will be added to this display.'),
 876      );
 877  
 878      $options['analyze-theme'] = array(
 879        'category' => 'basic',
 880        'title' => t('Theme'),
 881        'value' => t('Information'),
 882        'desc' => t('Get information on how to theme this display'),
 883      );
 884    }
 885  
 886    /**
 887     * Provide the default form for setting options.
 888     */
 889    function options_form(&$form, &$form_state) {
 890      if ($this->defaultable_sections($form_state['section'])) {
 891        $this->add_override_button($form, $form_state, $form_state['section']);
 892      }
 893      $form['#title'] = check_plain($this->display->display_title) . ': ';
 894  
 895      // Set the 'section' to hilite on the form.
 896      // If it's the item we're looking at is pulling from the default display,
 897      // reflect that. Don't use is_defaulted since we want it to show up even
 898      // on the default display.
 899      if (!empty($this->options['defaults'][$form_state['section']])) {
 900        $form['#section'] = 'default-' . $form_state['section'];
 901      }
 902      else {
 903        $form['#section'] = $this->display->id . '-' . $form_state['section'];
 904      }
 905  
 906      switch ($form_state['section']) {
 907        case 'display_title':
 908          $form['#title'] .= t('The name of this display');
 909          $form['display_title'] = array(
 910            '#type' => 'textfield',
 911            '#description' => t('This title will appear only in the administrative interface for the View.'),
 912            '#default_value' => $this->display->display_title,
 913          );
 914          break;
 915        case 'title':
 916          $form['#title'] .= t('The title of this view');
 917          $form['title'] = array(
 918            '#type' => 'textfield',
 919            '#description' => t('This title will be displayed with the view, wherever titles are normally displayed; i.e, as the page title, block title, etc.'),
 920            '#default_value' => $this->get_option('title'),
 921          );
 922          break;
 923        case 'css_class':
 924          $form['#title'] .= t('CSS class');
 925          $form['css_class'] = array(
 926            '#type' => 'textfield',
 927            '#description' => t('The CSS class names will be added to the view. This enables you to use specific CSS code for each view. You may define multiples classes separated by spaces.'),
 928            '#default_value' => $this->get_option('css_class'),
 929          );
 930          break;
 931        case 'use_ajax':
 932          $form['#title'] .= t('Use AJAX when available to load this view');
 933          $form['description'] = array(
 934            '#prefix' => '<div class="description form-item">',
 935            '#suffix' => '</div>',
 936            '#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.'),
 937          );
 938          $form['use_ajax'] = array(
 939            '#type' => 'radios',
 940            '#options' => array(1 => t('Yes'), 0 => t('No')),
 941            '#default_value' => $this->get_option('use_ajax') ? 1 : 0,
 942          );
 943          break;
 944        case 'use_pager':
 945          $form['#title'] .= t('Use a pager for this view');
 946          $form['use_pager'] = array(
 947            '#type' => 'radios',
 948            '#options' => array(TRUE => t('Full pager'), 'mini' => t('Mini pager'), 0 => t('No')),
 949            '#default_value' => $this->get_option('use_pager'),
 950          );
 951          $form['pager_element'] = array(
 952            '#type' => 'textfield',
 953            '#title' => t('Pager element'),
 954            '#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."),
 955            '#default_value' => intval($this->get_option('pager_element')),
 956          );
 957          break;
 958        case 'items_per_page':
 959          $form['#title'] .= $this->use_pager() ? t('Items per page') : t('Items to display');
 960  
 961          $form['items_per_page'] = array(
 962            '#type' => 'textfield',
 963            '#description' => t('The number of items to display per page. Enter 0 for no limit.'),
 964            '#default_value' => intval($this->get_option('items_per_page')),
 965          );
 966          $form['offset'] = array(
 967            '#type' => 'textfield',
 968            '#title' => t('Offset'),
 969            '#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.'),
 970            '#default_value' => intval($this->get_option('offset')),
 971          );
 972          break;
 973        case 'use_more':
 974          $form['#title'] .= t('Add a more link to the bottom of the display.');
 975          $form['use_more'] = array(
 976            '#type' => 'checkbox',
 977            '#title' => t('Create more link'),
 978            '#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."),
 979            '#default_value' => $this->get_option('use_more'),
 980          );
 981          $form['use_more_always'] = array(
 982            '#type' => 'checkbox',
 983            '#title' => t('Always display more link'),
 984            '#description' => t("This will display the more link even if there are no more items to display."),
 985            '#default_value' => $this->get_option('use_more_always'),
 986          );
 987          $form['#title'] .= t('Text to use for the more link.');
 988          $form['use_more_text'] = array(
 989            '#type' => 'textfield',
 990            '#title' => t('More link text'),
 991            '#description' => t("The text to display for the more link."),
 992            '#default_value' => $this->get_option('use_more_text'),
 993          );
 994          break;
 995        case 'distinct':
 996          $form['#title'] .= t('Display only distinct items, without duplicates.');
 997          $form['distinct'] = array(
 998            '#type' => 'checkbox',
 999            '#title' => t('Distinct'),
1000            '#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.'),
1001            '#default_value' => $this->get_option('distinct'),
1002          );
1003          break;
1004        case 'access':
1005          $form['#title'] .= t('Access restrictions');
1006          $form['access'] = array(
1007            '#prefix' => '<div class="clear-block">',
1008            '#suffix' => '</div>',
1009            '#tree' => TRUE,
1010          );
1011  
1012          $access = $this->get_option('access');
1013          $form['access']['type'] =  array(
1014            '#type' => 'radios',
1015            '#options' => views_fetch_plugin_names('access'),
1016            '#default_value' => $access['type'],
1017          );
1018  
1019          $access_plugin = views_fetch_plugin_data('access', $access['type']);
1020          if (!empty($access_plugin['uses options'])) {
1021            $form['markup'] = array(
1022              '#prefix' => '<div class="form-item description">',
1023              '#suffix' => '</div>',
1024              '#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'))),
1025            );
1026          }
1027  
1028          break;
1029        case 'access_options':
1030          $access = $this->get_option('access');
1031          $plugin = $this->get_access_plugin();
1032          $form['#title'] .= t('Access options');
1033          if ($plugin) {
1034            $form['#help_topic'] = $plugin->definition['help topic'];
1035            $form['#help_module'] = $plugin->definition['module'];
1036  
1037            $form['access_options'] = array(
1038              '#tree' => TRUE,
1039            );
1040            $form['access_options']['type'] = array(
1041              '#type' => 'value',
1042              '#value' => $access['type'],
1043            );
1044            $plugin->options_form($form['access_options'], $form_state);
1045          }
1046          break;
1047        case 'cache':
1048          $form['#title'] .= t('Caching');
1049          $form['cache'] = array(
1050            '#prefix' => '<div class="clear-block">',
1051            '#suffix' => '</div>',
1052            '#tree' => TRUE,
1053          );
1054  
1055          $cache = $this->get_option('cache');
1056          $form['cache']['type'] =  array(
1057            '#type' => 'radios',
1058            '#options' => views_fetch_plugin_names('cache'),
1059            '#default_value' => $cache['type'],
1060          );
1061  
1062          $cache_plugin = views_fetch_plugin_data('cache', $cache['type']);
1063          if (!empty($cache_plugin['uses options'])) {
1064            $form['markup'] = array(
1065              '#prefix' => '<div class="form-item description">',
1066              '#suffix' => '</div>',
1067              '#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'))),
1068            );
1069          }
1070          break;
1071        case 'cache_options':
1072          $cache = $this->get_option('cache');
1073          $plugin = $this->get_cache_plugin();
1074          $form['#title'] .= t('Caching options');
1075          if ($plugin) {
1076            $form['#help_topic'] = $plugin->definition['help topic'];
1077            $form['#help_module'] = $plugin->definition['module'];
1078  
1079            $form['cache_options'] = array(
1080              '#tree' => TRUE,
1081            );
1082            $form['cache_options']['type'] = array(
1083              '#type' => 'value',
1084              '#value' => $cache['type'],
1085            );
1086            $plugin->options_form($form['cache_options'], $form_state);
1087          }
1088          break;
1089        case 'header':
1090          $form['#title'] .= t('Header');
1091          $form['header_empty'] = array(
1092            '#type' => 'checkbox',
1093            '#title' => t('Display even if view has no result'),
1094            '#default_value' => $this->get_option('header_empty'),
1095          );
1096          $form['header'] = array(
1097            '#type' => 'textarea',
1098            '#default_value' => $this->get_option('header'),
1099            '#rows' => 6,
1100            '#description' => t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional.'),
1101          );
1102  
1103          $form['header_format'] = filter_form($this->get_option('header_format'), NULL, array('header_format'));
1104          break;
1105        case 'footer':
1106          $form['#title'] .= t('Footer');
1107          $form['footer_empty'] = array(
1108            '#type' => 'checkbox',
1109            '#title' => t('Display even if view has no result'),
1110            '#default_value' => $this->get_option('footer_empty'),
1111          );
1112          $form['footer'] = array(
1113            '#type' => 'textarea',
1114            '#default_value' => $this->get_option('footer'),
1115            '#rows' => 6,
1116            '#description' => t('Text to display beneath the view. May contain an explanation or links or whatever you like. Optional.'),
1117          );
1118  
1119          $form['footer_format'] = filter_form($this->get_option('footer_format'), NULL, array('footer_format'));
1120          break;
1121        case 'empty':
1122          $form['#title'] .= t('Empty text');
1123          $form['empty'] = array(
1124            '#type' => 'textarea',
1125            '#default_value' => $this->get_option('empty'),
1126            '#rows' => 6,
1127            '#description' => t('Text to display if the view has no results. Optional.'),
1128          );
1129  
1130          $form['empty_format'] = filter_form($this->get_option('empty_format'), NULL, array('empty_format'));
1131          break;
1132        case 'style_plugin':
1133          $form['#title'] .= t('How should this view be styled');
1134          $form['#help_topic'] = 'style';
1135          $form['style_plugin'] =  array(
1136            '#type' => 'radios',
1137            '#options' => views_fetch_plugin_names('style', $this->get_style_type(), array($this->view->base_table)),
1138            '#default_value' => $this->get_option('style_plugin'),
1139            '#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.'),
1140          );
1141  
1142          $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin'));
1143          if (!empty($style_plugin['uses options'])) {
1144            $form['markup'] = array(
1145              '#prefix' => '<div class="form-item description">',
1146              '#suffix' => '</div>',
1147              '#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'))),
1148            );
1149          }
1150  
1151          break;
1152        case 'style_options':
1153          $form['#title'] .= t('Style options');
1154          $style = TRUE;
1155          $type = 'style_plugin';
1156          $name = $this->get_option('style_plugin');
1157  
1158        case 'row_options':
1159          if (!isset($name)) {
1160            $name = $this->get_option('row_plugin');
1161          }
1162          // if row, $style will be empty.
1163          if (empty($style)) {
1164            $form['#title'] .= t('Row style options');
1165            $type = 'row_plugin';
1166          }
1167          $plugin = $this->get_plugin(empty($style) ? 'row' : 'style');
1168          if ($plugin) {
1169            if (isset($plugin->definition['help topic'])) {
1170              $form['#help_topic'] = $plugin->definition['help topic'];
1171              $form['#help_module'] = $plugin->definition['module'];
1172            }
1173            $form[$form_state['section']] = array(
1174              '#tree' => TRUE,
1175            );
1176            $plugin->options_form($form[$form_state['section']], $form_state);
1177          }
1178          break;
1179        case 'row_plugin':
1180          $form['#title'] .= t('How should each row in this view be styled');
1181          $form['#help_topic'] = 'style-row';
1182          $form['row_plugin'] =  array(
1183            '#type' => 'radios',
1184            '#options' => views_fetch_plugin_names('row', $this->get_style_type(), array($this->view->base_table)),
1185            '#default_value' => $this->get_option('row_plugin'),
1186          );
1187  
1188          $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin'));
1189          if (!empty($row_plugin['uses options'])) {
1190            $form['markup'] = array(
1191              '#prefix' => '<div class="form-item description">',
1192              '#suffix' => '</div>',
1193              '#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'))),
1194            );
1195          }
1196  
1197          break;
1198        case 'link_display':
1199          $form['#title'] .= t('Which display to use for path');
1200          foreach ($this->view->display as $display_id => $display) {
1201            if ($display->handler->has_path()) {
1202              $options[$display_id] = $display->display_title;
1203            }
1204          }
1205          $form['link_display'] = array(
1206            '#type' => 'radios',
1207            '#options' => $options,
1208            '#description' => t("Which display to use to get this display's path for things like summary links, rss feed links, more links, etc."),
1209            '#default_value' => $this->get_link_display(),
1210          );
1211          break;
1212        case 'analyze-theme':
1213          $form['#title'] .= t('Theming information');
1214          $form['#help_topic'] = 'analyze-theme';
1215  
1216          if (isset($_POST['theme'])) {
1217            $this->view->theme = $_POST['theme'];
1218          }
1219          else if (empty($this->view->theme)) {
1220            $this->view->theme = variable_get('theme_default', 'garland');
1221          }
1222  
1223          global $custom_theme;
1224          $custom_theme = $this->view->theme;
1225          init_theme();
1226  
1227          $funcs = array();
1228          // Get theme functions for the display. Note that some displays may
1229          // not have themes. The 'feed' display, for example, completely
1230          // delegates to the style.
1231          if (!empty($this->definition['theme'])) {
1232            $funcs[] = $this->option_link(t('Display output'), 'analyze-theme-display') . ': '  . $this->format_themes($this->theme_functions());
1233            $themes = $this->additional_theme_functions();
1234            if ($themes) {
1235              foreach ($themes as $theme) {
1236                $funcs[] = $this->option_link(t('Alternative display output'), 'analyze-theme-display') . ': '  . $this->format_themes($theme);
1237              }
1238            }
1239          }
1240  
1241          $plugin = $this->get_plugin();
1242          if ($plugin) {
1243            $funcs[] = $this->option_link(t('Style output'), 'analyze-theme-style') . ': ' . $this->format_themes($plugin->theme_functions(), $plugin->additional_theme_functions());
1244            $themes = $plugin->additional_theme_functions();
1245            if ($themes) {
1246              foreach ($themes as $theme) {
1247                $funcs[] = $this->option_link(t('Alternative style'), 'analyze-theme-style') . ': '  . $this->format_themes($theme);
1248              }
1249            }
1250  
1251            if ($plugin->uses_row_plugin()) {
1252              $row_plugin = $this->get_plugin('row');
1253              if ($row_plugin) {
1254                $funcs[] = $this->option_link(t('Row style output'), 'analyze-theme-row') . ': ' . $this->format_themes($row_plugin->theme_functions());
1255                $themes = $row_plugin->additional_theme_functions();
1256                if ($themes) {
1257                  foreach ($themes as $theme) {
1258                    $funcs[] = $this->option_link(t('Alternative row style'), 'analyze-theme-row') . ': '  . $this->format_themes($theme);
1259                  }
1260                }
1261              }
1262            }
1263  
1264            if ($plugin->uses_fields()) {
1265              foreach ($this->get_handlers('field') as $id => $handler) {
1266                $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());
1267              }
1268            }
1269          }
1270  
1271          $form['important'] = array(
1272            '#prefix' => '<div class="form-item description">',
1273            '#suffix' => '</div>',
1274            '#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>',
1275          );
1276  
1277          foreach (list_themes() as $key => $theme) {
1278            $options[$key] = $theme->info['name'];
1279          }
1280  
1281          $form['box'] = array(
1282            '#prefix' => '<div class="container-inline">',
1283            '#suffix' => '</div>',
1284          );
1285          $form['box']['theme'] = array(
1286            '#type' => 'select',
1287            '#options' => $options,
1288            '#default_value' => $this->view->theme,
1289          );
1290  
1291          $form['box']['change'] = array(
1292            '#type' => 'submit',
1293            '#value' => t('Change theme'),
1294            '#submit' => array('views_ui_edit_display_form_change_theme'),
1295          );
1296  
1297          $form['analysis'] = array(
1298            '#prefix' => '<div class="form-item">',
1299            '#suffix' => '</div>',
1300            '#value' => theme('item_list', $funcs),
1301          );
1302  
1303          $form['rescan_button'] = array(
1304            '#prefix' => '<div class="form-item">',
1305            '#suffix' => '</div>',
1306          );
1307          $form['rescan_button']['button'] = array(
1308            '#type' => 'submit',
1309            '#value' => t('Rescan template files'),
1310            '#submit' => array('views_ui_config_item_form_rescan'),
1311          );
1312          $form['rescan_button']['markup'] = array(
1313            '#prefix' => '<div class="description">',
1314            '#suffix' => '</div>',
1315            '#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."),
1316          );
1317  
1318          $form_state['ok_button'] = TRUE;
1319          break;
1320        case 'analyze-theme-display':
1321          $form['#title'] .= t('Theming information (display)');
1322          $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
1323  
1324          if (empty($this->definition['theme'])) {
1325            $output .= t('This display has no theming information');
1326          }
1327          else {
1328            $output .= '<p>' . t('This is the default theme template used for this display.') . '</p>';
1329            $output .= '<pre>' . check_plain(file_get_contents('./' . $this->definition['theme path'] . '/' . strtr($this->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>';
1330          }
1331  
1332          if (!empty($this->definition['additional themes'])) {
1333            foreach ($this->definition['additional themes'] as $theme => $type) {
1334              $output .= '<p>' . t('This is an alternative template for this display.') . '</p>';
1335              $output .= '<pre>' . check_plain(file_get_contents('./' . $this->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>';
1336            }
1337          }
1338  
1339          $form['analysis'] = array(
1340            '#prefix' => '<div class="form-item">',
1341            '#suffix' => '</div>',
1342            '#value' => $output,
1343          );
1344  
1345          $form_state['ok_button'] = TRUE;
1346          break;
1347        case 'analyze-theme-style':
1348          $form['#title'] .= t('Theming information (style)');
1349          $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
1350  
1351          $plugin = $this->get_plugin();
1352  
1353          if (empty($plugin->definition['theme'])) {
1354            $output .= t('This display has no style theming information');
1355          }
1356          else {
1357            $output .= '<p>' . t('This is the default theme template used for this style.') . '</p>';
1358            $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($plugin->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>';
1359          }
1360  
1361          if (!empty($plugin->definition['additional themes'])) {
1362            foreach ($plugin->definition['additional themes'] as $theme => $type) {
1363              $output .= '<p>' . t('This is an alternative template for this style.') . '</p>';
1364              $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>';
1365            }
1366          }
1367  
1368          $form['analysis'] = array(
1369            '#prefix' => '<div class="form-item">',
1370            '#suffix' => '</div>',
1371            '#value' => $output,
1372          );
1373  
1374          $form_state['ok_button'] = TRUE;
1375          break;
1376        case 'analyze-theme-row':
1377          $form['#title'] .= t('Theming information (row style)');
1378          $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
1379  
1380          $plugin = $this->get_plugin('row');
1381  
1382          if (empty($plugin->definition['theme'])) {
1383            $output .= t('This display has no row style theming information');
1384          }
1385          else {
1386            $output .= '<p>' . t('This is the default theme template used for this row style.') . '</p>';
1387            $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($plugin->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>';
1388          }
1389  
1390          if (!empty($plugin->definition['additional themes'])) {
1391            foreach ($plugin->definition['additional themes'] as $theme => $type) {
1392              $output .= '<p>' . t('This is an alternative template for this row style.') . '</p>';
1393              $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>';
1394            }
1395          }
1396  
1397          $form['analysis'] = array(
1398            '#prefix' => '<div class="form-item">',
1399            '#suffix' => '</div>',
1400            '#value' => $output,
1401          );
1402  
1403          $form_state['ok_button'] = TRUE;
1404          break;
1405        case 'analyze-theme-field':
1406          $form['#title'] .= t('Theming information (row style)');
1407          $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
1408  
1409          $output .= '<p>' . t('This is the default theme template used for this row style.') . '</p>';
1410  
1411          // Field templates aren't registered the normal way...and they're always
1412          // this one, anyhow.
1413          $output .= '<pre>' . check_plain(file_get_contents(drupal_get_path('module', 'views') . '/theme/views-view-field.tpl.php')) . '</pre>';
1414  
1415          $form['analysis'] = array(
1416            '#prefix' => '<div class="form-item">',
1417            '#suffix' => '</div>',
1418            '#value' => $output,
1419          );
1420          $form_state['ok_button'] = TRUE;
1421          break;
1422  
1423        case 'exposed_block':
1424          $form['#title'] .= t('Put the exposed form in a block');
1425          $form['description'] = array(
1426            '#prefix' => '<div class="description form-item">',
1427            '#suffix' => '</div>',
1428            '#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.'),
1429          );
1430          $form['exposed_block'] = array(
1431            '#type' => 'radios',
1432            '#options' => array(1 => t('Yes'), 0 => t('No')),
1433            '#default_value' => $this->get_option('exposed_block') ? 1 : 0,
1434          );
1435          break;
1436      }
1437    }
1438  
1439    /**
1440     * Format a list of theme templates for output by the theme info helper.
1441     */
1442    function format_themes($themes) {
1443      $registry = theme_get_registry();
1444  
1445      // Run through the theme engine variables, if necessary
1446      global $theme_engine;
1447      $extension = '.tpl.php';
1448      if (isset($theme_engine)) {
1449        $extension_function = $theme_engine . '_extension';
1450        if (function_exists($extension_function)) {
1451          $extension = $extension_function();
1452        }
1453      }
1454  
1455      $output = '';
1456      $picked = FALSE;
1457      foreach ($themes as $theme) {
1458        $template = strtr($theme, '_', '-') . $extension;
1459        if (!$picked && !empty($registry[$theme])) {
1460          $template_path = isset($registry[$theme]['path']) ? $registry[$theme]['path'] . '/' : './';
1461          if (file_exists($template_path . $template)) {
1462            $hint = t('File found in folder @template-path', array('@template-path' => $template_path));
1463            $template = '<strong title="'. $hint .'">' . $template . '</strong>';
1464          }
1465          else {
1466            $template = '<strong class="error">' . $template . ' ' . t('(File not found, in folder @template-path)', array('@template-path' => $template_path)) . '</strong>';
1467          }
1468          $picked = TRUE;
1469        }
1470        $fixed[] = $template;
1471      }
1472  
1473      return implode(', ', array_reverse($fixed));
1474    }
1475  
1476    /**
1477     * Validate the options form.
1478     */
1479    function options_validate(&$form, &$form_state) {
1480      switch ($form_state['section']) {
1481        case 'css_class':
1482          $css_class = $form_state['values']['css_class'];
1483          if (preg_match('/[^a-zA-Z0-9- ]/', $css_class)) {
1484            form_error($form['css_class'], t('CSS classes must be alphanumeric or dashes only.'));
1485          }
1486        break;
1487        case 'style_options':
1488          $style = TRUE;
1489        case 'row_options':
1490          // if row, $style will be empty.
1491          $plugin = $this->get_plugin(empty($style) ? 'row' : 'style');
1492          if ($plugin) {
1493            $plugin->options_validate($form[$form_state['section']], $form_state);
1494          }
1495          break;
1496        case 'access_options':
1497          $plugin = $this->get_access_plugin();
1498          if ($plugin) {
1499            $plugin->options_validate($form['access_options'], $form_state);
1500          }
1501          break;
1502        case 'cache_options':
1503          $plugin = $this->get_cache_plugin();
1504          if ($plugin) {
1505            $plugin->options_validate($form['cache_options'], $form_state);
1506          }
1507          break;
1508      }
1509    }
1510  
1511    /**
1512     * Perform any necessary changes to the form values prior to storage.
1513     * There is no need for this function to actually store the data.
1514     */
1515    function options_submit(&$form, &$form_state) {
1516      // Not sure I like this being here, but it seems (?) like a logical place.
1517      $cache_plugin = $this->get_cache_plugin();
1518      if ($cache_plugin) {
1519        $cache_plugin->cache_flush();
1520      }
1521  
1522      $section = $form_state['section'];
1523      switch ($section) {
1524        case 'display_title':
1525          $this->display->display_title = $form_state['values']['display_title'];
1526          break;
1527        case 'access':
1528          $access = $this->get_option('access');
1529          if ($access['type'] != $form_state['values']['access']['type']) {
1530            $plugin = views_get_plugin('access', $form_state['values']['access']['type']);
1531            if ($plugin) {
1532              $access = array('type' => $form_state['values']['access']['type']);
1533              $plugin->option_defaults($access);
1534              $this->set_option('access', $access);
1535              if (!empty($plugin->definition['uses options'])) {
1536                views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('access_options'));
1537              }
1538            }
1539          }
1540  
1541          break;
1542        case 'access_options':
1543          $plugin = views_get_plugin('access', $form_state['values'][$section]['type']);
1544          if ($plugin) {
1545            $plugin->options_submit($form['access_options'], $form_state);
1546            $this->set_option('access', $form_state['values'][$section]);
1547          }
1548          break;
1549        case 'cache':
1550          $cache = $this->get_option('cache');
1551          if ($cache['type'] != $form_state['values']['cache']['type']) {
1552            $plugin = views_get_plugin('cache', $form_state['values']['cache']['type']);
1553            if ($plugin) {
1554              $cache = array('type' => $form_state['values']['cache']['type']);
1555              $plugin->option_defaults($cache);
1556              $this->set_option('cache', $cache);
1557              if (!empty($plugin->definition['uses options'])) {
1558                views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('cache_options'));
1559              }
1560            }
1561          }
1562  
1563          break;
1564        case 'cache_options':
1565          $plugin = views_get_plugin('cache', $form_state['values'][$section]['type']);
1566          if ($plugin) {
1567            $plugin->options_submit($form['cache_options'], $form_state);
1568            $this->set_option('cache', $form_state['values'][$section]);
1569          }
1570          break;
1571        case 'title':
1572        case 'css_class':
1573        case 'link_display':
1574          $this->set_option($section, $form_state['values'][$section]);
1575          break;
1576        case 'use_ajax':
1577          $this->set_option($section, (bool)$form_state['values'][$section]);
1578          break;
1579        case 'use_pager':
1580          $this->set_option($section, $form_state['values'][$section]);
1581          $this->set_option('pager_element', intval($form_state['values']['pager_element']));
1582          break;
1583        case 'items_per_page':
1584          $this->set_option($section, intval($form_state['values'][$section]));
1585          $this->set_option('offset', intval($form_state['values']['offset']));
1586          break;
1587        case 'use_more':
1588          $this->set_option($section, intval($form_state['values'][$section]));
1589          $this->set_option('use_more_always', intval($form_state['values']['use_more_always']));
1590          $this->set_option('use_more_text', $form_state['values']['use_more_text']);
1591        case 'distinct':
1592          $this->set_option($section, $form_state['values'][$section]);
1593          break;
1594        case 'row_plugin':
1595          // This if prevents resetting options to default if they don't change
1596          // the plugin.
1597          if ($this->get_option($section) != $form_state['values'][$section]) {
1598            $plugin = views_get_plugin('row', $form_state['values'][$section]);
1599            if ($plugin) {
1600              $this->set_option($section, $form_state['values'][$section]);
1601              $this->set_option('row_options', array());
1602  
1603              // send ajax form to options page if we use it.
1604              if (!empty($plugin->definition['uses options'])) {
1605                views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('row_options'));
1606              }
1607            }
1608          }
1609          break;
1610        case 'style_plugin':
1611          // This if prevents resetting options to default if they don't change
1612          // the plugin.
1613          if ($this->get_option($section) != $form_state['values'][$section]) {
1614            $plugin = views_get_plugin('style', $form_state['values'][$section]);
1615            if ($plugin) {
1616              $this->set_option($section, $form_state['values'][$section]);
1617              $this->set_option('style_options', array());
1618              // send ajax form to options page if we use it.
1619              if (!empty($plugin->definition['uses options'])) {
1620                views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('style_options'));
1621              }
1622            }
1623          }
1624          break;
1625        case 'style_options':
1626          $style = TRUE;
1627        case 'row_options':
1628          // if row, $style will be empty.
1629          $plugin = $this->get_plugin(empty($style) ? 'row' : 'style');
1630          if ($plugin) {
1631            $plugin->options_submit($form[$section], $form_state);
1632          }
1633          $this->set_option($section, $form_state['values'][$section]);
1634          break;
1635        case 'header':
1636        case 'footer':
1637        case 'empty':
1638          $this->set_option($section, $form_state['values'][$section]);
1639          $this->set_option($section . '_format', $form_state['values'][$section . '_format']);
1640          if ($section != 'empty') {
1641            $this->set_option($section . '_empty', $form_state['values'][$section . '_empty']);
1642          }
1643          break;
1644        case 'exposed_block':
1645          $this->set_option($section, (bool) $form_state['values'][$section]);
1646          break;
1647      }
1648    }
1649  
1650    /**
1651     * Add an override button for a given section, allowing the user to
1652     * change whether this info is stored on the default display or on
1653     * the current display.
1654     */
1655    function add_override_button(&$form, &$form_state, $section) {
1656      if ($this->is_default_display()) {
1657        return;
1658      }
1659  
1660      $form['override'] = array(
1661        '#prefix' => '<div class="views-override clear-block">',
1662        '#suffix' => '</div>',
1663      );
1664      if ($this->is_defaulted($section)) {
1665        $form['override']['button'] = array(
1666          '#type' => 'submit',
1667          '#value' => t('Override'),
1668          '#submit' => array('views_ui_edit_display_form_override'),
1669        );
1670        $form['override']['markup'] = array(
1671          '#prefix' => '<div class="description">',
1672          '#value' => theme('advanced_help_topic', 'views', 'overrides') . t('Status: using default values.'),
1673          '#suffix' => '</div>',
1674        );
1675  
1676        $form_state['update_name'] = t('Update default display');
1677      }
1678      else {
1679        $form['override']['button'] = array(
1680          '#type' => 'submit',
1681          '#value' => t('Use default'),
1682          '#submit' => array('views_ui_edit_display_form_override'),
1683        );
1684        $form['override']['markup'] = array(
1685          '#prefix' => '<div class="description">',
1686          '#value' => theme('advanced_help_topic', 'views', 'overrides') . t('Status: using overridden values.'),
1687          '#suffix' => '</div>',
1688        );
1689  
1690        $form_state['update_name'] = NULL;
1691      }
1692    }
1693  
1694    /**
1695     * If override/revert was clicked, perform the proper toggle.
1696     */
1697    function options_override($form, &$form_state) {
1698      $this->set_override($form_state['section']);
1699    }
1700  
1701    /**
1702     * Flip the override setting for the given section.
1703     */
1704    function set_override($section, $new_state = NULL) {
1705      $options = $this->defaultable_sections($section);
1706      if (!$options) {
1707        return;
1708      }
1709  
1710      if (!isset($new_state)) {
1711        $new_state = empty($this->options['defaults'][$section]);
1712      }
1713  
1714      // For each option that is part of this group, fix our settings.
1715      foreach ($options as $option) {
1716        if ($new_state) {
1717          // Revert to defaults.
1718          unset($this->options[$option]);
1719          unset($this->display->display_options[$option]);
1720        }
1721        else {
1722          // copy existing values into our display.
1723          $this->options[$option] = $this->get_option($option);
1724          $this->display->display_options[$option] = $this->options[$option];
1725        }
1726        $this->options['defaults'][$option] = $new_state;
1727        $this->display->display_options['defaults'][$option] = $new_state;
1728      }
1729    }
1730  
1731    /**
1732     * Inject anything into the query that the display handler needs.
1733     */
1734    function query() {
1735      // Make the query distinct if the option was set.
1736      if ($this->get_option('distinct')) {
1737        $this->view->query->set_distinct();
1738      }
1739    }
1740  
1741    /**
1742     * Not all display plugins will support filtering
1743     */
1744    function render_filters() { }
1745  
1746    /**
1747     * Render the 'more' link
1748     */
1749    function render_more_link() {
1750      if ($this->use_more() && ($this->use_more_always() || !isset($this->view->total_rows) || $this->view->total_rows > $this->view->pager['items_per_page'])) {
1751        $path = $this->get_path();
1752        if ($path) {
1753          $path = $this->view->get_url(NULL, $path);
1754          $url_options = array();
1755          if (!empty($this->view->exposed_raw_input)) {
1756            $url_options['query'] = $this->view->exposed_raw_input;
1757          }
1758          $theme = views_theme_functions('views_more', $this->view, $this->display);
1759          $path = check_url(url($path, $url_options));
1760          return theme($theme, $path, check_plain($this->use_more_text()));
1761        }
1762      }
1763    }
1764  
1765    /**
1766     * Render a text area, using the proper format.
1767     */
1768    function render_textarea($area) {
1769      static $formats = array();
1770  
1771      $value = $this->get_option($area);
1772      // Check to make sure the filter format exists; if not, we don't
1773      // display anything.
1774      $format = filter_resolve_format($this->get_option($area . '_format'));
1775  
1776      if (!array_key_exists($format, $formats)) {
1777        $formats[$format] = db_result(db_query("SELECT name FROM {filter_formats} WHERE format = %d", $format));
1778      }
1779  
1780      if (!$formats[$format]) {
1781        return;
1782      }
1783  
1784      if ($value) {
1785        return check_markup($value, $format, FALSE);
1786      }
1787    }
1788  
1789    /**
1790     * Render the header of the view.
1791     */
1792    function render_header() {
1793      if (!empty($this->view->result) || $this->get_option('header_empty')) {
1794        return $this->render_textarea('header');
1795      }
1796    }
1797  
1798    /**
1799     * Render the footer of the view.
1800     */
1801    function render_footer() {
1802      if (!empty($this->view->result) || $this->get_option('footer_empty')) {
1803        return $this->render_textarea('footer');
1804      }
1805    }
1806  
1807    /**
1808     * Render the empty text of the view.
1809     */
1810    function render_empty() { return $this->render_textarea('empty'); }
1811    /**
1812     * If this display creates a block, implement one of these.
1813     */
1814    function hook_block($op = 'list', $delta = 0, $edit = array()) { return array(); }
1815  
1816    /**
1817     * If this display creates a page with a menu item, implement it here.
1818     */
1819    function hook_menu() { return array(); }
1820  
1821    /**
1822     * Render this display.
1823     */
1824    function render() {
1825      return theme($this->theme_functions(), $this->view);
1826    }
1827  
1828    /**
1829     * Determine if the user has access to this display of the view.
1830     */
1831    function access($account = NULL) {
1832      if (!isset($account)) {
1833        global $user;
1834        $account = $user;
1835      }
1836  
1837      // Full override.
1838      if (user_access('access all views', $account)) {
1839        return TRUE;
1840      }
1841  
1842      $plugin = $this->get_access_plugin();
1843      if ($plugin) {
1844        return $plugin->access($account);
1845      }
1846  
1847      // fallback to all access if no plugin.
1848      return TRUE;
1849    }
1850  
1851    /**
1852     * Set up any variables on the view prior to execution. These are separated
1853     * from execute because they are extremely common and unlikely to be
1854     * overridden on an individual display.
1855     */
1856    function pre_execute() {
1857      $this->view->set_use_ajax($this->use_ajax());
1858      // Copy pager information from the display.
1859      $this->view->set_use_pager($this->use_pager());
1860      $this->view->set_pager_element($this->get_option('pager_element'));
1861      $this->view->set_items_per_page($this->get_option('items_per_page'));
1862      $this->view->set_offset($this->get_option('offset'));
1863      if ($this->use_more()) {
1864        $this->view->get_total_rows = TRUE;
1865      }
1866    }
1867  
1868    /**
1869     * When used externally, this is how a view gets run and returns
1870     * data in the format required.
1871     *
1872     * The base class cannot be executed.
1873     */
1874    function execute() { }
1875  
1876    /**
1877     * Fully render the display for the purposes of a live preview or
1878     * some other AJAXy reason.
1879     */
1880    function preview() { return $this->view->render(); }
1881  
1882    /**
1883     * Displays can require a certain type of style plugin. By default, they will
1884     * be 'normal'.
1885     */
1886    function get_style_type() { return 'normal'; }
1887  
1888    /**
1889     * Make sure the display and all associated handlers are valid.
1890     *
1891     * @return
1892     *   Empty array if the display is valid; an array of error strings if it is not.
1893     */
1894    function validate() {
1895      $errors = array();
1896      // Make sure displays that use fields HAVE fields.
1897      if ($this->uses_fields()) {
1898        $fields = FALSE;
1899        foreach ($this->get_handlers('field') as $field) {
1900          if (empty($field->options['exclude'])) {
1901            $fields = TRUE;
1902          }
1903        }
1904  
1905        if (!$fields) {
1906          $errors[] = t('Display "@display" uses fields but there are none defined for it or all are excluded.', array('@display' => $this->display->display_title));
1907        }
1908      }
1909  
1910      if ($this->has_path() && !$this->get_option('path')) {
1911        $errors[] = t('Display "@display" uses a path but the path is undefined.', array('@display' => $this->display->display_title));
1912      }
1913  
1914      // Validate style plugin
1915      $style = $this->get_plugin();
1916      if (empty($style)) {
1917        $errors[] = t('Display "@display" has an invalid style plugin.', array('@display' => $this->display->display_title));
1918      }
1919      else {
1920        $result = $style->validate();
1921        if (!empty($result) && is_array($result)) {
1922          $errors = array_merge($errors, $result);
1923        }
1924      }
1925  
1926      // Validate handlers
1927      foreach (views_object_types() as $type => $info) {
1928        foreach ($this->get_handlers($type) as $handler) {
1929          $result = $handler->validate();
1930          if (!empty($result) && is_array($result)) {
1931            $errors = array_merge($errors, $result);
1932          }
1933        }
1934      }
1935  
1936      return $errors;
1937    }
1938  
1939    /**
1940     * Check if the provided identifier is unique.
1941     */
1942    function is_identifier_unique($id, $identifier) {
1943      foreach (views_object_types() as $type => $info) {
1944        foreach ($this->get_handlers($type) as $key => $handler) {
1945          if ($handler->can_expose() && $handler->is_exposed()) {
1946            if ($id != $key && $identifier == $handler->options['expose']['identifier']) {
1947              return FALSE;
1948            }
1949          }
1950        }
1951      }
1952      return TRUE;
1953    }
1954  
1955    /**
1956     * Provide the block system with any exposed widget blocks for this display.
1957     */
1958    function get_special_blocks() {
1959      $delta = '-exp-' . $this->view->name . '-' . $this->display->id;
1960      $desc = t('Exposed form: @view-@display_id', array('@view' => $this->view->name, '@display_id' => $this->display->id));
1961  
1962      return array(
1963        $delta => array(
1964          'info' => $desc,
1965        )
1966      );
1967    }
1968  
1969    /**
1970     * Render any special blocks provided for this display.
1971     */
1972    function view_special_blocks($type) {
1973      if ($type == '-exp') {
1974        // avoid interfering with the admin forms.
1975        if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views') {
1976          return;
1977        }
1978        $this->view->init_handlers();
1979        return array(
1980          'content' => $this->view->render_exposed_form(TRUE),
1981        );
1982      }
1983    }
1984  
1985  }
1986  
1987  
1988  /**
1989   * @}
1990   */
1991  


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7