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' => '
', ); $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' => '
', ); $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' => '
', ); $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' => '
', ); } 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'), ); }