You are here

panels_views.module in Panels 6.2

Same filename and directory in other branches
  1. 5.2 panels_views/panels_views.module

panels_views.module

Provides views as panels content, configurable by the administrator. Each view provided as panel content must be configured in advance, but once configured, building panels with views is a little bit simpler.

File

panels_views/panels_views.module
View source
<?php

/**
 * @file panels_views.module
 *
 * Provides views as panels content, configurable by the administrator.
 * Each view provided as panel content must be configured in advance,
 * but once configured, building panels with views is a little bit simpler.
 */

/**
 * Implementation of hook_menu().
 */
function panels_views_menu() {
  $items = array();
  $base = array(
    'access arguments' => array(
      'administer panel views',
    ),
    'file' => 'panels_views.admin.inc',
  );
  $items['admin/panels/views'] = array(
    'title' => 'Views panes',
    'type' => MENU_NORMAL_ITEM,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'panels_views_admin_page',
    ),
    'description' => 'Configure Views to be used as panes within panel displays.',
  ) + $base;
  return $items;
}

/**
 * Implementation of hook_panels_content_types()
 */
function panels_views_panels_content_types() {

  // Only valid if views module loaded.
  $items['views'] = array(
    'title' => t('All views'),
    'content_types' => 'panels_views_all_views_content_types',
    'render callback' => 'panels_views_all_views_render',
    'add callback' => 'panels_views_all_views_add',
    'edit callback' => 'panels_views_all_views_edit',
    'title callback' => 'panels_views_all_views_title',
  );
  $items['views_panes'] = array(
    'title' => t('Views panes'),
    'content_types' => 'panels_views_panes_content_types',
    'render callback' => 'panels_views_panes_render',
    'add callback' => 'panels_views_panes_edit',
    'edit callback' => 'panels_views_panes_edit',
    'title callback' => 'panels_views_panes_title',
  );
  return $items;
}

/**
 * Return all content types available.
 */
function panels_views_all_views_content_types() {
  $types = array();
  $views = views_get_all_views();
  foreach ($views as $view) {
    $view
      ->init_display();
    foreach ($view->display as $id => $display) {
      $title = t('@name: @display', array(
        '@name' => $view->name,
        '@display' => $display->display_title,
      ));
      $icon = $display->display_plugin != 'page' ? 'icon_views_block_legacy.png' : 'icon_views_page_legacy.png';
      $contexts = array();
      if (isset($display->handler) && ($arguments = $display->handler
        ->get_handlers('argument'))) {
        foreach ($arguments as $arg) {
          $contexts[] = new panels_optional_context($arg
            ->ui_name(), 'any');
        }
      }
      $types[$view->name . '-' . $id] = array(
        'title' => $title,
        'icon' => $icon,
        'description' => filter_xss_admin($view->description),
        'required context' => $contexts,
        'category' => array(
          t('Views'),
          -1,
        ),
      );
    }
  }
  return $types;
}

/**
 * Output function for the 'views' content type.
 *
 * Outputs a view based on the module and delta supplied in the configuration.
 */
