[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

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

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


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7