Newer
Older
The Great Git Migration
committed
<?php
The Great Git Migration
committed
/**
* @file
* Contains the base display plugin.
*/
/**
* @defgroup views_display_plugins Views display plugins
The Great Git Migration
committed
* @{
* Display plugins control how Views interact with the rest of Drupal.
*
* They can handle creating Views from a Drupal page hook; they can
* handle creating Views from a Drupal block hook. They can also
* handle creating Views from an external module source, such as
* a Panels pane, or an insert view, or a CCK field type.
*
* @see hook_views_plugins()
The Great Git Migration
committed
*/
/**
* The default display plugin handler. Display plugins handle options and
* basic mechanisms for different output methods.
*/
class views_plugin_display extends views_plugin {
/**
* The top object of a view.
* @var view
*/
var $view = NULL;
The Great Git Migration
committed
var $handlers = array();
* Stores all available display extenders.
*/
var $extender = array();
The Great Git Migration
committed
function init(&$view, &$display, $options = NULL) {
$this->view = &$view;
$this->display = &$display;
The Great Git Migration
committed
Tim Plunkett
committed
// Load extenders as soon as possible.
$this->extender = array();
$extenders = views_get_enabled_display_extenders();
// If you update to the dev version the registry might not be loaded yet.
if (!empty($extenders) && class_exists('views_plugin_display_extender')) {
foreach ($extenders as $extender) {
$plugin = views_get_plugin('display_extender', $extender);
if ($plugin) {
$plugin->init($this->view, $this);
$this->extender[$extender] = $plugin;
}
else {
vpr('Invalid display extender @extender', array('@handler' => $extender));
}
}
}
// Track changes that the user should know about.
$changed = FALSE;
The Great Git Migration
committed
// Make some modifications:
if (!isset($options) && isset($display->display_options)) {
The Great Git Migration
committed
$options = $display->display_options;
}
if ($this->is_default_display() && isset($options['defaults'])) {
unset($options['defaults']);
}
// Cache for unpack_options, but not if we are in the ui.
static $unpack_options = array();
if (empty($view->editing)) {
$cid = 'unpack_options:' . md5(serialize(array($this->options, $options)));
if (empty($unpack_options[$cid])) {
$cache = views_cache_get($cid, TRUE);
if (!empty($cache->data)) {
$this->options = $cache->data;
}
else {
$this->unpack_options($this->options, $options);
views_cache_set($cid, $this->options, TRUE);
}
$unpack_options[$cid] = $this->options;
}
else {
$this->options = $unpack_options[$cid];
}
}
else {
$this->unpack_options($this->options, $options);
}
Daniel Wehner
committed
// Translate changed settings:
$items_per_page = $this->get_option('items_per_page');
$offset = $this->get_option('offset');
$use_pager = $this->get_option('use_pager');
$pager = $this->get_option('pager');
// Check if the pager options were already converted.
Daniel Wehner
committed
// The pager settings of a Views 2.x view specifying 10 items with an
// offset of 0 and no pager is the same as of a Views 3.x view with
// default settings. In this case, the only way to determine which case we
// are dealing with is checking the API version but that's only available
// for exported Views as it's not stored in the database.
// If you would like to change this code, really take care that you thought
// of every possibility.
// @TODO: Provide a way to convert the database views as well.
if (((!empty($items_per_page) && $items_per_page != 10) || !empty($offset) || !empty($use_pager))
|| (!empty($view->api_version) && $view->api_version == 2)) {
// Find out the right pager type.
// If the view "use pager" it's a normal/full pager.
if ($use_pager) {
Daniel Wehner
committed
$type = 'full';
}
// If it does not use pager, but 0 items per page it should not page
// else it should display just a certain amount of items.
else {
$type = $items_per_page ? 'some' : 'none';
}
Daniel Wehner
committed
// Setup the pager options.
Daniel Wehner
committed
$pager = array(
'type' => $type,
'options' => array(
'offset' => intval($offset)
Daniel Wehner
committed
),
);
if ($items_per_page) {
$pager['options']['items_per_page'] = $items_per_page;
}
// Setup the pager element.
Daniel Wehner
committed
if ($id = $this->get_option('pager_element')) {
$pager['options']['id'] = $id;
}
// Unset the previous options
// After edit and save the view they will be erased
$this->set_option('items_per_page', NULL);
$this->set_option('offset', NULL);
$this->set_option('use_pager', NULL);
$this->set_option('pager', $pager);
$changed = TRUE;
Daniel Wehner
committed
}
Daniel Wehner
committed
Daniel Wehner
committed
// Plugable headers, footer and empty texts are
// not compatible with previous version of views
// This code converts old values into a configured handler for each area
foreach (array('header', 'footer', 'empty') as $area) {
$converted = FALSE;
Daniel Wehner
committed
if (isset($this->options[$area]) && !is_array($this->options[$area])) {
if (!empty($this->options[$area])) {
$content = $this->get_option($area);
if (!empty($content) && !is_array($content)) {
$format = $this->get_option($area . '_format');
$options = array(
'id' => 'area',
'table' => 'views',
'field' => 'area',
'label' => '',
'relationship' => 'none',
'group_type' => 'group',
'content' => $content,
Daniel Wehner
committed
'format' => !empty($format) ? $format : filter_default_format(),
Daniel Wehner
committed
);
if ($area != 'empty' && $empty = $this->get_option($area . '_empty')) {
$options['empty'] = $empty;
}
$this->set_option($area, array('text' => $options));
$converted = TRUE;
$changed = TRUE;
Daniel Wehner
committed
}
}
// Ensure that options are at least an empty array
if (!$converted) {
$this->set_option($area, array());
}
}
Daniel Wehner
committed
}
// Convert distinct setting from display to query settings.
$distinct = $this->get_option('distinct');
if (!empty($distinct)) {
$query_settings = $this->get_option('query');
$query_settings['options']['distinct'] = $distinct;
$this->set_option('query', $query_settings);
// Clear the values
$this->set_option('distinct', NULL);
$changed = TRUE;
// Convert field language settings.
$query_options = $this->get_option('query');
if (isset($query_options['options']['field_language'])) {
$this->set_option('field_language', $query_options['options']['field_language']);
unset($query_options['options']['field_language']);
$changed = TRUE;
}
if (isset($query_options['options']['field_language_add_to_query'])) {
$this->set_option('field_language_add_to_query', $query_options['options']['field_language_add_to_query']);
unset($query_options['options']['field_language_add_to_query']);
$changed = TRUE;
}
$this->set_option('query', $query_options);
Daniel Wehner
committed
// Convert filter groups.
$filter_groups = $this->get_option('filter_groups');
// Only convert if it wasn't converted yet, which is the case if there is a 0 group.
if (isset($filter_groups['groups'][0])) {
// Update filter groups.
$filter_groups ['groups'] = views_array_key_plus($filter_groups['groups']);
$this->set_option('filter_groups', $filter_groups);
// Update the filter group on each filter.
$filters = $this->get_option('filters');
foreach ($filters as &$filter) {
if (isset($filter['group'])) {
$filter['group']++;
}
else {
$filter['group'] = 1;
}
Daniel Wehner
committed
}
$this->set_option('filters', $filters);
$changed = TRUE;
}
Daniel Wehner
committed
// Filter groups were allowed to be rewritten without its filters, so
// before this update the view was using the default values. To be sure that
// the existing view isn't broken, don't use this overridden values but copy
// them from the default display. Only do this if the filters are overridden
// but the filter_groups are not marked as so.
if (!$this->is_default_display() && !$this->options['defaults']['filters'] && $this->options['defaults']['filter_groups']) {
// Set filter_groups to be overridden and save the value in the
// display_options as well.
$this->options['defaults']['filter_groups'] = FALSE;
$this->display->display_options['defaults']['filter_groups'] = $this->options['defaults']['filter_groups'];
// Copy the filter_groups from the default, and add them to the
// display_options as well. $this->default_display is not initialized at
// this point.
$this->options['filter_groups'] = $this->view->display['default']->handler->options['filter_groups'];
$this->display->display_options['filter_groups'] = $this->options['filter_groups'];
$changed = TRUE;
}
// Mark the view as changed so the user has a chance to save it.
if ($changed) {
$this->view->changed = TRUE;
Daniel Wehner
committed
}
The Great Git Migration
committed
}
function destroy() {
parent::destroy();
foreach ($this->handlers as $type => $handlers) {
foreach ($handlers as $id => $handler) {
if (is_object($handler)) {
$this->handlers[$type][$id]->destroy();
}
}
}
if (isset($this->default_display)) {
unset($this->default_display);
}
foreach ($this->extender as $extender) {
$extender->destroy();
}
The Great Git Migration
committed
}
/**
* Determine if this display is the 'default' display which contains
* fallback settings
*/
function is_default_display() { return FALSE; }
/**
* Determine if this display uses exposed filters, so the view
* will know whether or not to build them.
*/
function uses_exposed() {
if (!isset($this->has_exposed)) {
foreach ($this->handlers as $type => $value) {
foreach ($this->view->$type as $id => $handler) {
if ($handler->can_expose() && $handler->is_exposed()) {
The Great Git Migration
committed
// one is all we need; if we find it, return true.
$this->has_exposed = TRUE;
return TRUE;
}
}
}
$pager = $this->get_plugin('pager');
if (isset($pager) && $pager->uses_exposed()) {
$this->has_exposed = TRUE;
return TRUE;
}
The Great Git Migration
committed
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
$this->has_exposed = FALSE;
}
return $this->has_exposed;
}
/**
* Determine if this display should display the exposed
* filters widgets, so the view will know whether or not
* to render them.
*
* Regardless of what this function
* returns, exposed filters will not be used nor
* displayed unless uses_exposed() returns TRUE.
*/
function displays_exposed() {
return TRUE;
}
/**
* Does the display use AJAX?
*/
function use_ajax() {
if (!empty($this->definition['use ajax'])) {
return $this->get_option('use_ajax');
}
return FALSE;
}
/**
* Does the display have a pager enabled?
*/
function use_pager() {
Daniel Wehner
committed
$pager = $this->get_plugin('pager');
if ($pager) {
return $pager->use_pager();
The Great Git Migration
committed
}
The Great Git Migration
committed
/**
* Does the display have a more link enabled?
*/
function use_more() {
if (!empty($this->definition['use more'])) {
return $this->get_option('use_more');
}
return FALSE;
}
Daniel Wehner
committed
/**
* Does the display have groupby enabled?
Daniel Wehner
committed
*/
function use_group_by() {
return $this->get_option('group_by');
}
/**
* Should the enabled display more link be shown when no more items?
*/
function use_more_always() {
if (!empty($this->definition['use more'])) {
return $this->get_option('use_more_always');
}
return FALSE;
}
The Great Git Migration
committed
/**
* Does the display have custom link text?
*/
function use_more_text() {
if (!empty($this->definition['use more'])) {
return $this->get_option('use_more_text');
}
return FALSE;
}
/**
* Can this display accept attachments?
*/
function accept_attachments() {
if (empty($this->definition['accept attachments'])) {
return FALSE;
}
if (!empty($this->view->argument) && $this->get_option('hide_attachment_summary')) {
foreach ($this->view->argument as $argument_id => $argument) {
if ($argument->needs_style_plugin() && empty($argument->argument_validated)) {
return FALSE;
}
}
}
return TRUE;
The Great Git Migration
committed
}
/**
* Allow displays to attach to other views.
*/
function attach_to($display_id) { }
/**
* Static member function to list which sections are defaultable
* and what items each section contains.
*/
function defaultable_sections($section = NULL) {
$sections = array(
'access' => array('access', 'access_options'),
'access_options' => array('access', 'access_options'),
'cache' => array('cache', 'cache_options'),
'cache_options' => array('cache', 'cache_options'),
The Great Git Migration
committed
'title' => array('title'),
'css_class' => array('css_class'),
The Great Git Migration
committed
'use_ajax' => array('use_ajax'),
'hide_attachment_summary' => array('hide_attachment_summary'),
Damian Lee
committed
'hide_admin_links' => array('hide_admin_links'),
'group_by' => array('group_by'),
Daniel Wehner
committed
'query' => array('query'),
'use_more' => array('use_more', 'use_more_always', 'use_more_text'),
Daniel Wehner
committed
'use_more_always' => array('use_more', 'use_more_always', 'use_more_text'),
'use_more_text' => array('use_more', 'use_more_always', 'use_more_text'),
Daniel Wehner
committed
'link_display' => array('link_display', 'link_url'),
The Great Git Migration
committed
// Force these to cascade properly.
'style_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
'style_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
'row_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
'row_options' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'),
'pager' => array('pager', 'pager_options'),
'pager_options' => array('pager', 'pager_options'),
'exposed_form' => array('exposed_form', 'exposed_form_options'),
'exposed_form_options' => array('exposed_form', 'exposed_form_options'),
The Great Git Migration
committed
// These guys are special
Daniel Wehner
committed
'header' => array('header'),
'footer' => array('footer'),
Daniel Wehner
committed
'empty' => array('empty'),
The Great Git Migration
committed
'relationships' => array('relationships'),
'fields' => array('fields'),
'sorts' => array('sorts'),
'arguments' => array('arguments'),
'filters' => array('filters', 'filter_groups'),
Daniel Wehner
committed
'filter_groups' => array('filters', 'filter_groups'),
The Great Git Migration
committed
);
// If the display cannot use a pager, then we cannot default it.
if (empty($this->definition['use pager'])) {
unset($sections['pager']);
unset($sections['items_per_page']);
}
foreach ($this->extender as $extender) {
$extender->defaultable_sections($sections, $section);
}
The Great Git Migration
committed
if ($section) {
if (!empty($sections[$section])) {
return $sections[$section];
}
}
else {
return $sections;
}
}
function option_definition() {
$options = array(
'defaults' => array(
'default' => array(
'access' => TRUE,
'cache' => TRUE,
Daniel Wehner
committed
'query' => TRUE,
The Great Git Migration
committed
'title' => TRUE,
'css_class' => TRUE,
The Great Git Migration
committed
'display_description' => FALSE,
The Great Git Migration
committed
'use_ajax' => TRUE,
'hide_attachment_summary' => TRUE,
Damian Lee
committed
'hide_admin_links' => FALSE,
Daniel Wehner
committed
'pager' => TRUE,
The Great Git Migration
committed
'use_more' => TRUE,
'use_more_always' => TRUE,
The Great Git Migration
committed
'use_more_text' => TRUE,
Daniel Wehner
committed
'exposed_form' => TRUE,
'exposed_form_options' => TRUE,
The Great Git Migration
committed
'link_display' => TRUE,
Daniel Wehner
committed
'link_url' => '',
Daniel Wehner
committed
'group_by' => TRUE,
The Great Git Migration
committed
'style_plugin' => TRUE,
'style_options' => TRUE,
'row_plugin' => TRUE,
'row_options' => TRUE,
Daniel Wehner
committed
'header' => TRUE,
'footer' => TRUE,
'empty' => TRUE,
The Great Git Migration
committed
'relationships' => TRUE,
'fields' => TRUE,
'sorts' => TRUE,
'arguments' => TRUE,
'filters' => TRUE,
'filter_groups' => TRUE,
The Great Git Migration
committed
),
'export' => FALSE,
The Great Git Migration
committed
),
The Great Git Migration
committed
'title' => array(
'default' => '',
'translatable' => TRUE,
),
'enabled' => array(
'default' => TRUE,
'translatable' => FALSE,
'bool' => TRUE,
),
Earl Miles
committed
'display_comment' => array(
'default' => '',
),
'css_class' => array(
'default' => '',
'translatable' => FALSE,
),
'display_description' => array(
'default' => '',
'translatable' => TRUE,
),
The Great Git Migration
committed
'use_ajax' => array(
'default' => FALSE,
'bool' => TRUE,
The Great Git Migration
committed
),
'hide_attachment_summary' => array(
'default' => FALSE,
'bool' => TRUE,
),
Damian Lee
committed
'hide_admin_links' => array(
'default' => FALSE,
'bool' => TRUE,
),
// This is legacy code:
// Items_per/offset/use_pager is moved to the pager plugin
// but the automatic update path needs this items defined, so don't remove it.
// @see views_plugin_display::init()
The Great Git Migration
committed
'items_per_page' => array(
'default' => 10,
),
'offset' => array(
'default' => 0,
),
'use_pager' => array(
'default' => FALSE,
'bool' => TRUE,
The Great Git Migration
committed
),
'use_more' => array(
'default' => FALSE,
'bool' => TRUE,
The Great Git Migration
committed
),
'use_more_always' => array(
'default' => FALSE,
Daniel Wehner
committed
'bool' => TRUE,
'export' => 'export_option_always',
The Great Git Migration
committed
'use_more_text' => array(
'default' => 'more',
'translatable' => TRUE,
),
'link_display' => array(
'default' => '',
),
Daniel Wehner
committed
'link_url' => array(
'default' => '',
),
Daniel Wehner
committed
'group_by' => array(
'default' => FALSE,
'bool' => TRUE,
),
'field_language' => array(
'default' => '***CURRENT_LANGUAGE***',
),
'field_language_add_to_query' => array(
'default' => 1,
),
// These types are all plugins that can have individual settings
// and therefore need special handling.
'access' => array(
'contains' => array(
Daniel Wehner
committed
'type' => array('default' => 'none', 'export' => 'export_plugin', 'unpack_translatable' => 'unpack_plugin'),
),
),
'cache' => array(
'contains' => array(
Daniel Wehner
committed
'type' => array('default' => 'none', 'export' => 'export_plugin', 'unpack_translatable' => 'unpack_plugin'),
),
),
Daniel Wehner
committed
'query' => array(
'contains' => array(
'type' => array('default' => 'views_query', 'export' => 'export_plugin'),
'options' => array('default' => array(), 'export' => FALSE),
),
),
// Note that exposed_form plugin has options in a separate array,
// while access and cache do not. access and cache are legacy and
// that pattern should not be repeated, but it is left as is to
// reduce the need to modify older views. Let's consider the
// pattern used here to be the template from which future plugins
// should be copied.
'exposed_form' => array(
'contains' => array(
Daniel Wehner
committed
'type' => array('default' => 'basic', 'export' => 'export_plugin', 'unpack_translatable' => 'unpack_plugin'),
'options' => array('default' => array(), 'export' => FALSE),
),
Daniel Wehner
committed
),
Daniel Wehner
committed
'pager' => array(
'contains' => array(
Daniel Wehner
committed
'type' => array('default' => 'full', 'export' => 'export_plugin', 'unpack_translatable' => 'unpack_plugin'),
Daniel Wehner
committed
'options' => array('default' => array(), 'export' => FALSE),
),
),
The Great Git Migration
committed
// Note that the styles have their options completely independent.
// Like access and cache above, this is a legacy pattern and
// should not be repeated.
The Great Git Migration
committed
'style_plugin' => array(
'default' => 'default',
'export' => 'export_style',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_style',
The Great Git Migration
committed
),
'style_options' => array(
'default' => array(),
'export' => FALSE,
The Great Git Migration
committed
),
'row_plugin' => array(
'default' => 'fields',
'export' => 'export_style',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_style',
The Great Git Migration
committed
),
'row_options' => array(
'default' => array(),
'export' => FALSE,
The Great Git Migration
committed
),
'exposed_block' => array(
'default' => FALSE,
),
Daniel Wehner
committed
'header' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
Daniel Wehner
committed
),
'footer' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
Daniel Wehner
committed
),
'empty' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
Daniel Wehner
committed
),
// We want these to export last.
// These are the 5 handler types.
'relationships' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
),
'fields' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
),
'sorts' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
),
'arguments' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
),
'filter_groups' => array(
'contains' => array(
'operator' => array('default' => 'AND'),
Daniel Wehner
committed
'groups' => array('default' => array(1 => 'AND')),
),
),
'filters' => array(
'default' => array(),
'export' => 'export_handler',
Daniel Wehner
committed
'unpack_translatable' => 'unpack_handler',
Daniel Wehner
committed
),
The Great Git Migration
committed
);
if (empty($this->definition['use pager'])) {
$options['defaults']['default']['use_pager'] = FALSE;
$options['defaults']['default']['items_per_page'] = FALSE;
$options['defaults']['default']['offset'] = FALSE;
$options['defaults']['default']['pager'] = FALSE;
$options['pager']['contains']['type']['default'] = 'some';
}
The Great Git Migration
committed
if ($this->is_default_display()) {
unset($options['defaults']);
}
foreach ($this->extender as $extender) {
$extender->options_definition_alter($options);
The Great Git Migration
committed
return $options;
}
/**
* Check to see if the display has a 'path' field.
*
* This is a pure function and not just a setting on the definition
* because some displays (such as a panel pane) may have a path based
* upon configuration.
*
* By default, displays do not have a path.
*/
function has_path() { return FALSE; }
/**
* Check to see if the display has some need to link to another display.
*
* For the most part, displays without a path will use a link display. However,
* sometimes displays that have a path might also need to link to another display.
* This is true for feeds.
*/
function uses_link_display() { return !$this->has_path(); }
/**
* Check to see if the display can put the exposed formin a block.
*
* By default, displays that do not have a path cannot disconnect
* the exposed form and put it in a block, because the form has no
* place to go and Views really wants the forms to go to a specific
* page.
*/
function uses_exposed_form_in_block() { return $this->has_path(); }
The Great Git Migration
committed
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
/**
* Check to see which display to use when creating links within
* a view using this display.
*/
function get_link_display() {
$display_id = $this->get_option('link_display');
// If unknown, pick the first one.
if (empty($display_id) || empty($this->view->display[$display_id])) {
foreach ($this->view->display as $display_id => $display) {
if (!empty($display->handler) && $display->handler->has_path()) {
return $display_id;
}
}
}
else {
return $display_id;
}
// fall-through returns NULL
}
/**
* Return the base path to use for this display.
*
* This can be overridden for displays that do strange things
* with the path.
*/
function get_path() {
if ($this->has_path()) {
return $this->get_option('path');
}
$display_id = $this->get_link_display();
if ($display_id && !empty($this->view->display[$display_id]) && is_object($this->view->display[$display_id]->handler)) {
return $this->view->display[$display_id]->handler->get_path();
}
}
Daniel Wehner
committed
function get_url() {
return $this->view->get_url();
}
The Great Git Migration
committed
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
/**
* Check to see if the display needs a breadcrumb
*
* By default, displays do not need breadcrumbs
*/
function uses_breadcrumb() { return FALSE; }
/**
* Determine if a given option is set to use the default display or the
* current display
*
* @return
* TRUE for the default display
*/
function is_defaulted($option) {
return !$this->is_default_display() && !empty($this->default_display) && !empty($this->options['defaults'][$option]);
}
/**
* Intelligently get an option either from this display or from the
* default display, if directed to do so.
*/
function get_option($option) {
if ($this->is_defaulted($option)) {
return $this->default_display->get_option($option);
}
if (array_key_exists($option, $this->options)) {
return $this->options[$option];
}
}
/**
* Determine if the display's style uses fields.
*/
function uses_fields() {
$plugin = $this->get_plugin();
if ($plugin) {
return $plugin->uses_fields();
}
}
/**
* Get the instance of a plugin, for example style or row.
*
* @param string $type
* The type of the plugin.
* @param string $name
* The name of the plugin defined in hook_views_plugins.
*
* @return views_plugin|FALSE
The Great Git Migration
committed
*/
function get_plugin($type = 'style', $name = NULL) {
Daniel Wehner
committed
static $cache = array();
if (!isset($cache[$type][$name])) {
switch ($type) {
case 'style':
case 'row':
$option_name = $type . '_plugin';
$options = $this->get_option($type . '_options');
if (!$name) {
$name = $this->get_option($option_name);
}
The Great Git Migration
committed
Daniel Wehner
committed
break;
Daniel Wehner
committed
case 'query':
$views_data = views_fetch_data($this->view->base_table);
$name = !empty($views_data['table']['base']['query class']) ? $views_data['table']['base']['query class'] : 'views_query';
Daniel Wehner
committed
default:
$option_name = $type;
$options = $this->get_option($type);
if (!$name) {
$name = $options['type'];
}
The Great Git Migration
committed
Daniel Wehner
committed
// access & cache store their options as siblings with the
// type; all others use an 'options' array.
if ($type != 'access' && $type != 'cache') {
$options = $options['options'];
}
}
$plugin = views_get_plugin($type, $name);
Daniel Wehner
committed
Daniel Wehner
committed
if (!$plugin) {
return;
}
Daniel Wehner
committed
if ($type != 'query') {
$plugin->init($this->view, $this->display, $options);
}
else {
$display_id = $this->is_defaulted($option_name) ? $this->display->id : 'default';
$plugin->localization_keys = array($display_id, $type);
if (!isset($this->base_field)) {
$views_data = views_fetch_data($this->view->base_table);
Daniel Wehner
committed
$this->view->base_field = !empty($views_data['table']['base']['field']) ? $views_data['table']['base']['field'] : '';
Daniel Wehner
committed
$plugin->init($this->view->base_table, $this->view->base_field, $options);
}
Daniel Wehner
committed
$cache[$type][$name] = $plugin;
Daniel Wehner
committed
}
Daniel Wehner
committed
return $cache[$type][$name];
Daniel Wehner
committed
}
The Great Git Migration
committed
/**
* Get the handler object for a single handler.
*/
function &get_handler($type, $id) {
if (!isset($this->handlers[$type])) {
$this->get_handlers($type);
}
if (isset($this->handlers[$type][$id])) {
return $this->handlers[$type][$id];
}
// So we can return a reference.
$null = NULL;
return $null;
}
/**
* Get a full array of handlers for $type. This caches them.
*/
function get_handlers($type) {
if (!isset($this->handlers[$type])) {
$this->handlers[$type] = array();
$types = views_object_types();
$plural = $types[$type]['plural'];
Earl Miles
committed
The Great Git Migration
committed
foreach ($this->get_option($plural) as $id => $info) {
Earl Miles
committed
// If this is during form submission and there are temporary options
// which can only appear if the view is in the edit cache, use those
// options instead. This is used for AJAX multi-step stuff.
if (isset($_POST['form_id']) && isset($this->view->temporary_options[$type][$id])) {
$info = $this->view->temporary_options[$type][$id];
}
Earl Miles
committed
if ($info['id'] != $id) {
$info['id'] = $id;
}
Daniel Wehner
committed
// If aggregation is on, the group type might override the actual
// handler that is in use. This piece of code checks that and,
// if necessary, sets the override handler.
$override = NULL;
if ($this->use_group_by() && !empty($info['group_type'])) {
if (empty($this->view->query)) {
$this->view->init_query();
}
$aggregate = $this->view->query->get_aggregation_info();
if (!empty($aggregate[$info['group_type']]['handler'][$type])) {
$override = $aggregate[$info['group_type']]['handler'][$type];
}
}
Daniel Wehner
committed
if (!empty($types[$type]['type'])) {
$handler_type = $types[$type]['type'];
}
else {
$handler_type = $type;
}
$handler = views_get_handler($info['table'], $info['field'], $handler_type, $override);
The Great Git Migration
committed
if ($handler) {
// Special override for area types so they know where they come from.
if ($handler_type == 'area') {
$handler->handler_type = $type;
}
The Great Git Migration
committed
$handler->init($this->view, $info);
$this->handlers[$type][$id] = &$handler;
The Great Git Migration
committed
}
// Prevent reference problems.
unset($handler);
}
}
return $this->handlers[$type];
}
Earl Miles
committed
/**
* Retrieve a list of fields for the current display with the
* relationship associated if it exists.
*
* @param $groupable_only
* Return only an array of field labels from handler that return TRUE
* from use_string_group_by method.
Earl Miles
committed
function get_field_labels() {
// Use func_get_arg so the function signature isn't amended
// but we can still pass TRUE into the function to filter
// by groupable handlers.
$args = func_get_args();
$groupable_only = isset($args[0]) ? $args[0] : FALSE;
Earl Miles
committed
$options = array();
foreach ($this->get_handlers('relationship') as $relationship => $handler) {
if ($label = $handler->label()) {
$relationships[$relationship] = $label;
}
else {
$relationships[$relationship] = $handler->ui_name();
}
}
foreach ($this->get_handlers('field') as $id => $handler) {