You are here

class views_plugin_display_system in Administration Views 7

Same name and namespace in other branches
  1. 6 plugins/views_plugin_display_system.inc \views_plugin_display_system

Plugin to handle replacement of existing system paths.

The System display is mostly identical to Views' native Page display. The only differences are:

  • No menu link options.
  • No tab/local task options.

These options make no sense, because the System display is supposed to replace the main page output of an existing system path only. This plugin code should therefore always be kept in sync with the Page display plugin code (excluding the support code for the removed functionality).

To achieve a correct replacement of an existing system path, execute_hook_menu() performs some advanced processing on menu router definitions to account for possible child router items that would normally inherit properties of the original system path.

Hierarchy

Expanded class hierarchy of views_plugin_display_system

See also

views_plugin_display_page

views_plugin_display_system::execute_hook_menu()

1 string reference to 'views_plugin_display_system'
admin_views_system_display_views_plugins in ./admin_views.views.inc
Implements hook_views_plugins().

File

plugins/views_plugin_display_system.inc, line 31
System display plugin.

View source
class views_plugin_display_system extends views_plugin_display {

  /**
   * The system display requires a path.
   */
  function has_path() {
    return TRUE;
  }

  /**
   * The system display uses breadcrumbs.
   */
  function uses_breadcrumb() {
    return TRUE;
  }

  /**
   * Overrides views_plugin_display::option_definition().
   */
  function option_definition() {
    $options = parent::option_definition();
    $options['path'] = array(
      'default' => '',
    );

    // Override the access plugin to always enforce views_plugin_access_menu.
    // The UI widget for configuring access is additionally hidden.
    // @see options_summary()
    $options['defaults']['default']['access'] = FALSE;
    $options['access'] = array(
      // This isn't actually used, but we set it to a reasonable value, in case
      // this gets cloned to a display of a different type.
      'default' => array(
        'type' => 'perm',
        'perm' => 'use admin views system display ajax pages',
      ),
    );
    return $options;
  }

  /**
   * Overrides views_plugin_display::options_summary().
   */
  function options_summary(&$categories, &$options) {
    parent::options_summary($categories, $options);
    $categories['system'] = array(
      'title' => t('System path settings'),
    );

    // Disable the access plugin configuration in the UI.
    // @see option_definition()
    $categories['access']['build']['#access'] = FALSE;
    $path = strip_tags('/' . $this
      ->get_option('path'));
    if (empty($path)) {
      $path = t('None');
    }
    $options['path'] = array(
      'category' => 'system',
      'title' => t('Path'),
      'value' => views_ui_truncate($path, 24),
    );
  }

