Newer
Older
Angie Byron
committed
* Contains \Drupal\views\Plugin\views\display\DisplayPluginBase.
namespace Drupal\views\Plugin\views\display;
Angie Byron
committed
use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Unicode;
Alex Pott
committed
use Drupal\Core\Cache\Cache;
Dries Buytaert
committed
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
Angie Byron
committed
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Theme\Registry;
use Drupal\Core\Url;
Alex Pott
committed
use Drupal\views\Form\ViewsForm;
use Drupal\views\Plugin\CacheablePluginInterface;
use Drupal\views\Plugin\views\area\AreaPluginBase;
Daniel Wehner
committed
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\PluginBase;
Dries Buytaert
committed
use Drupal\views\Views;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\Exception\RuntimeException as DependencyInjectionRuntimeException;
/**
* @defgroup views_display_plugins Views display plugins
* @{
Angie Byron
committed
* Plugins to handle the overall display of views.
Angie Byron
committed
* Display plugins are responsible for controlling where a view is rendered;
* that is, how it is exposed to other parts of Drupal. 'Page' and 'block' are
* the most commonly used display plugins. Each view also has a 'master' (or
* 'default') display that includes information shared between all its
* displays (see \Drupal\views\Plugin\views\display\DefaultDisplay).
*
* Display plugins extend \Drupal\views\Plugin\views\display\DisplayPluginBase.
Alex Pott
committed
* They must be annotated with \Drupal\views\Annotation\ViewsDisplay
Angie Byron
committed
* annotation, and they must be in namespace directory Plugin\views\display.
*
* @ingroup views_plugins
*
* @see plugin_api
* @see views_display_extender_plugins
Angie Byron
committed
* Base class for views display plugins.
Tim Plunkett
committed
abstract class DisplayPluginBase extends PluginBase {
* @var \Drupal\views\ViewExecutable
/**
* An array of instantiated handlers used in this display.
*
* @var \Drupal\views\Plugin\views\ViewsHandlerInterface[]
*/
public $handlers = [];
Tim Plunkett
committed
/**
* An array of instantiated plugins used in this display.
*
* @var \Drupal\views\Plugin\views\ViewsPluginInterface[]
Tim Plunkett
committed
*/
protected $plugins = array();
/**
* Stores all available display extenders.
*/
var $extender = array();
Tim Plunkett
committed
/**
* Overrides Drupal\views\Plugin\Plugin::$usesOptions.
*/
protected $usesOptions = TRUE;
Tim Plunkett
committed
Daniel Wehner
committed
/**
* Stores the rendered output of the display.
*
* @see View::render
Daniel Wehner
committed
* @var string
*/
public $output = NULL;
Salvador Molina
committed
/**
* Whether the display allows the use of AJAX or not.
*
* @var bool
*/
protected $usesAJAX = TRUE;
Salvador Molina
committed
/**
* Whether the display allows the use of a pager or not.
*
* @var bool
*/
protected $usesPager = TRUE;
/**
* Whether the display allows the use of a 'more' link or not.
*
* @var bool
*/
protected $usesMore = TRUE;
Damian Lee
committed
/**
* Whether the display allows attachments.
*
* @var bool
* TRUE if the display can use attachments, or FALSE otherwise.
*/
protected $usesAttachments = FALSE;
Angie Byron
committed
/**
* Whether the display allows area plugins.
*
* @var bool
*/
protected $usesAreas = TRUE;
/**
* Static cache for unpackOptions, but not if we are in the UI.
*
* @var array
*/
protected static $unpackOptions = array();
/**
* Constructs a new DisplayPluginBase object.
*
* Because DisplayPluginBase::initDisplay() takes the display configuration by
* reference and handles it differently than usual plugin configuration, pass
* an empty array of configuration to the parent. This prevents our
* configuration from being duplicated.
*
* @todo Replace DisplayPluginBase::$display with
* DisplayPluginBase::$configuration to standardize with other plugins.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct(array(), $plugin_id, $plugin_definition);
}
public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
$this->view = $view;
Angie Byron
committed
$this->setOptionDefaults($this->options, $this->defineOptions());
$this->display = &$display;
// Load extenders as soon as possible.
$this->extender = array();
if ($extenders = Views::getEnabledDisplayExtenders()) {
Dries Buytaert
committed
$manager = Views::pluginManager('display_extender');
if ($plugin = $manager->createInstance($extender)) {
$plugin->init($this->view, $this);
$this->extender[$extender] = $plugin;
}
}
}
// Track changes that the user should know about.
$changed = FALSE;
// Make some modifications:
Daniel Wehner
committed
if (!isset($options) && isset($display['display_options'])) {
$options = $display['display_options'];
Daniel Wehner
committed
if ($this->isDefaultDisplay() && isset($options['defaults'])) {
$skip_cache = \Drupal::config('views.settings')->get('skip_cache');
if (empty($view->editing) || !$skip_cache) {
$cid = 'views:unpack_options:' . hash('sha256', serialize(array($this->options, $options))) . ':' . \Drupal::languageManager()->getCurrentLanguage()->getId();
if (empty(static::$unpackOptions[$cid])) {
$cache = \Drupal::cache('data')->get($cid);
if (!empty($cache->data)) {
$this->options = $cache->data;
}
else {
$this->unpackOptions($this->options, $options);
Alex Pott
committed
$id = $this->view->storage->id();
\Drupal::cache('data')->set($cid, $this->options, Cache::PERMANENT, array('extension', 'extension:views', 'view:' . $id));
static::$unpackOptions[$cid] = $this->options;
$this->options = static::$unpackOptions[$cid];
$this->unpackOptions($this->options, $options);
// Convert the field_langcode and field_language_add_to_query settings.
$field_langcode = $this->getOption('field_langcode');
Daniel Wehner
committed
$field_language_add_to_query = $this->getOption('field_language_add_to_query');
if (isset($field_langcode)) {
$this->setOption('field_langcode', $field_langcode);
Daniel Wehner
committed
$this->setOption('field_langcode_add_to_query', $field_language_add_to_query);
$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
public 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();
}
}
/**
* Determine if this display is the 'default' display which contains
* fallback settings
*/
Daniel Wehner
committed
public function isDefaultDisplay() { return FALSE; }
/**
* Determine if this display uses exposed filters, so the view
* will know whether or not to build them.
*/
Daniel Wehner
committed
public function usesExposed() {
if (!isset($this->has_exposed)) {
foreach ($this->handlers as $type => $value) {
Angie Byron
committed
foreach ($this->view->$type as $handler) {
if ($handler->canExpose() && $handler->isExposed()) {
// one is all we need; if we find it, return true.
$this->has_exposed = TRUE;
return TRUE;
}
}
}
Daniel Wehner
committed
$pager = $this->getPlugin('pager');
Alex Pott
committed
if (isset($pager) && $pager->usesExposed()) {
$this->has_exposed = TRUE;
return TRUE;
}
$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
Daniel Wehner
committed
* displayed unless usesExposed() returns TRUE.
Daniel Wehner
committed
public function displaysExposed() {
Salvador Molina
committed
* Whether the display allows the use of AJAX or not.
*
* @return bool
*/
Daniel Wehner
committed
public function usesAJAX() {
Salvador Molina
committed
return $this->usesAJAX;
}
/**
* Whether the display is actually using AJAX or not.
*
* @return bool
public function ajaxEnabled() {
Salvador Molina
committed
if ($this->usesAJAX()) {
Daniel Wehner
committed
return $this->getOption('use_ajax');
Daniel Wehner
committed
/**
* Whether the display is enabled.
*
* @return bool
* Returns TRUE if the display is marked as enabled, else FALSE.
*/
public function isEnabled() {
return (bool) $this->getOption('enabled');
}
Salvador Molina
committed
* Whether the display allows the use of a pager or not.
*
* @return bool
*/
Daniel Wehner
committed
public function usesPager() {
Salvador Molina
committed
return $this->usesPager;
}
/**
* Whether the display is using a pager or not.
*
* @return bool
Daniel Wehner
committed
public function isPagerEnabled() {
Salvador Molina
committed
if ($this->usesPager()) {
Daniel Wehner
committed
$pager = $this->getPlugin('pager');
Salvador Molina
committed
if ($pager) {
Alex Pott
committed
return $pager->usePager();
Salvador Molina
committed
}
Salvador Molina
committed
return FALSE;
Salvador Molina
committed
* Whether the display allows the use of a 'more' link or not.
*
* @return bool
*/
Daniel Wehner
committed
public function usesMore() {
Salvador Molina
committed
return $this->usesMore;
}
/**
* Whether the display is using the 'more' link or not.
*
* @return bool
Daniel Wehner
committed
public function isMoreEnabled() {
Salvador Molina
committed
if ($this->usesMore()) {
Daniel Wehner
committed
return $this->getOption('use_more');
}
return FALSE;
}
/**
* Does the display have groupby enabled?
*/
Daniel Wehner
committed
public function useGroupBy() {
return $this->getOption('group_by');
}
/**
* Should the enabled display more link be shown when no more items?
*/
Daniel Wehner
committed
public function useMoreAlways() {
Salvador Molina
committed
if ($this->usesMore()) {
return $this->getOption('use_more_always');
}
return FALSE;
}
/**
* Does the display have custom link text?
*/
Daniel Wehner
committed
public function useMoreText() {
Salvador Molina
committed
if ($this->usesMore()) {
return $this->getOption('use_more_text');
Damian Lee
committed
* Determines whether this display can use attachments.
*
* @return bool
Daniel Wehner
committed
public function acceptAttachments() {
Angie Byron
committed
// To be able to accept attachments this display have to be able to use
// attachments but at the same time, you cannot attach a display to itself.
if (!$this->usesAttachments() || ($this->definition['id'] == $this->view->current_display)) {
Angie Byron
committed
Daniel Wehner
committed
if (!empty($this->view->argument) && $this->getOption('hide_attachment_summary')) {
Angie Byron
committed
foreach ($this->view->argument as $argument) {
if ($argument->needsStylePlugin() && empty($argument->argument_validated)) {
Angie Byron
committed
Damian Lee
committed
/**
* Returns whether the display can use attachments.
*
* @return bool
*/
Daniel Wehner
committed
public function usesAttachments() {
Damian Lee
committed
return $this->usesAttachments;
}
Angie Byron
committed
/**
* Returns whether the display can use areas.
*
* @return bool
* TRUE if the display can use areas, or FALSE otherwise.
*/
public function usesAreas() {
return $this->usesAreas;
}
/**
* Allow displays to attach to other views.
Alex Pott
committed
*
* @param \Drupal\views\ViewExecutable $view
* The views executable.
* @param string $display_id
* The display to attach to.
* @param array $build
* The parent view render array.
Alex Pott
committed
public function attachTo(ViewExecutable $view, $display_id, array &$build) { }
/**
* Static member function to list which sections are defaultable
* and what items each section contains.
*/
Daniel Wehner
committed
public function defaultableSections($section = NULL) {
'access' => array('access'),
'cache' => array('cache'),
'title' => array('title'),
'css_class' => array('css_class'),
'use_ajax' => array('use_ajax'),
'hide_attachment_summary' => array('hide_attachment_summary'),
Angie Byron
committed
'show_admin_links' => array('show_admin_links'),
'group_by' => array('group_by'),
'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'),
'link_display' => array('link_display', 'link_url'),
// Force these to cascade properly.
'style' => array('style', 'row'),
'row' => array('style', 'row'),
Alex Pott
committed
'pager' => array('pager'),
Alex Pott
committed
'exposed_form' => array('exposed_form'),
// These guys are special
'header' => array('header'),
'footer' => array('footer'),
'empty' => array('empty'),
'relationships' => array('relationships'),
'fields' => array('fields'),
'sorts' => array('sorts'),
'arguments' => array('arguments'),
'filters' => array('filters', 'filter_groups'),
'filter_groups' => array('filters', 'filter_groups'),
);
// If the display cannot use a pager, then we cannot default it.
Salvador Molina
committed
if (!$this->usesPager()) {
unset($sections['pager']);
unset($sections['items_per_page']);
}
foreach ($this->extender as $extender) {
Daniel Wehner
committed
$extender->defaultableSections($sections, $section);
}
if ($section) {
if (!empty($sections[$section])) {
return $sections[$section];
}
}
else {
return $sections;
}
}
protected function defineOptions() {
$options = array(
'defaults' => array(
'default' => array(
'access' => TRUE,
'cache' => TRUE,
'query' => TRUE,
'title' => TRUE,
'css_class' => TRUE,
'display_description' => FALSE,
'use_ajax' => TRUE,
'hide_attachment_summary' => TRUE,
Angie Byron
committed
'show_admin_links' => TRUE,
'pager' => TRUE,
'use_more' => TRUE,
'use_more_always' => TRUE,
'use_more_text' => TRUE,
'exposed_form' => TRUE,
'link_display' => TRUE,
Angie Byron
committed
'link_url' => TRUE,
'style' => TRUE,
'row' => TRUE,
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
'header' => TRUE,
'footer' => TRUE,
'empty' => TRUE,
'relationships' => TRUE,
'fields' => TRUE,
'sorts' => TRUE,
'arguments' => TRUE,
'filters' => TRUE,
'filter_groups' => TRUE,
),
),
'title' => array(
'default' => '',
),
'enabled' => array(
'default' => TRUE,
),
'display_comment' => array(
'default' => '',
),
'css_class' => array(
'default' => '',
),
'display_description' => array(
'default' => '',
),
'use_ajax' => array(
'default' => FALSE,
),
'hide_attachment_summary' => array(
'default' => FALSE,
),
Angie Byron
committed
'show_admin_links' => array(
'default' => TRUE,
Damian Lee
committed
),
'use_more' => array(
'default' => FALSE,
),
'use_more_always' => array(
Angie Byron
committed
'default' => TRUE,
),
'use_more_text' => array(
'default' => 'more',
),
'link_display' => array(
'default' => '',
),
'link_url' => array(
'default' => '',
),
'group_by' => array(
'default' => FALSE,
),
'field_langcode' => array(
Angie Byron
committed
'default' => '***LANGUAGE_language_content***',
'field_langcode_add_to_query' => array(
'default' => TRUE,
),
// These types are all plugins that can have individual settings
// and therefore need special handling.
'access' => array(
'contains' => array(
Tim Plunkett
committed
'type' => array('default' => 'none'),
'options' => array('default' => array()),
),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
),
'cache' => array(
'contains' => array(
Tim Plunkett
committed
'type' => array('default' => 'none'),
'options' => array('default' => array()),
),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
),
'query' => array(
'contains' => array(
Tim Plunkett
committed
'type' => array('default' => 'views_query'),
'options' => array('default' => array()),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
),
'exposed_form' => array(
'contains' => array(
Tim Plunkett
committed
'type' => array('default' => 'basic'),
'options' => array('default' => array()),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
),
'pager' => array(
'contains' => array(
'type' => array('default' => 'mini'),
Tim Plunkett
committed
'options' => array('default' => array()),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
'style' => array(
'contains' => array(
'type' => array('default' => 'default'),
'options' => array('default' => array()),
),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
'row' => array(
'contains' => array(
'type' => array('default' => 'fields'),
'options' => array('default' => array()),
),
Alex Pott
committed
'merge_defaults' => array($this, 'mergePlugin'),
),
'exposed_block' => array(
'default' => FALSE,
),
'header' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
'footer' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
'empty' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
// We want these to export last.
// These are the 5 handler types.
'relationships' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
'fields' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
'sorts' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
'arguments' => array(
'default' => array(),
Alex Pott
committed
'merge_defaults' => array($this, 'mergeHandler'),
),
'filter_groups' => array(
'contains' => array(
'operator' => array('default' => 'AND'),
'groups' => array('default' => array(1 => 'AND')),
),
),
'filters' => array(
'default' => array(),
),
);
Salvador Molina
committed
if (!$this->usesPager()) {
$options['defaults']['default']['pager'] = FALSE;
$options['pager']['contains']['type']['default'] = 'some';
}
Daniel Wehner
committed
if ($this->isDefaultDisplay()) {
unset($options['defaults']);
}
foreach ($this->extender as $extender) {
Daniel Wehner
committed
$extender->defineOptionsAlter($options);
}
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.
*/
Daniel Wehner
committed
public function hasPath() { 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.
*/
Daniel Wehner
committed
public function usesLinkDisplay() { return !$this->hasPath(); }
/**
* 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.
*/
Daniel Wehner
committed
public function usesExposedFormInBlock() { return $this->hasPath(); }
catch
committed
/**
* Find out all displays which are attached to this display.
*
* The method is just using the pure storage object to avoid loading of the
* sub displays which would kill lazy loading.
*/
public function getAttachedDisplays() {
$current_display_id = $this->display['id'];
$attached_displays = array();
// Go through all displays and search displays which link to this one.
foreach ($this->view->storage->get('display') as $display_id => $display) {
if (isset($display['display_options']['displays'])) {
$displays = $display['display_options']['displays'];
if (isset($displays[$current_display_id])) {
$attached_displays[] = $display_id;
}
}
}
return $attached_displays;
}
/**
* Check to see which display to use when creating links within
* a view using this display.
*/
Daniel Wehner
committed
public function getLinkDisplay() {
$display_id = $this->getOption('link_display');
if (empty($display_id) || !$this->view->displayHandlers->has($display_id)) {
Daniel Wehner
committed
foreach ($this->view->displayHandlers as $display_id => $display) {
if (!empty($display) && $display->hasPath()) {
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.
*/
Daniel Wehner
committed
public function getPath() {
if ($this->hasPath()) {
return $this->getOption('path');
Daniel Wehner
committed
$display_id = $this->getLinkDisplay();
if ($display_id && $this->view->displayHandlers->has($display_id) && is_object($this->view->displayHandlers->get($display_id))) {
return $this->view->displayHandlers->get($display_id)->getPath();
Daniel Wehner
committed
public function getUrl() {
Damian Lee
committed
return $this->view->getUrl();
}
/**
* Determine if a given option is set to use the default display or the
* current display
*
* @return
* TRUE for the default display
*/
Daniel Wehner
committed
public function isDefaulted($option) {
return !$this->isDefaultDisplay() && !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.
*/
Daniel Wehner
committed
public function getOption($option) {
if ($this->isDefaulted($option)) {
return $this->default_display->getOption($option);
}
if (array_key_exists($option, $this->options)) {
return $this->options[$option];
}
}
/**
* Determine if the display's style uses fields.
*
* @return bool
Daniel Wehner
committed
public function usesFields() {
Tim Plunkett
committed
return $this->getPlugin('style')->usesFields();
}
/**
* Get the instance of a plugin, for example style or row.
*
* @param string $type
* The type of the plugin.
*
Alex Pott
committed
* @return \Drupal\views\Plugin\views\ViewsPluginInterface
Tim Plunkett
committed
*/
public function getPlugin($type) {
Tim Plunkett
committed
// Look up the plugin name to use for this instance.
Tim Plunkett
committed
$options = $this->getOption($type);
// Return now if no options have been loaded.
if (empty($options) || !isset($options['type'])) {
return;
}
Tim Plunkett
committed
// Query plugins allow specifying a specific query class per base table.
if ($type == 'query') {
Dries Buytaert
committed
$views_data = Views::viewsData()->get($this->view->storage->get('base_table'));
catch
committed
$name = isset($views_data['table']['base']['query_id']) ? $views_data['table']['base']['query_id'] : 'views_query';
Tim Plunkett
committed
}
else {
$name = $options['type'];
}
Tim Plunkett
committed
// Plugin instances are stored on the display for re-use.
if (!isset($this->plugins[$type][$name])) {
Dries Buytaert
committed
$plugin = Views::pluginManager($type)->createInstance($name);
catch
committed
// Initialize the plugin.
$plugin->init($this->view, $this, $options['options']);
Tim Plunkett
committed
Tim Plunkett
committed
$this->plugins[$type][$name] = $plugin;
Tim Plunkett
committed
return $this->plugins[$type][$name];
}
/**
* Get the handler object for a single handler.
*/
Daniel Wehner
committed
public function &getHandler($type, $id) {
Daniel Wehner
committed
$this->getHandlers($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.
Angie Byron
committed
*
Alex Pott
committed
* @return \Drupal\views\Plugin\views\ViewsHandlerInterface[]
Daniel Wehner
committed
public function getHandlers($type) {
if (!isset($this->handlers[$type])) {
$this->handlers[$type] = array();
catch
committed
$types = ViewExecutable::getHandlerTypes();
// Cast to an array so that if the display does not have any handlers of
// this type there is no PHP error.
foreach ((array) $this->getOption($plural) as $id => $info) {
// 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.
Alex Pott
committed
if ($this->view->getRequest()->request->get('form_id') && isset($this->view->temporary_options[$type][$id])) {
$info = $this->view->temporary_options[$type][$id];
}
if ($info['id'] != $id) {
$info['id'] = $id;
}
// 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;
Daniel Wehner
committed
if ($this->useGroupBy() && !empty($info['group_type'])) {
Damian Lee
committed
$this->view->initQuery();
$aggregate = $this->view->query->getAggregationInfo();
if (!empty($aggregate[$info['group_type']]['handler'][$type])) {
$override = $aggregate[$info['group_type']]['handler'][$type];
}
}
if (!empty($types[$type]['type'])) {
$handler_type = $types[$type]['type'];
}
else {
$handler_type = $type;
}
Dries Buytaert
committed
if ($handler = Views::handlerManager($handler_type)->getHandler($info, $override)) {
// Special override for area types so they know where they come from.
if ($handler instanceof AreaPluginBase) {
$handler->areaType = $type;
$handler->init($this->view, $this, $info);
$this->handlers[$type][$id] = &$handler;
}
// Prevent reference problems.
unset($handler);
}
}
return $this->handlers[$type];
}
/**
* Retrieves a list of fields for the current display.
*
* This also takes into account any associated relationships, if they exist.
*
* @param bool $groupable_only
* (optional) TRUE to only return an array of field labels from handlers
Alex Pott
committed
* that support the useStringGroupBy method, defaults to FALSE.
*
* @return array
* An array of applicable field options, keyed by ID.
public function getFieldLabels($groupable_only = FALSE) {
Daniel Wehner
committed
foreach ($this->getHandlers('relationship') as $relationship => $handler) {
Alex Pott
committed
$relationships[$relationship] = $handler->adminLabel();
Daniel Wehner
committed
foreach ($this->getHandlers('field') as $id => $handler) {
Alex Pott
committed
if ($groupable_only && !$handler->useStringGroupBy()) {
// Continue to next handler if it's not groupable.
continue;
}
if ($label = $handler->label()) {
$options[$id] = $label;
}
else {
$options[$id] = $handler->adminLabel();
}
if (!empty($handler->options['relationship']) && !empty($relationships[$handler->options['relationship']])) {
$options[$id] = '(' . $relationships[$handler->options['relationship']] . ') ' . $options[$id];
}
}
return $options;
}
/**
* Intelligently set an option either from this display or from the
* default display, if directed to do so.
*/
Daniel Wehner
committed
public function setOption($option, $value) {
if ($this->isDefaulted($option)) {