function panels_views_all_views_render($subtype, $conf, $panel_args, $contexts) {
  if (!is_array($contexts)) {
    $contexts = array(
      $contexts,
    );
  }
  list($name, $display) = explode('-', $subtype);
  $view = views_get_view($name);
  if (empty($view)) {
    return;
  }
  $view
    ->set_display($display);
  if (!$view->display_handler
    ->access($GLOBALS['user'])) {
    return;
  }
  $arguments = explode('/', $_GET['q']);
  $args = $conf['args'];
  foreach ($arguments as $id => $arg) {
    $args = str_replace("%{$id}", $arg, $args);
  }
  foreach ($panel_args as $id => $arg) {
    $args = str_replace("@{$id}", $arg, $args);
  }
  $args = preg_replace(',/?(%\\d|@\\d),', '', $args);
  $args = $args ? explode('/', $args) : array();
  if ($conf['panel_args'] && is_array($panel_args)) {
    $args = array_merge($panel_args, $args);
  }
  if (is_array($conf['context'])) {
    foreach ($conf['context'] as $count => $cid) {
      if ($cid != 'any' && !empty($contexts[$count]) && isset($contexts[$count]->argument)) {
        array_splice($args, $count, 0, array(
          $contexts[$count]->argument,
        ));
      }
    }
  }
  $view
    ->set_arguments($args);
  if ($conf['url']) {
    $view->display_handler
      ->set_option('path', $conf['url']);
  }
  $block = new stdClass();
  $block->module = 'views';
  $block->delta = $view->name . $display;
  $block->subject = $view
    ->get_title();
  if (!empty($conf['link_to_view'])) {
    $block->title_link = $view
      ->get_url();
  }
  if (!empty($conf['more_link'])) {
    $block->more = array(
      'href' => $view
        ->get_url(),
    );
    $view->display_handler
      ->set_option('use_more', FALSE);
  }
  $view->display_handler
    ->set_option('use_pager', $conf['use_pager']);
  $view->display_handler
    ->set_option('pager_element', $conf['pager_id']);
  $view->display_handler
    ->set_option('items_per_page', $conf['nodes_per_page']);
  $view->display_handler
    ->set_option('offset', $conf['offset']);
  $stored_feeds = drupal_add_feed();
  $block->content = $view
    ->preview();
  if (!empty($conf['feed_icons'])) {
    $new_feeds = drupal_add_feed();
    if ($diff = array_diff(array_keys($new_feeds), array_keys($stored_feeds))) {
      foreach ($diff as $url) {
        $block->feeds[$url] = $new_feeds[$url];
      }
    }
  }
  return $block;
}

/**
 * Returns the form for a new view.
 */
function panels_views_all_views_add($id, $parents, $conf = array()) {
  list($name, $display_id) = explode('-', $id);
  $view = views_get_view($name);
  if (!$view) {
    return;
  }
  $view
    ->set_display($display_id);
  $conf['nodes_per_page'] = $view->display_handler
    ->get_option('items_per_page');
  $conf['pager_id'] = 1;
  $conf['use_pager'] = 0;
  $conf['more_link'] = 0;
  $conf['feed_icons'] = 0;
  $conf['offset'] = 0;
  $conf['panel_args'] = FALSE;
  $conf['link_to_view'] = FALSE;
  $conf['args'] = '';
  $conf['url'] = '';
  return panels_views_all_views_edit($id, $parents, $conf);
}

/**
 * Returns an edit form for a block.
 */
function panels_views_all_views_edit($id, $parents, $conf) {
  $form['link_to_view'] = array(
    '#type' => 'checkbox',
    '#default_value' => $conf['link_to_view'],
    '#title' => t('Link title to view'),
    '#description' => t('If checked, the title will be a link to the view.'),
  );
  $form['more_link'] = array(
    '#type' => 'checkbox',
    '#default_value' => $conf['more_link'],
    '#title' => t('Provide a "more" link that links to the view'),
    '#description' => t('This is independent of any more link that may be provided by the view itself; if you see two more links, turn this one off. Views will only provide a more link if using the "block" type, however, so if using embed, use this one.'),
  );
  $form['feed_icons'] = array(
    '#type' => 'checkbox',
    '#default_value' => $conf['feed_icons'],
    '#title' => t('Display feed icons'),
    '#description' => t('If checked, any feed icons provided by this view will be displayed.'),
  );
  $form['pager_aligner_start'] = array(
    '#value' => '<div class="option-text-aligner">',
  );
  $form['use_pager'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use pager'),
    '#default_value' => $conf['use_pager'],
    '#id' => 'use-pager-checkbox',
  );
  $form['pager_id'] = array(
    '#type' => 'textfield',
    '#default_value' => $conf['pager_id'],
    '#title' => t('Pager ID'),
    '#size' => 4,
    '#id' => 'use-pager-textfield',
  );
  $form['pager_aligner_stop'] = array(
    '#value' => '</div><div style="clear: both; padding: 0; margin: 0"></div>',
  );
  $form['nodes_per_page'] = array(
    '#type' => 'textfield',
    '#default_value' => $conf['nodes_per_page'],
    '#title' => t('Num posts'),
    '#size' => 4,
    '#description' => t('Select the number of posts to display, or 0 to display all results.'),
  );
  $form['offset'] = array(
    '#type' => 'textfield',
    '#default_value' => $conf['offset'],
    '#title' => t('Offset'),
    '#size' => 4,
    '#description' => t('Offset in the node list or 0 to start at 1st item.'),
  );
  $form['panel_args'] = array(
    '#type' => 'checkbox',
    '#title' => t('Send arguments'),
    '#default_value' => $conf['panel_args'],
    '#description' => t('Select this to send all arguments from the panel directly to the view. If checked, the panel arguments will come after any context arguments above and precede any additional arguments passed in through the Arguments field below.'),
  );
  $form['args'] = array(
    '#type' => 'textfield',
    '#default_value' => $conf['args'],
    '#title' => t('Arguments'),
    '#size' => 30,
    '#description' => t('Additional arguments to send to the view as if they were part of the URL in the form of arg1/arg2/arg3. You may use %0, %1, ..., %N to grab arguments from the URL. Or use @0, @1, @2, ..., @N to use arguments passed into the panel.'),
  );
  $form['url'] = array(
    '#type' => 'textfield',
    '#default_value' => $conf['url'],
    '#title' => t('Override URL'),
    '#size' => 30,
    '#description' => t('If this is set, override the View URL; this can sometimes be useful to set to the panel URL'),
  );
  return $form;
}