  /**
   * Overrides views_plugin_display::options_form().
   */
  function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);
    switch ($form_state['section']) {
      case 'path':
        $form['#title'] .= t('An existing menu path this view replaces');
        $form['path'] = array(
          '#type' => 'textfield',
          '#description' => t('This view replaces this path on your site. You may use "%" in your URL to represent values that will be used for contextual filters. For example: "node/%/feed". The path must not be used by another enabled system view, otherwise conflicts will occur and <em>user_access()</em> notices displayed.'),
          '#default_value' => $this
            ->get_option('path'),
          '#field_prefix' => '<span dir="ltr">' . url(NULL, array(
            'absolute' => TRUE,
          )) . (variable_get('clean_url', 0) ? '' : '?q='),
          '#field_suffix' => '</span>&lrm;',
          '#attributes' => array(
            'dir' => 'ltr',
          ),
        );
        break;
    }
  }

  /**
   * Overrides views_plugin_display::options_validate().
   */
  function options_validate(&$form, &$form_state) {
    parent::options_validate($form, $form_state);
    switch ($form_state['section']) {
      case 'path':
        if (strpos($form_state['values']['path'], '$arg') !== FALSE) {
          form_error($form['path'], t('"$arg" is no longer supported. Use % instead.'));
        }
        if (strpos($form_state['values']['path'], '%') === 0) {
          form_error($form['path'], t('"%" may not be used for the first segment of a path.'));
        }

        // Automatically remove '/' from path.
        $form_state['values']['path'] = trim($form_state['values']['path'], '/');
        $system_view[$form_state['values']['path']] = array(
          $this->view->name => $this->view->current_display,
        );
        if (admin_views_duplicate_path($system_view)) {
          form_error($form['path'], t('Already used by another system view. Enter a different path.'));
        }
        break;
    }
  }

  /**
   * Overrides views_plugin_display::options_submit().
   */
  function options_submit(&$form, &$form_state) {
    parent::options_submit($form, $form_state);
    switch ($form_state['section']) {
      case 'path':
        $this
          ->set_option('path', $form_state['values']['path']);
        break;
    }
  }

  /**
   * Add this display's path information to Drupal's menu system.
   *
   * @param array $callbacks
   *   All existing menu router items defined by modules. Taken by reference, in
   *   order to adjust any possibly existing child router items of the replaced
   *   system path. (This method only returns new router items normally.)
   */
  function execute_hook_menu(&$callbacks) {
    $items = array();

    // Replace % with the link to our standard views argument loader
    // views_arg_load().
    $bits = explode('/', $this
      ->get_option('path'));
    $page_arguments = array(
      $this->view->name,
      $this->display->id,
    );
    $this->view
      ->init_handlers();
    $view_arguments = $this->view->argument;

    // Replace % with %views_arg for menu autoloading and add to the
    // page arguments so the argument actually comes through.
    foreach ($bits as $pos => $bit) {
      if ($bit == '%') {
        $argument = array_shift($view_arguments);
        if (!empty($argument->options['specify_validation']) && $argument->options['validate']['type'] != 'none') {
          $bits[$pos] = '%views_arg';
        }
        $page_arguments[] = $pos;
      }
    }
    $path = implode('/', $bits);
    if (!$path) {
      return $items;
    }

    // Only existing system paths can be replaced.
    if (!isset($callbacks[$path])) {

      // However, if the specified path contains dynamic argument placeholders,
      // then we need to search more carefully.
      $views_path = $this
        ->get_option('path');
      if (strpos($views_path, '%') !== FALSE) {
        $views_path = preg_quote($views_path, '@');
        $views_path = strtr($views_path, array(
          '%' => '%[^/]*',
        ));
        $result = preg_grep('@^' . $views_path . '$@', array_keys($callbacks));
        if ($result) {
          $parent_path = reset($result);
          $parent =& $callbacks[$parent_path];
        }
        else {
          return $items;
        }
      }
      else {
        return $items;
      }
    }
    else {
      $parent =& $callbacks[$path];
    }

    // Work out whether we need to get the access callback and arguments from
    // the parent item.
    $default_map = array(
      'access callback' => 'user_access',
      'access arguments' => array(),
    );
    foreach ($default_map as $menu_key => &$default) {

      // Override the default if we can. Otherwise this will use the defaults
      // above.
      if (!empty($callbacks[$path][$menu_key])) {
        $default = $callbacks[$path][$menu_key];
      }
      elseif (!empty($parent[$menu_key])) {
        $default = $parent[$menu_key];
      }
    }
    $items[$path] = array(
      // default views page entry
      'page callback' => 'views_page',
      'page arguments' => $page_arguments,
      // Take over the access definition from the original router item.
      // @see option_definition()
      // @see views_plugin_access_menu
      'access callback' => $default_map['access callback'],
      'access arguments' => $default_map['access arguments'],
      // Identify URL embedded arguments and correlate them to a handler
      'load arguments' => array(
        $this->view->name,
        $this->display->id,
        '%index',
      ),
    );

    // List of router item default property values, which are inherited to
    // children. These default values are only applied if the original parent
    // item does not define them (see below).
    // @see _menu_router_build()
    $defaults = array(
      'access callback' => 'user_access',
      'menu_name' => NULL,
      'file' => NULL,
      'file path' => NULL,
      'delivery callback' => NULL,
      'theme callback' => NULL,
      'theme arguments' => array(),
    );

    // Grep all router items below the target path.
    $num_parent_parts = count(explode('/', $path));
    $children = preg_grep('@^' . preg_quote($path, '@') . '/@', array_keys($callbacks));

    // Ensure correct inheritance of properties on the original parent path
    // (being replaced) to child items.
    foreach ($children as $child_path) {

      // Only apply property inheritance to direct children of the parent path.
      $num_child_parts = count(explode('/', $child_path));
      if ($num_parent_parts == $num_child_parts - 1) {

        // Check if the child router item is a views page. If so, there are
        // default properties we do not want this item to inherit.
        if (isset($callbacks[$child_path]['page callback']) && $callbacks[$child_path]['page callback'] === 'views_page') {
          continue;
        }
        $child =& $callbacks[$child_path];

        // Get these first, as we want to know if they existed before parent and
        // default values are merged.
        $file = isset($child['file']);
        $access_callback = isset($child['access callback']);

        // Copy all properties from the original parent that will be replaced
        // with new values.
        // This typically resets 'access arguments', etc.
        $child += array_intersect_key($parent, $items[$path]);

        // Copy all properties from the original parent, for which the router
        // system would inherit parent values or fill in default values.
        // This typically adds back 'file' and other properties defined on the
        // parent but not on $items[$path]. (The two operations could be
        // combined with $items[$path] + $defaults, but are separated for
        // documentation purposes and clarity.)
        $child += array_intersect_key($parent, $defaults);

        // Unset the child 'file' property if its implementing module doesn't
        // match it's parent and it didn't have a 'file' preoperty specified
        // before. Otherwise, for example, example_module could inherit a 'file'
        // property of 'node.admin.inc', so the actual include path would be
        // something like .../modules/example_module/node.admin.inc.
        if (!$file && isset($child['module'], $parent['module']) && $child['module'] != $parent['module']) {
          unset($child['file']);
        }

        // The access callback should only be inherited for default local tasks.
        // Ensure it hasn't been mistakenly set.
        if (!$access_callback && (!isset($child['type']) || $child['type'] != MENU_DEFAULT_LOCAL_TASK)) {
          unset($child['access callback']);
        }

        // Last catch-22, insert new default properties and their default values
        // for the child, which may not be defined on the original parent.
        // This typically inserts 'access callback', which can be omitted in
        // router item definitions and only gets a default of user_access() in
        // the final _menu_router_build(). Without this, the new access callback
        // views_access() in $items[$path] would be inherited to all children.
        $child += $defaults;
      }
    }

    // If the original parent path already existed, copy over its remaining
    // properties.
    $items[$path] += $parent;
    return $items;
  }

  /**
   * Overrides views_plugin_display::execute().
   *
   * Build and render the page view.
   *
   * Since we replace an existing page, we need to invoke views_set_page_view().
   * Also set the page title, because original page callbacks might do this.
   */
  function execute() {

    // Let the world know that this is the page view we're using.
    views_set_page_view($this->view);

    // Prior to this being called, the $view should already be set to this
    // display, and arguments should be set on the view.
    $this->view
      ->build();
    if (!empty($this->view->build_info['fail'])) {
      return drupal_not_found();
    }
    if (!empty($this->view->build_info['denied'])) {
      return drupal_access_denied();
    }
    drupal_add_css(drupal_get_path('module', 'admin_views_system_display') . '/admin_views_system_display.css');
    return $this->view
      ->render();
  }

  /**
   * Overrides views_plugin_display::get_argument_text().
   */
  function get_argument_text() {
    return array(
      'filter value not present' => t('When the filter value is <em>NOT</em> in the URL'),
      'filter value present' => t('When the filter value <em>IS</em> in the URL or a default is provided'),
      'description' => t('The contextual filter values is provided by the URL.'),
    );
  }

}