/**
 * Returns the administrative title for a type.
 */
function panels_views_all_views_title($subtype, $conf) {
  list($name, $display) = explode('-', $subtype);
  $view = views_get_view($name);
  if (empty($view)) {
    return t('Deleted/missing view @view', array(
      '@view' => $name,
    ));
  }
  if (empty($view->display[$display])) {
    return t('Deleted/missing view @view', array(
      '@view' => $name,
    ));
  }
  return t('@name: @display', array(
    '@name' => $view->name,
    '@display' => $view->display[$display]->display_title,
  ));
}

/**
 * Don't show Views' blocks; we expose them already.
 */
function views_panels_block_info($module, $delta, &$info) {
  $info = NULL;
}

// --------------------------------------------------------------------------
// Panels functions for the panel pane display plugin.

/**
 * Return all views that have panel pane displays on them.
 */
function panels_views_panes_content_types() {
  $types = array();
  $views = views_get_all_views();
  foreach ($views as $view) {
    $view
      ->init_display();
    foreach ($view->display as $id => $display) {
      if (empty($display->handler->panel_pane_display)) {
        continue;
      }
      $title = $display->handler
        ->get_option('pane_title');
      if (!$title) {
        $title = $view->name;
      }
      $description = $display->handler
        ->get_option('pane_description');
      if (!$description) {
        $description = $view->description;
      }
      $category = $display->handler
        ->get_option('pane_category');
      if (!$category['name']) {
        $category['name'] = t('View panes');
      }
      $icon = 'icon_views_page.png';
      $contexts = array();
      $arguments = $display->handler
        ->get_argument_input();
      foreach ($arguments as $argument) {
        if ($argument['type'] == 'context') {
          $contexts[] = new panels_required_context($argument['label'], $argument['context']);
        }
      }
      $types[$view->name . '-' . $id] = array(
        'title' => $title,
        'icon' => $icon,
        'description' => filter_xss_admin($description),
        'required context' => $contexts,
        'category' => array(
          $category['name'],
          $category['weight'],
        ),
      );
    }
  }
  return $types;
}

/**
 * Render a view pane
 */
function panels_views_panes_render($subtype, $conf, $panel_args, $contexts) {
  if (!is_array($contexts)) {
    $contexts = array(
      $contexts,
    );
  }
  list($name, $display) = explode('-', $subtype);
  $view = views_get_view($name);
  if (empty($view)) {
    return;
  }
  $view
    ->set_display($display);
  if (!$view->display_handler
    ->access($GLOBALS['user'])) {
    return;
  }
  if (!$view->display_handler
    ->access($GLOBALS['user'])) {
    return;
  }
  $args = array();
  $arguments = $view->display_handler
    ->get_option('arguments');
  foreach ($view->display_handler
    ->get_argument_input() as $id => $argument) {
    switch ($argument['type']) {
      case 'context':
        $c = array_shift($contexts);
        $args[] = $c->argument;
        break;
      case 'fixed':
        $args[] = $argument['fixed'];
        break;
      case 'panel':
        $args[] = $panel_args[$argument['panel']];
        break;
      case 'user':
        $args[] = isset($conf['arguments'][$id]) ? $conf['arguments'][$id] : NULL;
        break;
      case 'wildcard':

        // Put in the wildcard.
        $args[] = isset($arguments[$id]['wildcard']) ? $arguments[$id]['wildcard'] : '*';
        break;
      case 'none':
      default:

        // Put in NULL.
        // views.module knows what to do with NULL (or missing) arguments
        $args[] = NULL;
        break;
    }
  }

  // remove any trailing NULL arguments as these are non-args:
  while (count($args) && end($args) === NULL) {
    array_pop($args);
  }
  $view
    ->set_arguments($args);
  if ($allow['path_override'] && !empty($conf['path'])) {
    $view->display_handler
      ->set_option('path', $conf['path']);
  }
  $block = new stdClass();
  $block->module = 'views';
  $block->delta = $view->name . $display;
  $block->subject = $view
    ->get_title();
  if ($allow['link_to_view'] && !empty($conf['link_to_view']) || !$allow['link_to_view'] && $view->display_handler->get_option['link_to_view']) {
    $block->title_link = $view
      ->get_url();
  }

  // more link
  if ($allow['more_link'] && !empty($conf['more_link']) || !$allow['more_link'] && $view->display_handler->get_option['more_link']) {
    $block->more = array(
      'href' => $view
        ->get_url(),
    );
    $view->display_handler
      ->set_option('use_more', FALSE);

    // make sure the view runs the count query so we know whether or not the more link
    // applies.
    $view->get_total_rows = TRUE;
  }
  if ($allow['use_pager']) {
    $view->display_handler
      ->set_option('use_pager', $conf['use_pager']);
    $view->display_handler
      ->set_option('pager_element', $conf['pager_id']);
  }
  if ($allow['items_per_page']) {
    $view->display_handler
      ->set_option('items_per_page', $conf['items_per_page']);
  }
  if ($allow['offset']) {
    $view->display_handler
      ->set_option('offset', $conf['offset']);
  }
  $stored_feeds = drupal_add_feed();
  $block->content = $view
    ->preview();
  if ($view->total_rows <= $view->display_handler
    ->get_option('items_per_page')) {
    unset($block->more);
  }
  if ($allow['feed_icons'] && !empty($conf['feed_icons']) || !$allow['feed_icons'] && $view->display_handler->get_option['feed_icons']) {
    $new_feeds = drupal_add_feed();
    if ($diff = array_diff(array_keys($new_feeds), array_keys($stored_feeds))) {
      foreach ($diff as $url) {
        $block->feeds[$url] = $new_feeds[$url];
      }
    }
  }
  return $block;
}
function panels_views_panes_edit($id, $parents, $conf) {
  list($name, $display_id) = explode('-', $id);
  $view = views_get_view($name);
  if (!$view) {
    return;
  }
  $view
    ->set_display($display_id);
  $allow = $view->display_handler
    ->get_option('allow');

  // Provide defaults for everything in order to prevent warnings.
  if (empty($conf)) {
    $conf['link_to_view'] = $view->display_handler
      ->get_option('link_to_view');
    $conf['more_link'] = $view->display_handler
      ->get_option('more_link');
    $conf['feed_icons'] = $pv->feed_icons;
    $conf['use_pager'] = $view->display_handler
      ->get_option('use_pager');
    $conf['element_id'] = $view->display_handler
      ->get_option('element_id');
    $conf['items_per_page'] = $view->display_handler
      ->get_option('items_per_page');
    $conf['offset'] = $view->display_handler
      ->get_option('offset');
    $conf['path_override'] = FALSE;
    $conf['url'] = $view
      ->get_path();
  }
  foreach ($view->display_handler
    ->get_argument_input() as $id => $argument) {
    if ($argument['type'] == 'user') {
      $form['arguments'][$id] = array(
        '#type' => 'textfield',
        '#default_value' => isset($conf['arguments'][$id]) ? $conf['arguments'][$id] : '',
        '#title' => $argument['label'],
      );
    }
  }
  if ($view->display_handler
    ->has_path()) {
    if ($allow['link_to_view']) {
      $form['link_to_view'] = array(
        '#type' => 'checkbox',
        '#default_value' => $conf['link_to_view'],
        '#title' => t('Link title to page'),
        '#description' => t('If checked, the title will be a link to the page.'),
      );
    }
    if ($allow['more_link']) {
      $form['more_link'] = array(
        '#type' => 'checkbox',
        '#default_value' => $conf['more_link'],
        '#title' => t('Provide a "more" link that links to the view'),
        '#description' => t('This is independent of any more link that may be provided by the view itself; if you see two more links, turn this one off. Views will only provide a more link if using the "block" type, however, so if using embed, use this one.'),
      );
    }
  }
  if ($allow['feed_icons']) {
    $form['feed_icons'] = array(
      '#type' => 'checkbox',
      '#default_value' => $conf['feed_icons'],
      '#title' => t('Display feed icons'),
      '#description' => t('If checked, any feed icons provided will be displayed.'),
    );
  }
  if ($allow['use_pager']) {
    $form['pager_aligner_start'] = array(
      '#value' => '<div class="option-text-aligner">',
    );
    $form['use_pager'] = array(
      '#type' => 'checkbox',
      '#title' => t('Use pager'),
      '#default_value' => $conf['use_pager'],
      '#id' => 'use-pager-checkbox',
    );
    $form['pager_id'] = array(
      '#type' => 'textfield',
      '#default_value' => $conf['pager_id'],
      '#title' => t('Pager ID'),
      '#size' => 4,
      '#id' => 'use-pager-textfield',
    );
    $form['pager_aligner_stop'] = array(
      '#value' => '</div><div style="clear: both; padding: 0; margin: 0"></div>',
    );
  }
  if ($allow['items_per_page']) {
    $form['items_per_page'] = array(
      '#type' => 'textfield',
      '#default_value' => $conf['items_per_page'],
      '#title' => t('Num items'),
      '#size' => 4,
      '#description' => t('Select the number of items to display, or 0 to display all results.'),
    );
  }
  if ($allow['offset']) {
    $form['offset'] = array(
      '#type' => 'textfield',
      '#default_value' => $conf['offset'],
      '#title' => t('Offset'),
      '#size' => 4,
      '#description' => t('Enter the number of items to skip; enter 0 to skip no items.'),
    );
  }
  if ($allow['path_override']) {

    // TODO: Because javascript in the dialogs is kind of weird, dependent checkboxes
    // don't work right for external modules. This needs fixing in panels itself.
    $form['path'] = array(
      '#type' => 'textfield',
      '#default_value' => $conf['path'],
      '#title' => t('Override path'),
      '#size' => 30,
      '#description' => t('If this is set, override the View URL path; this can sometimes be useful to set to the panel URL.'),
    );
  }
  return $form;
}
function panels_views_panes_title($subtype, $conf) {
  list($name, $display) = explode('-', $subtype);
  $view = views_get_view($name);
  if (empty($view)) {
    return t('Deleted/missing view @view', array(
      '@view' => $name,
    ));
  }
  if (empty($view->display[$display])) {
    return t('Deleted/missing view @view', array(
      '@view' => $name,
    ));
  }
  $view
    ->set_display($display);
  $title = $view->display_handler
    ->get_option('pane_title');
  return check_plain($title ? $title : $view->name);
}

/**
 * Implementation of hook_views_api().
 *
 * This one is used as the base to reduce errors when updating.
 */
function panels_views_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'panels_views'),
  );
}

Functions

Namesort descending Description
panels_views_all_views_add Returns the form for a new view.
panels_views_all_views_content_types Return all content types available.
panels_views_all_views_edit Returns an edit form for a block.
panels_views_all_views_render Output function for the 'views' content type.
panels_views_all_views_title Returns the administrative title for a type.
panels_views_menu Implementation of hook_menu().
panels_views_panels_content_types Implementation of hook_panels_content_types()
panels_views_panes_content_types Return all views that have panel pane displays on them.
panels_views_panes_edit
panels_views_panes_render Render a view pane
panels_views_panes_title
panels_views_views_api Implementation of hook_views_api().
views_panels_block_info Don't show Views' blocks; we expose them already.