Members

Namesort descending Modifiers Type Description Overrides
views_object::$definition public property Handler's definition.
views_object::$options public property Except for displays, options for the object will be held here. 1
views_object::altered_option_definition function Collect this handler's option definition and alter them, ready for use.
views_object::construct public function Views handlers use a special construct function. 4
views_object::export_options public function
views_object::export_option_always public function Always exports the option, regardless of the default value.
views_object::options Deprecated public function Set default options on this object. 1
views_object::set_default_options public function Set default options.
views_object::set_definition public function Let the handler know what its full definition is.
views_object::unpack_options public function Unpack options over our existing defaults, drilling down into arrays so that defaults don't get totally blown away.
views_object::unpack_translatable public function Unpack a single option definition.
views_object::unpack_translatables public function Unpacks each handler to store translatable texts.
views_object::_set_option_defaults public function
views_plugin::$display public property The current used views display.
views_plugin::$plugin_name public property The plugin name of this plugin, for example table or full.
views_plugin::$plugin_type public property The plugin type of this plugin, for example style or query.
views_plugin::additional_theme_functions public function Provide a list of additional theme functions for the theme info page.
views_plugin::plugin_title public function Return the human readable name of the display.
views_plugin::summary_title public function Returns the summary of the settings in the display. 8
views_plugin::theme_functions public function Provide a full list of possible theme templates used by this style.
views_plugin_display::$extender public property Stores all available display extenders.
views_plugin_display::$handlers public property List of handlers for this display.
views_plugin_display::$view public property The top object of a view. Overrides views_plugin::$view
views_plugin_display::accept_attachments public function Can this display accept attachments?
views_plugin_display::access public function Determine if the user has access to this display of the view.
views_plugin_display::attach_to public function Allow displays to attach to other views. 2
views_plugin_display::defaultable_sections public function List which sections are defaultable and what items each section contains. 1
views_plugin_display::destroy public function Destructor. Overrides views_object::destroy
views_plugin_display::displays_exposed public function Determine if this display should display the exposed filters widgets. 1
views_plugin_display::export_handler public function Special method to export items that have handlers.
views_plugin_display::export_option public function Override of export_option() Overrides views_object::export_option
views_plugin_display::export_plugin public function Special handling for plugin export.
views_plugin_display::export_style public function Special handling for the style export.
views_plugin_display::format_themes public function Format a list of theme templates for output by the theme info helper.
views_plugin_display::get_arguments_tokens public function Returns to tokens for arguments.
views_plugin_display::get_field_labels public function List of fields for the current display with the associated relationship.
views_plugin_display::get_handler public function Get the handler object for a single handler.
views_plugin_display::get_handlers public function Get a full array of handlers for $type. This caches them.
views_plugin_display::get_link_display public function Check to see which display to use when creating links.
views_plugin_display::get_option public function Intelligently get an option either from this or default display.
views_plugin_display::get_pager_text public function Provide some helpful text for pagers. 1
views_plugin_display::get_path public function Return the base path to use for this display.
views_plugin_display::get_plugin public function Get the instance of a plugin, for example style or row.
views_plugin_display::get_special_blocks public function Provide the block system with any exposed widget blocks for this display.
views_plugin_display::get_style_type public function Displays can require a certain type of style plugin. 1
views_plugin_display::get_url public function
views_plugin_display::hook_block_list public function If this display creates a block, implement one of these.
views_plugin_display::hook_menu public function If this display creates a page with a menu item, implement it here.
views_plugin_display::init public function 1
views_plugin_display::is_defaulted public function Determine if a given option is set to use the default or current display.
views_plugin_display::is_default_display public function If this display is the 'default' display which contains fallback settings. 1
views_plugin_display::is_identifier_unique public function Check if the provided identifier is unique.
views_plugin_display::options_override public function If override/revert was clicked, perform the proper toggle.
views_plugin_display::option_link public function Because forms may be split up into sections, this provides an easy URL to exactly the right section. Don't override this.
views_plugin_display::override_option public function Set an option and force it to be an override.
views_plugin_display::preview public function Fully render the display. 1
views_plugin_display::pre_execute public function Set up any variables on the view prior to execution.
views_plugin_display::query public function Inject anything into the query that the display handler needs. Overrides views_plugin::query
views_plugin_display::render public function Render this display. 1
views_plugin_display::render_area public function
views_plugin_display::render_empty public function
views_plugin_display::render_filters public function Not all display plugins will support filtering.
views_plugin_display::render_footer public function Render the footer of the view.
views_plugin_display::render_header public function Render the header of the view.
views_plugin_display::render_more_link public function Render the 'more' link.
views_plugin_display::render_pager public function Not all display plugins will suppert pager rendering. 1
views_plugin_display::set_option public function Intelligently set an option either from this display or from the default display, if directed to do so.
views_plugin_display::set_override public function Flip the override setting for the given section.
views_plugin_display::unpack_handler public function Special method to unpack items that have handlers.
views_plugin_display::unpack_plugin public function Special handling for plugin unpacking.
views_plugin_display::unpack_style public function
views_plugin_display::uses_exposed public function Does this display uses exposed filters? 2
views_plugin_display::uses_exposed_form_in_block public function Check to see if the display can put the exposed form in a block.
views_plugin_display::uses_fields public function Determine if the display's style uses fields.
views_plugin_display::uses_link_display public function Check to see if the display has some need to link to another display. 1
views_plugin_display::use_ajax public function Does the display use AJAX?
views_plugin_display::use_group_by public function Does the display have groupby enabled?
views_plugin_display::use_more public function Does the display have a more link enabled?
views_plugin_display::use_more_always public function Should the enabled display more link be shown when no more items?
views_plugin_display::use_more_open_new_window public function Should the enabled display more link being opened in an new window?
views_plugin_display::use_more_text public function Does the display have custom link text?
views_plugin_display::use_pager public function Does the display have a pager enabled? 1
views_plugin_display::validate public function Make sure the display and all associated handlers are valid. Overrides views_plugin::validate 1
views_plugin_display::view_special_blocks public function Render any special blocks provided for this display.
views_plugin_display_system::execute function Overrides views_plugin_display::execute(). Overrides views_plugin_display::execute
views_plugin_display_system::execute_hook_menu function Add this display's path information to Drupal's menu system.
views_plugin_display_system::get_argument_text function Overrides views_plugin_display::get_argument_text(). Overrides views_plugin_display::get_argument_text
views_plugin_display_system::has_path function The system display requires a path. Overrides views_plugin_display::has_path
views_plugin_display_system::options_form function Overrides views_plugin_display::options_form(). Overrides views_plugin_display::options_form
views_plugin_display_system::options_submit function Overrides views_plugin_display::options_submit(). Overrides views_plugin_display::options_submit
views_plugin_display_system::options_summary function Overrides views_plugin_display::options_summary(). Overrides views_plugin_display::options_summary
views_plugin_display_system::options_validate function Overrides views_plugin_display::options_validate(). Overrides views_plugin_display::options_validate
views_plugin_display_system::option_definition function Overrides views_plugin_display::option_definition(). Overrides views_plugin_display::option_definition
views_plugin_display_system::uses_breadcrumb function The system display uses breadcrumbs. Overrides views_plugin_display::uses_breadcrumb