upgrades core to 8.4.2
This commit is contained in:
@@ -77,7 +77,7 @@ class Analyzer {
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $messages,
|
||||
];
|
||||
$message = drupal_render($item_list);
|
||||
$message = \Drupal::service('renderer')->render($item_list);
|
||||
}
|
||||
elseif ($messages) {
|
||||
$message = array_shift($messages);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Drupal\views\Annotation;
|
||||
|
||||
|
||||
/**
|
||||
* Defines a Plugin annotation object for views access plugins.
|
||||
*
|
||||
|
||||
@@ -142,7 +142,7 @@ class ViewAjaxController implements ContainerInjectionInterface {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$view = $this->executableFactory->get($entity);
|
||||
if ($view && $view->access($display_id) && $view->setDisplay($display_id) && $view->display_handler->getOption('use_ajax')) {
|
||||
if ($view && $view->access($display_id) && $view->setDisplay($display_id) && $view->display_handler->ajaxEnabled()) {
|
||||
$response->setView($view);
|
||||
// Fix the current path for paging.
|
||||
if (!empty($path)) {
|
||||
@@ -181,7 +181,7 @@ class ViewAjaxController implements ContainerInjectionInterface {
|
||||
$view->dom_id = $dom_id;
|
||||
|
||||
$context = new RenderContext();
|
||||
$preview = $this->renderer->executeInRenderContext($context, function() use ($view, $display_id, $args) {
|
||||
$preview = $this->renderer->executeInRenderContext($context, function () use ($view, $display_id, $args) {
|
||||
return $view->preview($display_id, $args);
|
||||
});
|
||||
if (!$context->isEmpty()) {
|
||||
|
||||
@@ -28,15 +28,54 @@ class TranslationLanguageRenderer extends EntityTranslationRendererBase {
|
||||
if (!$this->languageManager->isMultilingual() || !$this->entityType->hasKey('langcode')) {
|
||||
return;
|
||||
}
|
||||
$langcode_key = $this->entityType->getKey('langcode');
|
||||
$storage = \Drupal::entityManager()->getStorage($this->entityType->id());
|
||||
|
||||
if ($table = $storage->getTableMapping()->getFieldTableName($langcode_key)) {
|
||||
$table_alias = $query->ensureTable($table, $relationship);
|
||||
$langcode_table = $this->getLangcodeTable($query, $relationship);
|
||||
if ($langcode_table) {
|
||||
/** @var \Drupal\views\Plugin\views\query\Sql $query */
|
||||
$table_alias = $query->ensureTable($langcode_table, $relationship);
|
||||
$langcode_key = $this->entityType->getKey('langcode');
|
||||
$this->langcodeAlias = $query->addField($table_alias, $langcode_key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the table holding the "langcode" field.
|
||||
*
|
||||
* @param \Drupal\views\Plugin\views\query\QueryPluginBase $query
|
||||
* The query being executed.
|
||||
* @param string $relationship
|
||||
* The relationship used by the entity type.
|
||||
*
|
||||
* @return string
|
||||
* A table name.
|
||||
*/
|
||||
protected function getLangcodeTable(QueryPluginBase $query, $relationship) {
|
||||
/** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */
|
||||
$storage = \Drupal::entityTypeManager()->getStorage($this->entityType->id());
|
||||
$langcode_key = $this->entityType->getKey('langcode');
|
||||
$langcode_table = $storage->getTableMapping()->getFieldTableName($langcode_key);
|
||||
|
||||
// If the entity type is revisionable, we need to take into account views of
|
||||
// entity revisions. Usually the view will use the entity data table as the
|
||||
// query base table, however, in case of an entity revision view, we need to
|
||||
// use the revision table or the revision data table, depending on which one
|
||||
// is being used as query base table.
|
||||
if ($this->entityType->isRevisionable()) {
|
||||
$query_base_table = isset($query->relationships[$relationship]['base']) ?
|
||||
$query->relationships[$relationship]['base'] :
|
||||
$this->view->storage->get('base_table');
|
||||
$revision_table = $storage->getRevisionTable();
|
||||
$revision_data_table = $storage->getRevisionDataTable();
|
||||
if ($query_base_table === $revision_table) {
|
||||
$langcode_table = $revision_table;
|
||||
}
|
||||
elseif ($query_base_table === $revision_data_table) {
|
||||
$langcode_table = $revision_data_table;
|
||||
}
|
||||
}
|
||||
|
||||
return $langcode_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -5,8 +5,11 @@ namespace Drupal\views\Entity;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\views\Plugin\DependentWithRemovalPluginInterface;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\ViewEntityInterface;
|
||||
|
||||
@@ -16,9 +19,6 @@ use Drupal\views\ViewEntityInterface;
|
||||
* @ConfigEntityType(
|
||||
* id = "view",
|
||||
* label = @Translation("View", context = "View entity type"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\views\ViewAccessControlHandler"
|
||||
* },
|
||||
* admin_permission = "administer views",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
@@ -290,10 +290,13 @@ class View extends ConfigEntityBase implements ViewEntityInterface {
|
||||
public function preSave(EntityStorageInterface $storage) {
|
||||
parent::preSave($storage);
|
||||
|
||||
$displays = $this->get('display');
|
||||
|
||||
$this->fixTableNames($displays);
|
||||
|
||||
// Sort the displays.
|
||||
$display = $this->get('display');
|
||||
ksort($display);
|
||||
$this->set('display', ['default' => $display['default']] + $display);
|
||||
ksort($displays);
|
||||
$this->set('display', ['default' => $displays['default']] + $displays);
|
||||
|
||||
// @todo Check whether isSyncing is needed.
|
||||
if (!$this->isSyncing()) {
|
||||
@@ -301,6 +304,45 @@ class View extends ConfigEntityBase implements ViewEntityInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes table names for revision metadata fields of revisionable entities.
|
||||
*
|
||||
* Views for revisionable entity types using revision metadata fields might
|
||||
* be using the wrong table to retrieve the fields after system_update_8300
|
||||
* has moved them correctly to the revision table. This method updates the
|
||||
* views to use the correct tables.
|
||||
*
|
||||
* @param array &$displays
|
||||
* An array containing display handlers of a view.
|
||||
*
|
||||
* @deprecated in Drupal 8.3.0, will be removed in Drupal 9.0.0.
|
||||
*/
|
||||
private function fixTableNames(array &$displays) {
|
||||
// Fix wrong table names for entity revision metadata fields.
|
||||
foreach ($displays as $display => $display_data) {
|
||||
if (isset($display_data['display_options']['fields'])) {
|
||||
foreach ($display_data['display_options']['fields'] as $property_name => $property_data) {
|
||||
if (isset($property_data['entity_type']) && isset($property_data['field']) && isset($property_data['table'])) {
|
||||
$entity_type = $this->entityTypeManager()->getDefinition($property_data['entity_type']);
|
||||
// We need to update the table name only for revisionable entity
|
||||
// types, otherwise the view is already using the correct table.
|
||||
if (($entity_type instanceof ContentEntityTypeInterface) && is_subclass_of($entity_type->getClass(), FieldableEntityInterface::class) && $entity_type->isRevisionable()) {
|
||||
$revision_metadata_fields = $entity_type->getRevisionMetadataKeys();
|
||||
// @see \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout()
|
||||
$revision_table = $entity_type->getRevisionTable() ?: $entity_type->id() . '_revision';
|
||||
|
||||
// Check if this is a revision metadata field and if it uses the
|
||||
// wrong table.
|
||||
if (in_array($property_data['field'], $revision_metadata_fields) && $property_data['table'] != $revision_table) {
|
||||
$displays[$display]['display_options']['fields'][$property_name]['table'] = $revision_table;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in the cache metadata of this view.
|
||||
*
|
||||
@@ -468,4 +510,61 @@ class View extends ConfigEntityBase implements ViewEntityInterface {
|
||||
\Drupal::service('cache_tags.invalidator')->invalidateTags($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
$changed = FALSE;
|
||||
|
||||
// Don't intervene if the views module is removed.
|
||||
if (isset($dependencies['module']) && in_array('views', $dependencies['module'])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If the base table for the View is provided by a module being removed, we
|
||||
// delete the View because this is not something that can be fixed manually.
|
||||
$views_data = Views::viewsData();
|
||||
$base_table = $this->get('base_table');
|
||||
$base_table_data = $views_data->get($base_table);
|
||||
if (!empty($base_table_data['table']['provider']) && in_array($base_table_data['table']['provider'], $dependencies['module'])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$current_display = $this->getExecutable()->current_display;
|
||||
$handler_types = Views::getHandlerTypes();
|
||||
|
||||
// Find all the handlers and check whether they want to do something on
|
||||
// dependency removal.
|
||||
foreach ($this->display as $display_id => $display_plugin_base) {
|
||||
$this->getExecutable()->setDisplay($display_id);
|
||||
$display = $this->getExecutable()->getDisplay();
|
||||
|
||||
foreach (array_keys($handler_types) as $handler_type) {
|
||||
$handlers = $display->getHandlers($handler_type);
|
||||
foreach ($handlers as $handler_id => $handler) {
|
||||
if ($handler instanceof DependentWithRemovalPluginInterface) {
|
||||
if ($handler->onDependencyRemoval($dependencies)) {
|
||||
// Remove the handler and indicate we made changes.
|
||||
unset($this->display[$display_id]['display_options'][$handler_types[$handler_type]['plural']][$handler_id]);
|
||||
$changed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the View if we made changes.
|
||||
// @todo https://www.drupal.org/node/2832558 Give better feedback for
|
||||
// disabled config.
|
||||
if ($changed) {
|
||||
// Force a recalculation of the dependencies if we made changes.
|
||||
$this->getExecutable()->current_display = NULL;
|
||||
$this->calculateDependencies();
|
||||
$this->disable();
|
||||
}
|
||||
|
||||
$this->getExecutable()->setDisplay($current_display);
|
||||
return $changed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -236,6 +236,13 @@ class EntityViewsData implements EntityHandlerInterface, EntityViewsDataInterfac
|
||||
'type' => 'INNER',
|
||||
];
|
||||
}
|
||||
|
||||
// Add a filter for showing only the latest revisions of an entity.
|
||||
$data[$revision_table]['latest_revision'] = [
|
||||
'title' => $this->t('Is Latest Revision'),
|
||||
'help' => $this->t('Restrict the view to only revisions that are the latest revision of their entity.'),
|
||||
'filter' => ['id' => 'latest_revision'],
|
||||
];
|
||||
}
|
||||
|
||||
$this->addEntityLinks($data[$base_table]);
|
||||
@@ -300,7 +307,7 @@ class EntityViewsData implements EntityHandlerInterface, EntityViewsDataInterfac
|
||||
|
||||
// Add the entity type key to each table generated.
|
||||
$entity_type_id = $this->entityType->id();
|
||||
array_walk($data, function(&$table_data) use ($entity_type_id){
|
||||
array_walk($data, function (&$table_data) use ($entity_type_id) {
|
||||
$table_data['table']['entity type'] = $entity_type_id;
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Drupal\views;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\views\Plugin\views\HandlerBase;
|
||||
|
||||
@@ -268,8 +269,8 @@ class ManyToOneHelper {
|
||||
$options['group'] = 0;
|
||||
}
|
||||
|
||||
// add_condition determines whether a single expression is enough(FALSE) or the
|
||||
// conditions should be added via an db_or()/db_and() (TRUE).
|
||||
// If $add_condition is set to FALSE, a single expression is enough. If it
|
||||
// is set to TRUE, conditions will be added.
|
||||
$add_condition = TRUE;
|
||||
if ($operator == 'not') {
|
||||
$value = NULL;
|
||||
@@ -326,7 +327,7 @@ class ManyToOneHelper {
|
||||
|
||||
if ($add_condition) {
|
||||
$field = $this->handler->realField;
|
||||
$clause = $operator == 'or' ? db_or() : db_and();
|
||||
$clause = $operator == 'or' ? new Condition('OR') : new Condition('AND');
|
||||
foreach ($this->handler->tableAliases as $value => $alias) {
|
||||
$clause->condition("$alias.$field", $value);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
|
||||
/**
|
||||
@@ -24,9 +25,23 @@ class ViewsExposedFilterBlock extends ViewsBlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array
|
||||
* A renderable array representing the content of the block with additional
|
||||
* context of current view and display ID.
|
||||
*/
|
||||
public function build() {
|
||||
$output = $this->view->display_handler->viewExposedFormBlocks();
|
||||
// Provide the context for block build and block view alter hooks.
|
||||
// \Drupal\views\Plugin\Block\ViewsBlock::build() adds the same context in
|
||||
// \Drupal\views\ViewExecutable::buildRenderable() using
|
||||
// \Drupal\views\Plugin\views\display\DisplayPluginBase::buildRenderable().
|
||||
if (is_array($output) && !empty($output)) {
|
||||
$output += [
|
||||
'#view' => $this->view,
|
||||
'#display_id' => $this->displayID,
|
||||
];
|
||||
}
|
||||
|
||||
// Before returning the block output, convert it to a renderable array with
|
||||
// contextual links.
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Plugin;
|
||||
|
||||
/**
|
||||
* Provides an interface for a plugin that has dependencies that can be removed.
|
||||
*
|
||||
* @ingroup views_plugins
|
||||
*/
|
||||
interface DependentWithRemovalPluginInterface {
|
||||
|
||||
/**
|
||||
* Allows a plugin to define whether it should be removed.
|
||||
*
|
||||
* If this method returns TRUE then the plugin should be removed.
|
||||
*
|
||||
* @param array $dependencies
|
||||
* An array of dependencies that will be deleted keyed by dependency type.
|
||||
* Dependency types are, for example, entity, module and theme.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the plugin instance should be removed.
|
||||
*
|
||||
* @see \Drupal\Core\Config\Entity\ConfigDependencyManager
|
||||
* @see \Drupal\Core\Config\ConfigEntityBase::preDelete()
|
||||
* @see \Drupal\Core\Config\ConfigManager::uninstall()
|
||||
* @see \Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval()
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies);
|
||||
|
||||
}
|
||||
@@ -2,17 +2,12 @@
|
||||
|
||||
namespace Drupal\views\Plugin\EntityReferenceSelection;
|
||||
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase;
|
||||
use Drupal\Core\Entity\EntityReferenceSelection\SelectionTrait;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Plugin\PluginBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\views\Views;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'selection' entity_reference.
|
||||
@@ -24,66 +19,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
* weight = 0
|
||||
* )
|
||||
*/
|
||||
class ViewsSelection extends PluginBase implements SelectionInterface, ContainerFactoryPluginInterface {
|
||||
class ViewsSelection extends SelectionPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The module handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Constructs a new SelectionBase object.
|
||||
*
|
||||
* @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.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager service.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->currentUser = $current_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('entity.manager'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
use SelectionTrait;
|
||||
|
||||
/**
|
||||
* The loaded View object.
|
||||
@@ -92,12 +30,26 @@ class ViewsSelection extends PluginBase implements SelectionInterface, Container
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [
|
||||
'view' => [
|
||||
'view_name' => NULL,
|
||||
'display_name' => NULL,
|
||||
'arguments' => [],
|
||||
],
|
||||
] + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$selection_handler_settings = $this->configuration['handler_settings'];
|
||||
$view_settings = !empty($selection_handler_settings['view']) ? $selection_handler_settings['view'] : [];
|
||||
$form = parent::buildConfigurationForm($form, $form_state);
|
||||
|
||||
$view_settings = $this->getConfiguration()['view'];
|
||||
$displays = Views::getApplicableViews('entity_reference_display');
|
||||
// Filter views that list the entity type we want, and group the separate
|
||||
// displays by view.
|
||||
@@ -156,16 +108,6 @@ class ViewsSelection extends PluginBase implements SelectionInterface, Container
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { }
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { }
|
||||
|
||||
/**
|
||||
* Initializes a view.
|
||||
*
|
||||
@@ -184,9 +126,8 @@ class ViewsSelection extends PluginBase implements SelectionInterface, Container
|
||||
* Return TRUE if the view was initialized, FALSE otherwise.
|
||||
*/
|
||||
protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $limit = 0, $ids = NULL) {
|
||||
$handler_settings = $this->configuration['handler_settings'];
|
||||
$view_name = $handler_settings['view']['view_name'];
|
||||
$display_name = $handler_settings['view']['display_name'];
|
||||
$view_name = $this->getConfiguration()['view']['view_name'];
|
||||
$display_name = $this->getConfiguration()['view']['display_name'];
|
||||
|
||||
// Check that the view is valid and the display still exists.
|
||||
$this->view = Views::getView($view_name);
|
||||
@@ -211,9 +152,8 @@ class ViewsSelection extends PluginBase implements SelectionInterface, Container
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
|
||||
$handler_settings = $this->configuration['handler_settings'];
|
||||
$display_name = $handler_settings['view']['display_name'];
|
||||
$arguments = $handler_settings['view']['arguments'];
|
||||
$display_name = $this->getConfiguration()['view']['display_name'];
|
||||
$arguments = $this->getConfiguration()['view']['arguments'];
|
||||
$result = [];
|
||||
if ($this->initializeView($match, $match_operator, $limit)) {
|
||||
// Get the results.
|
||||
@@ -242,9 +182,8 @@ class ViewsSelection extends PluginBase implements SelectionInterface, Container
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateReferenceableEntities(array $ids) {
|
||||
$handler_settings = $this->configuration['handler_settings'];
|
||||
$display_name = $handler_settings['view']['display_name'];
|
||||
$arguments = $handler_settings['view']['arguments'];
|
||||
$display_name = $this->getConfiguration()['view']['display_name'];
|
||||
$arguments = $this->getConfiguration()['view']['arguments'];
|
||||
$result = [];
|
||||
if ($this->initializeView(NULL, 'CONTAINS', 0, $ids)) {
|
||||
// Get the results.
|
||||
@@ -283,9 +222,4 @@ class ViewsSelection extends PluginBase implements SelectionInterface, Container
|
||||
$form_state->setValueForElement($element, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function entityQueryAlter(SelectInterface $query) { }
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ trait BrokenHandlerTrait {
|
||||
}
|
||||
}
|
||||
|
||||
$description_bottom = t('Enabling the appropriate module will may solve this issue. Otherwise, check to see if there is a module update available.');
|
||||
$description_bottom = t('Enabling the appropriate module may solve this issue. Otherwise, check to see if there is a module update available.');
|
||||
|
||||
$form['description'] = [
|
||||
'#type' => 'container',
|
||||
|
||||
@@ -214,16 +214,16 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
||||
* Transform a string by a certain method.
|
||||
*
|
||||
* @param $string
|
||||
* The input you want to transform.
|
||||
* The input you want to transform.
|
||||
* @param $option
|
||||
* How do you want to transform it, possible values:
|
||||
* - upper: Uppercase the string.
|
||||
* - lower: lowercase the string.
|
||||
* - ucfirst: Make the first char uppercase.
|
||||
* - ucwords: Make each word in the string uppercase.
|
||||
* How do you want to transform it, possible values:
|
||||
* - upper: Uppercase the string.
|
||||
* - lower: lowercase the string.
|
||||
* - ucfirst: Make the first char uppercase.
|
||||
* - ucwords: Make each word in the string uppercase.
|
||||
*
|
||||
* @return string
|
||||
* The transformed string.
|
||||
* The transformed string.
|
||||
*/
|
||||
protected function caseTransform($string, $option) {
|
||||
switch ($option) {
|
||||
@@ -350,80 +350,84 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
||||
* If a handler has 'extra options' it will get a little settings widget and
|
||||
* another form called extra_options.
|
||||
*/
|
||||
public function hasExtraOptions() { return FALSE; }
|
||||
public function hasExtraOptions() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide defaults for the handler.
|
||||
*/
|
||||
public function defineExtraOptions(&$option) { }
|
||||
public function defineExtraOptions(&$option) {}
|
||||
|
||||
/**
|
||||
* Provide a form for setting options.
|
||||
*/
|
||||
public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Validate the options form.
|
||||
*/
|
||||
public function validateExtraOptionsForm($form, FormStateInterface $form_state) { }
|
||||
public function validateExtraOptionsForm($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Perform any necessary changes to the form values prior to storage.
|
||||
* There is no need for this function to actually store the data.
|
||||
*/
|
||||
public function submitExtraOptionsForm($form, FormStateInterface $form_state) { }
|
||||
public function submitExtraOptionsForm($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Determine if a handler can be exposed.
|
||||
*/
|
||||
public function canExpose() { return FALSE; }
|
||||
public function canExpose() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new exposed option defaults when exposed setting is flipped
|
||||
* on.
|
||||
*/
|
||||
public function defaultExposeOptions() { }
|
||||
public function defaultExposeOptions() {}
|
||||
|
||||
/**
|
||||
* Get information about the exposed form for the form renderer.
|
||||
*/
|
||||
public function exposedInfo() { }
|
||||
public function exposedInfo() {}
|
||||
|
||||
/**
|
||||
* Render our chunk of the exposed handler form when selecting
|
||||
*/
|
||||
public function buildExposedForm(&$form, FormStateInterface $form_state) { }
|
||||
public function buildExposedForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Validate the exposed handler form
|
||||
*/
|
||||
public function validateExposed(&$form, FormStateInterface $form_state) { }
|
||||
public function validateExposed(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Submit the exposed handler form
|
||||
*/
|
||||
public function submitExposed(&$form, FormStateInterface $form_state) { }
|
||||
public function submitExposed(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Form for exposed handler options.
|
||||
*/
|
||||
public function buildExposeForm(&$form, FormStateInterface $form_state) { }
|
||||
public function buildExposeForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Validate the options form.
|
||||
*/
|
||||
public function validateExposeForm($form, FormStateInterface $form_state) { }
|
||||
public function validateExposeForm($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Perform any necessary changes to the form exposes prior to storage.
|
||||
* There is no need for this function to actually store the data.
|
||||
*/
|
||||
public function submitExposeForm($form, FormStateInterface $form_state) { }
|
||||
public function submitExposeForm($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Shortcut to display the expose/hide button.
|
||||
*/
|
||||
public function showExposeButton(&$form, FormStateInterface $form_state) { }
|
||||
public function showExposeButton(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Shortcut to display the exposed options form.
|
||||
@@ -477,7 +481,7 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postExecute(&$values) { }
|
||||
public function postExecute(&$values) {}
|
||||
|
||||
/**
|
||||
* Provides a unique placeholders for handlers.
|
||||
@@ -531,7 +535,7 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function adminSummary() { }
|
||||
public function adminSummary() {}
|
||||
|
||||
/**
|
||||
* Determine if this item is 'exposed', meaning it provides form elements
|
||||
@@ -546,24 +550,32 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
||||
/**
|
||||
* Returns TRUE if the exposed filter works like a grouped filter.
|
||||
*/
|
||||
public function isAGroup() { return FALSE; }
|
||||
public function isAGroup() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define if the exposed input has to be submitted multiple times.
|
||||
* This is TRUE when exposed filters grouped are using checkboxes as
|
||||
* widgets.
|
||||
*/
|
||||
public function multipleExposedInput() { return FALSE; }
|
||||
public function multipleExposedInput() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take input from exposed handlers and assign to this handler, if necessary.
|
||||
*/
|
||||
public function acceptExposedInput($input) { return TRUE; }
|
||||
public function acceptExposedInput($input) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to remember exposed input in the session, store it there.
|
||||
*/
|
||||
public function storeExposedInput($input, $status) { return TRUE; }
|
||||
public function storeExposedInput($input, $status) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -587,7 +599,9 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate() { return []; }
|
||||
public function validate() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
||||
@@ -155,7 +155,9 @@ abstract class PluginBase extends ComponentPluginBase implements ContainerFactor
|
||||
* @return array
|
||||
* Returns the options of this handler/plugin.
|
||||
*/
|
||||
protected function defineOptions() { return []; }
|
||||
protected function defineOptions() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills up the options of the plugin with defaults.
|
||||
@@ -271,17 +273,17 @@ abstract class PluginBase extends ComponentPluginBase implements ContainerFactor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() { }
|
||||
public function query() {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -293,7 +295,9 @@ abstract class PluginBase extends ComponentPluginBase implements ContainerFactor
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate() { return []; }
|
||||
public function validate() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -351,7 +355,7 @@ abstract class PluginBase extends ComponentPluginBase implements ContainerFactor
|
||||
foreach ($tokens as $token => $replacement) {
|
||||
// Twig wants a token replacement array stripped of curly-brackets.
|
||||
// Some Views tokens come with curly-braces, others do not.
|
||||
//@todo: https://www.drupal.org/node/2544392
|
||||
// @todo: https://www.drupal.org/node/2544392
|
||||
if (strpos($token, '{{') !== FALSE) {
|
||||
// Twig wants a token replacement array stripped of curly-brackets.
|
||||
$token = trim(str_replace(['{{', '}}'], '', $token));
|
||||
|
||||
@@ -107,7 +107,7 @@ abstract class AreaPluginBase extends HandlerBase {
|
||||
* @return array
|
||||
* In any case we need a valid Drupal render array to return.
|
||||
*/
|
||||
public abstract function render($empty = FALSE);
|
||||
abstract public function render($empty = FALSE);
|
||||
|
||||
/**
|
||||
* Does that area have nothing to show.
|
||||
|
||||
@@ -42,7 +42,7 @@ class HTTPStatusCode extends AreaPluginBase {
|
||||
] + $options;
|
||||
|
||||
// Add the HTTP status code, so it's easier for people to find it.
|
||||
array_walk($options, function($title, $code) use(&$options) {
|
||||
array_walk($options, function ($title, $code) use (&$options) {
|
||||
$options[$code] = $this->t('@code (@title)', ['@code' => $code, '@title' => $title]);
|
||||
});
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class Result extends AreaPluginBase {
|
||||
'@page_count -- the total page count',
|
||||
],
|
||||
];
|
||||
$list = drupal_render($item_list);
|
||||
$list = \Drupal::service('renderer')->render($item_list);
|
||||
$form['content'] = [
|
||||
'#title' => $this->t('Display'),
|
||||
'#type' => 'textarea',
|
||||
|
||||
@@ -325,7 +325,8 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend
|
||||
'#suffix' => '</div>',
|
||||
'#type' => 'item',
|
||||
// Even if the plugin has no options add the key to the form_state.
|
||||
'#input' => TRUE, // trick it into checking input to make #process run
|
||||
// trick it into checking input to make #process run.
|
||||
'#input' => TRUE,
|
||||
'#states' => [
|
||||
'visible' => [
|
||||
':input[name="options[specify_validation]"]' => ['checked' => TRUE],
|
||||
@@ -498,12 +499,14 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend
|
||||
'method' => 'defaultDefault',
|
||||
'form method' => 'defaultArgumentForm',
|
||||
'has default argument' => TRUE,
|
||||
'default only' => TRUE, // this can only be used for missing argument, not validation failure
|
||||
// This can only be used for missing argument, not validation failure.
|
||||
'default only' => TRUE,
|
||||
],
|
||||
'not found' => [
|
||||
'title' => $this->t('Hide view'),
|
||||
'method' => 'defaultNotFound',
|
||||
'hard fail' => TRUE, // This is a hard fail condition
|
||||
// This is a hard fail condition.
|
||||
'hard fail' => TRUE,
|
||||
],
|
||||
'summary' => [
|
||||
'title' => $this->t('Display a summary'),
|
||||
@@ -669,7 +672,8 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend
|
||||
'#suffix' => '</div>',
|
||||
'#id' => 'edit-options-summary-options-' . $id,
|
||||
'#type' => 'item',
|
||||
'#input' => TRUE, // trick it into checking input to make #process run
|
||||
// Trick it into checking input to make #process run.
|
||||
'#input' => TRUE,
|
||||
'#states' => [
|
||||
'visible' => [
|
||||
':input[name="options[default_action]"]' => ['value' => 'summary'],
|
||||
|
||||
@@ -24,7 +24,7 @@ class MonthDate extends Date {
|
||||
*/
|
||||
public function summaryName($data) {
|
||||
$month = str_pad($data->{$this->name_alias}, 2, '0', STR_PAD_LEFT);
|
||||
return format_date(strtotime("2005" . $month . "15" . " 00:00:00 UTC" ), 'custom', $this->format, 'UTC');
|
||||
return format_date(strtotime("2005" . $month . "15" . " 00:00:00 UTC"), 'custom', $this->format, 'UTC');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,7 +86,7 @@ class NumericArgument extends ArgumentPluginBase {
|
||||
/**
|
||||
* Override for specific title lookups.
|
||||
* @return array
|
||||
* Returns all titles, if it's just one title it's an array with one entry.
|
||||
* Returns all titles, if it's just one title it's an array with one entry.
|
||||
*/
|
||||
public function titleQuery() {
|
||||
return $this->value;
|
||||
|
||||
@@ -42,7 +42,7 @@ abstract class ArgumentDefaultPluginBase extends PluginBase {
|
||||
*
|
||||
* This needs to be overridden by every default argument handler to properly do what is needed.
|
||||
*/
|
||||
public function getArgument() { }
|
||||
public function getArgument() {}
|
||||
|
||||
/**
|
||||
* Sets the parent argument this plugin is associated with.
|
||||
@@ -58,28 +58,32 @@ abstract class ArgumentDefaultPluginBase extends PluginBase {
|
||||
* Retrieve the options when this is a new access
|
||||
* control plugin
|
||||
*/
|
||||
protected function defineOptions() { return []; }
|
||||
protected function defineOptions() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the default form for setting options.
|
||||
*/
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Provide the default form form for validating options
|
||||
*/
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Provide the default form form for submitting options
|
||||
*/
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) {}
|
||||
|
||||
/**
|
||||
* Determine if the administrator has the privileges to use this
|
||||
* plugin
|
||||
*/
|
||||
public function access() { return TRUE; }
|
||||
public function access() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we don't have access to the form but are showing it anyway, ensure that
|
||||
|
||||
+14
-8
@@ -53,27 +53,31 @@ abstract class ArgumentValidatorPluginBase extends PluginBase {
|
||||
/**
|
||||
* Retrieves the options when this is a new access control plugin.
|
||||
*/
|
||||
protected function defineOptions() { return []; }
|
||||
protected function defineOptions() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the default form for setting options.
|
||||
*/
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Provides the default form for validating options.
|
||||
*/
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Provides the default form for submitting options.
|
||||
*/
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) {}
|
||||
|
||||
/**
|
||||
* Determines if the administrator has the privileges to use this plugin.
|
||||
*/
|
||||
public function access() { return TRUE; }
|
||||
public function access() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks user input when the form is shown but we don´t have access.
|
||||
@@ -92,7 +96,9 @@ abstract class ArgumentValidatorPluginBase extends PluginBase {
|
||||
/**
|
||||
* Performs validation for a given argument.
|
||||
*/
|
||||
public function validateArgument($arg) { return TRUE; }
|
||||
public function validateArgument($arg) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the summary arguments for displaying.
|
||||
@@ -102,7 +108,7 @@ abstract class ArgumentValidatorPluginBase extends PluginBase {
|
||||
* for a faster query. But there are use cases where you want to use
|
||||
* the old value again, for example the summary.
|
||||
*/
|
||||
public function processSummaryArguments(&$args) { }
|
||||
public function processSummaryArguments(&$args) {}
|
||||
|
||||
/**
|
||||
* Returns a context definition for this argument.
|
||||
@@ -111,7 +117,7 @@ abstract class ArgumentValidatorPluginBase extends PluginBase {
|
||||
* A context definition that represents the argument or NULL if that is
|
||||
* not possible.
|
||||
*/
|
||||
public function getContextDefinition() { }
|
||||
public function getContextDefinition() {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ abstract class CachePluginBase extends PluginBase {
|
||||
* All of the cached result data will be available in $view->result, as well,
|
||||
* so all ids used in the query should be discoverable.
|
||||
*/
|
||||
public function postRender(&$output) { }
|
||||
public function postRender(&$output) {}
|
||||
|
||||
/**
|
||||
* Calculates and sets a cache ID used for the result cache.
|
||||
@@ -190,7 +190,7 @@ abstract class CachePluginBase extends PluginBase {
|
||||
$query = clone $build_info[$index];
|
||||
$query->preExecute();
|
||||
$build_info[$index] = [
|
||||
'query' => (string)$query,
|
||||
'query' => (string) $query,
|
||||
'arguments' => $query->getArguments(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ class DefaultDisplay extends DisplayPluginBase {
|
||||
* Determine if this display is the 'default' display which contains
|
||||
* fallback settings
|
||||
*/
|
||||
public function isDefaultDisplay() { return TRUE; }
|
||||
public function isDefaultDisplay() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default execute handler fully renders the view.
|
||||
|
||||
@@ -234,7 +234,9 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDefaultDisplay() { return FALSE; }
|
||||
public function isDefaultDisplay() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -394,7 +396,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function attachTo(ViewExecutable $view, $display_id, array &$build) { }
|
||||
public function attachTo(ViewExecutable $view, $display_id, array &$build) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -665,17 +667,23 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasPath() { return FALSE; }
|
||||
public function hasPath() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function usesLinkDisplay() { return !$this->hasPath(); }
|
||||
public function usesLinkDisplay() {
|
||||
return !$this->hasPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function usesExposedFormInBlock() { return $this->hasPath(); }
|
||||
public function usesExposedFormInBlock() {
|
||||
return $this->hasPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -772,7 +780,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
return $this->default_display->getOption($option);
|
||||
}
|
||||
|
||||
if (array_key_exists($option, $this->options)) {
|
||||
if (isset($this->options[$option]) || array_key_exists($option, $this->options)) {
|
||||
return $this->options[$option];
|
||||
}
|
||||
}
|
||||
@@ -2051,7 +2059,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderFilters() { }
|
||||
public function renderFilters() {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -2115,7 +2123,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
'#cache' => &$this->view->element['#cache'],
|
||||
];
|
||||
|
||||
$this->applyDisplayCachablityMetadata($this->view->element);
|
||||
$this->applyDisplayCacheabilityMetadata($this->view->element);
|
||||
|
||||
return $element;
|
||||
}
|
||||
@@ -2126,7 +2134,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
* @param array $element
|
||||
* The render array with updated cacheability metadata.
|
||||
*/
|
||||
protected function applyDisplayCachablityMetadata(array &$element) {
|
||||
protected function applyDisplayCacheabilityMetadata(array &$element) {
|
||||
/** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
|
||||
$cache = $this->getPlugin('cache');
|
||||
|
||||
@@ -2138,6 +2146,22 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
->applyTo($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the cacheability of the current display to the given render array.
|
||||
*
|
||||
* @param array $element
|
||||
* The render array with updated cacheability metadata.
|
||||
*
|
||||
* @deprecated in Drupal 8.4.0, will be removed before Drupal 9.0. Use
|
||||
* DisplayPluginBase::applyDisplayCacheabilityMetadata instead.
|
||||
*
|
||||
* @see \Drupal\views\Plugin\views\display\DisplayPluginBase::applyDisplayCacheabilityMetadata()
|
||||
*/
|
||||
protected function applyDisplayCachablityMetadata(array &$element) {
|
||||
@trigger_error('The DisplayPluginBase::applyDisplayCachablityMetadata method is deprecated since version 8.4 and will be removed in 9.0. Use DisplayPluginBase::applyDisplayCacheabilityMetadata instead.', E_USER_DEPRECATED);
|
||||
$this->applyDisplayCacheabilityMetadata($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -2309,7 +2333,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute() { }
|
||||
public function execute() {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -2330,7 +2354,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte
|
||||
// of cacheability metadata (e.g.: cache contexts), so they can bubble up.
|
||||
// Thus, we add the cacheability metadata first, then modify / remove the
|
||||
// cache keys depending on the $cache argument.
|
||||
$this->applyDisplayCachablityMetadata($this->view->element);
|
||||
$this->applyDisplayCacheabilityMetadata($this->view->element);
|
||||
if ($cache) {
|
||||
$this->view->element['#cache'] += ['keys' => []];
|
||||
// Places like \Drupal\views\ViewExecutable::setCurrentPage() set up an
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\views\Plugin\views\display;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
|
||||
/**
|
||||
* The plugin that handles an EntityReference display.
|
||||
*
|
||||
@@ -88,13 +90,16 @@ class EntityReference extends DisplayPluginBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Builds the view result as a renderable array.
|
||||
*
|
||||
* @return array
|
||||
* Renderable array or empty array.
|
||||
*/
|
||||
public function render() {
|
||||
if (!empty($this->view->result) && $this->view->style_plugin->evenEmpty()) {
|
||||
return $this->view->style_plugin->render($this->view->result);
|
||||
}
|
||||
return '';
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +136,7 @@ class EntityReference extends DisplayPluginBase {
|
||||
}
|
||||
|
||||
// Multiple search fields are OR'd together.
|
||||
$conditions = db_or();
|
||||
$conditions = new Condition('OR');
|
||||
|
||||
// Build the condition using the selected search fields.
|
||||
foreach ($style_options['options']['search_fields'] as $field_id) {
|
||||
|
||||
@@ -106,7 +106,7 @@ class Feed extends PathPluginBase implements ResponseDisplayPluginInterface {
|
||||
public function render() {
|
||||
$build = $this->view->style_plugin->render($this->view->result);
|
||||
|
||||
$this->applyDisplayCachablityMetadata($build);
|
||||
$this->applyDisplayCacheabilityMetadata($build);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
@@ -36,45 +36,45 @@ abstract class DisplayExtenderPluginBase extends PluginBase {
|
||||
/**
|
||||
* Provide a form to edit options for this plugin.
|
||||
*/
|
||||
public function defineOptionsAlter(&$options) { }
|
||||
public function defineOptionsAlter(&$options) {}
|
||||
|
||||
/**
|
||||
* Provide a form to edit options for this plugin.
|
||||
*/
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Validate the options form.
|
||||
*/
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Handle any special handling on the validate form.
|
||||
*/
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Set up any variables on the view prior to execution.
|
||||
*/
|
||||
public function preExecute() { }
|
||||
public function preExecute() {}
|
||||
|
||||
/**
|
||||
* Inject anything into the query that the display_extender handler needs.
|
||||
*/
|
||||
public function query() { }
|
||||
public function query() {}
|
||||
|
||||
/**
|
||||
* Provide the default summary for options in the views UI.
|
||||
*
|
||||
* This output is returned as an array.
|
||||
*/
|
||||
public function optionsSummary(&$categories, &$options) { }
|
||||
public function optionsSummary(&$categories, &$options) {}
|
||||
|
||||
/**
|
||||
* Static member function to list which sections are defaultable
|
||||
* and what items each section contains.
|
||||
*/
|
||||
public function defaultableSections(&$sections, $section = NULL) { }
|
||||
public function defaultableSections(&$sections, $section = NULL) {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -179,22 +179,22 @@ abstract class ExposedFormPluginBase extends PluginBase implements CacheableDepe
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender($values) { }
|
||||
public function preRender($values) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postRender(&$output) { }
|
||||
public function postRender(&$output) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preExecute() { }
|
||||
public function preExecute() {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postExecute() { }
|
||||
public function postExecute() {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
||||
@@ -119,7 +119,7 @@ class Date extends FieldPluginBase {
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Timezone'),
|
||||
'#description' => $this->t('Timezone to be used for date output.'),
|
||||
'#options' => ['' => $this->t('- Default site/user timezone -')] + system_time_zones(FALSE),
|
||||
'#options' => ['' => $this->t('- Default site/user timezone -')] + system_time_zones(FALSE, TRUE),
|
||||
'#default_value' => $this->options['timezone'],
|
||||
];
|
||||
foreach (array_merge(['custom'], array_keys($date_formats)) as $timezone_date_formats) {
|
||||
@@ -143,7 +143,9 @@ class Date extends FieldPluginBase {
|
||||
|
||||
if ($value) {
|
||||
$timezone = !empty($this->options['timezone']) ? $this->options['timezone'] : NULL;
|
||||
$time_diff = REQUEST_TIME - $value; // will be positive for a datetime in the past (ago), and negative for a datetime in the future (hence)
|
||||
// Will be positive for a datetime in the past (ago), and negative for a
|
||||
// datetime in the future (hence).
|
||||
$time_diff = REQUEST_TIME - $value;
|
||||
switch ($format) {
|
||||
case 'raw time ago':
|
||||
return $this->dateFormatter->formatTimeDiffSince($value, ['granularity' => is_numeric($custom_format) ? $custom_format : 2]);
|
||||
|
||||
@@ -23,6 +23,7 @@ use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\views\FieldAPIHandlerTrait;
|
||||
use Drupal\views\Entity\Render\EntityFieldRenderer;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Plugin\DependentWithRemovalPluginInterface;
|
||||
use Drupal\views\ResultRow;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
@@ -34,7 +35,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
*
|
||||
* @ViewsField("field")
|
||||
*/
|
||||
class EntityField extends FieldPluginBase implements CacheableDependencyInterface, MultiItemsFieldHandlerInterface {
|
||||
class EntityField extends FieldPluginBase implements CacheableDependencyInterface, MultiItemsFieldHandlerInterface, DependentWithRemovalPluginInterface {
|
||||
|
||||
use FieldAPIHandlerTrait;
|
||||
use PluginDependencyTrait;
|
||||
@@ -315,24 +316,33 @@ class EntityField extends FieldPluginBase implements CacheableDependencyInterfac
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field storage of the used field.
|
||||
* Gets the field storage definition.
|
||||
*
|
||||
* @return \Drupal\Core\Field\FieldStorageDefinitionInterface
|
||||
* The field storage definition used by this handler.
|
||||
*/
|
||||
protected function getFieldStorageDefinition() {
|
||||
$entity_type_id = $this->definition['entity_type'];
|
||||
$field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
||||
|
||||
$field_storage = NULL;
|
||||
// @todo Unify 'entity field'/'field_name' instead of converting back and
|
||||
// forth. https://www.drupal.org/node/2410779
|
||||
if (isset($this->definition['field_name'])) {
|
||||
$field_storage = $field_storage_definitions[$this->definition['field_name']];
|
||||
if (isset($this->definition['field_name']) && isset($field_storage_definitions[$this->definition['field_name']])) {
|
||||
return $field_storage_definitions[$this->definition['field_name']];
|
||||
}
|
||||
elseif (isset($this->definition['entity field'])) {
|
||||
$field_storage = $field_storage_definitions[$this->definition['entity field']];
|
||||
|
||||
if (isset($this->definition['entity field']) && isset($field_storage_definitions[$this->definition['entity field']])) {
|
||||
return $field_storage_definitions[$this->definition['entity field']];
|
||||
}
|
||||
|
||||
// The list of field storage definitions above does not include computed
|
||||
// base fields, so we need to explicitly fetch a list of all base fields in
|
||||
// order to support them.
|
||||
// @see \Drupal\Core\Entity\EntityFieldManager::getFieldStorageDefinitions()
|
||||
$base_fields = $this->entityManager->getBaseFieldDefinitions($entity_type_id);
|
||||
if (isset($this->definition['field_name']) && isset($base_fields[$this->definition['field_name']])) {
|
||||
return $base_fields[$this->definition['field_name']]->getFieldStorageDefinition();
|
||||
}
|
||||
return $field_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1042,10 +1052,13 @@ class EntityField extends FieldPluginBase implements CacheableDependencyInterfac
|
||||
*/
|
||||
public function getValue(ResultRow $values, $field = NULL) {
|
||||
$entity = $this->getEntity($values);
|
||||
// Retrieve the translated object.
|
||||
$translated_entity = $this->getEntityFieldRenderer()->getEntityTranslation($entity, $values);
|
||||
|
||||
// Some bundles might not have a specific field, in which case the entity
|
||||
// (potentially a fake one) doesn't have it either.
|
||||
/** @var \Drupal\Core\Field\FieldItemListInterface $field_item_list */
|
||||
$field_item_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']} : NULL;
|
||||
$field_item_list = isset($translated_entity->{$this->definition['field_name']}) ? $translated_entity->{$this->definition['field_name']} : NULL;
|
||||
|
||||
if (!isset($field_item_list)) {
|
||||
// There isn't anything we can do without a valid field.
|
||||
@@ -1077,4 +1090,29 @@ class EntityField extends FieldPluginBase implements CacheableDependencyInterfac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
// See if this handler is responsible for any of the dependencies being
|
||||
// removed. If this is the case, indicate that this handler needs to be
|
||||
// removed from the View.
|
||||
$remove = FALSE;
|
||||
// Get all the current dependencies for this handler.
|
||||
$current_dependencies = $this->calculateDependencies();
|
||||
foreach ($current_dependencies as $group => $dependency_list) {
|
||||
// Check if any of the handler dependencies match the dependencies being
|
||||
// removed.
|
||||
foreach ($dependency_list as $config_key) {
|
||||
if (isset($dependencies[$group]) && array_key_exists($config_key, $dependencies[$group])) {
|
||||
// This handlers dependency matches a dependency being removed,
|
||||
// indicate that this handler needs to be removed.
|
||||
$remove = TRUE;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $remove;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class EntityOperations extends FieldPluginBase {
|
||||
* @param array $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
*/
|
||||
|
||||
@@ -865,10 +865,10 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf
|
||||
$optgroup_arguments = (string) t('Arguments');
|
||||
$optgroup_fields = (string) t('Fields');
|
||||
foreach ($previous as $id => $label) {
|
||||
$options[$optgroup_fields]["{{ $id }}"] = substr(strrchr($label, ":"), 2 );
|
||||
$options[$optgroup_fields]["{{ $id }}"] = substr(strrchr($label, ":"), 2);
|
||||
}
|
||||
// Add the field to the list of options.
|
||||
$options[$optgroup_fields]["{{ {$this->options['id']} }}"] = substr(strrchr($this->adminLabel(), ":"), 2 );
|
||||
$options[$optgroup_fields]["{{ {$this->options['id']} }}"] = substr(strrchr($this->adminLabel(), ":"), 2);
|
||||
|
||||
foreach ($this->view->display_handler->getHandlers('argument') as $arg => $handler) {
|
||||
$options[$optgroup_arguments]["{{ arguments.$arg }}"] = $this->t('@argument title', ['@argument' => $handler->adminLabel()]);
|
||||
@@ -1105,7 +1105,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$values) { }
|
||||
public function preRender(&$values) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -1713,14 +1713,14 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf
|
||||
* field ID is terms, then the tokens might be {{ terms__tid }} and
|
||||
* {{ terms__name }}.
|
||||
*/
|
||||
protected function addSelfTokens(&$tokens, $item) { }
|
||||
protected function addSelfTokens(&$tokens, $item) {}
|
||||
|
||||
/**
|
||||
* Document any special tokens this field might use for itself.
|
||||
*
|
||||
* @see addSelfTokens()
|
||||
*/
|
||||
protected function documentSelfTokens(&$tokens) { }
|
||||
protected function documentSelfTokens(&$tokens) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
||||
@@ -90,7 +90,7 @@ abstract class PrerenderList extends FieldPluginBase implements MultiItemsFieldH
|
||||
'#list_type' => $this->options['type'],
|
||||
];
|
||||
}
|
||||
return drupal_render($render);
|
||||
return \Drupal::service('renderer')->render($render);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class RenderedEntity extends FieldPluginBase implements CacheableDependencyInter
|
||||
* @param array $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
*/
|
||||
|
||||
@@ -49,7 +49,6 @@ class BooleanOperator extends FilterPluginBase {
|
||||
public $accept_null = FALSE;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,8 @@ class Bundle extends InOperator {
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info_service
|
||||
* The bundle info service.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $bundle_info_service) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
@@ -166,8 +166,10 @@ class Date extends NumericFilter {
|
||||
$b = intval(strtotime($this->value['max'], 0));
|
||||
|
||||
if ($this->value['type'] == 'offset') {
|
||||
$a = '***CURRENT_TIME***' . sprintf('%+d', $a); // keep sign
|
||||
$b = '***CURRENT_TIME***' . sprintf('%+d', $b); // keep sign
|
||||
// Keep sign.
|
||||
$a = '***CURRENT_TIME***' . sprintf('%+d', $a);
|
||||
// Keep sign.
|
||||
$b = '***CURRENT_TIME***' . sprintf('%+d', $b);
|
||||
}
|
||||
// This is safe because we are manually scrubbing the values.
|
||||
// It is necessary to do it this way because $a and $b are formulas when using an offset.
|
||||
@@ -178,7 +180,8 @@ class Date extends NumericFilter {
|
||||
protected function opSimple($field) {
|
||||
$value = intval(strtotime($this->value['value'], 0));
|
||||
if (!empty($this->value['type']) && $this->value['type'] == 'offset') {
|
||||
$value = '***CURRENT_TIME***' . sprintf('%+d', $value); // keep sign
|
||||
// Keep sign.
|
||||
$value = '***CURRENT_TIME***' . sprintf('%+d', $value);
|
||||
}
|
||||
// This is safe because we are manually scrubbing the value.
|
||||
// It is necessary to do it this way because $value is a formula when using an offset.
|
||||
|
||||
@@ -131,9 +131,11 @@ abstract class FilterPluginBase extends HandlerBase implements CacheableDependen
|
||||
'required' => ['default' => FALSE],
|
||||
'remember' => ['default' => FALSE],
|
||||
'multiple' => ['default' => FALSE],
|
||||
'remember_roles' => ['default' => [
|
||||
RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID,
|
||||
]],
|
||||
'remember_roles' => [
|
||||
'default' => [
|
||||
RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -174,7 +176,9 @@ abstract class FilterPluginBase extends HandlerBase implements CacheableDependen
|
||||
/**
|
||||
* Determine if a filter can be exposed.
|
||||
*/
|
||||
public function canExpose() { return TRUE; }
|
||||
public function canExpose() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a filter can be converted into a group.
|
||||
@@ -302,18 +306,20 @@ abstract class FilterPluginBase extends HandlerBase implements CacheableDependen
|
||||
* Provide a list of options for the default operator form.
|
||||
* Should be overridden by classes that don't override operatorForm
|
||||
*/
|
||||
public function operatorOptions() { return []; }
|
||||
public function operatorOptions() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the operator form.
|
||||
*/
|
||||
protected function operatorValidate($form, FormStateInterface $form_state) { }
|
||||
protected function operatorValidate($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Perform any necessary changes to the form values prior to storage.
|
||||
* There is no need for this function to actually store the data.
|
||||
*/
|
||||
public function operatorSubmit($form, FormStateInterface $form_state) { }
|
||||
public function operatorSubmit($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Shortcut to display the value form.
|
||||
@@ -341,13 +347,13 @@ abstract class FilterPluginBase extends HandlerBase implements CacheableDependen
|
||||
/**
|
||||
* Validate the options form.
|
||||
*/
|
||||
protected function valueValidate($form, FormStateInterface $form_state) { }
|
||||
protected function valueValidate($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Perform any necessary changes to the form values prior to storage.
|
||||
* There is no need for this function to actually store the data.
|
||||
*/
|
||||
protected function valueSubmit($form, FormStateInterface $form_state) { }
|
||||
protected function valueSubmit($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Shortcut to display the exposed options form.
|
||||
@@ -989,7 +995,9 @@ abstract class FilterPluginBase extends HandlerBase implements CacheableDependen
|
||||
'#default_value' => $this->options['group_info']['remember'],
|
||||
];
|
||||
|
||||
$groups = ['All' => $this->t('- Any -')]; // The string '- Any -' will not be rendered see @theme_views_ui_build_group_filter_form
|
||||
// The string '- Any -' will not be rendered.
|
||||
// @see theme_views_ui_build_group_filter_form()
|
||||
$groups = ['All' => $this->t('- Any -')];
|
||||
|
||||
// Provide 3 options to start when we are in a new group.
|
||||
if (count($this->options['group_info']['group_items']) == 0) {
|
||||
@@ -1199,7 +1207,6 @@ abstract class FilterPluginBase extends HandlerBase implements CacheableDependen
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the HTML select element's options.
|
||||
*
|
||||
|
||||
@@ -52,6 +52,8 @@ class GroupByNumeric extends NumericFilter {
|
||||
return $this->getField(parent::adminLabel($short));
|
||||
}
|
||||
|
||||
public function canGroup() { return FALSE; }
|
||||
public function canGroup() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -88,7 +88,8 @@ class InOperator extends FilterPluginBase {
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Limit list to selected items'),
|
||||
'#description' => $this->t('If checked, the only items presented to the user will be the ones selected here.'),
|
||||
'#default_value' => !empty($this->options['expose']['reduce']), // safety
|
||||
// Safety.
|
||||
'#default_value' => !empty($this->options['expose']['reduce']),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Plugin\views\filter;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\views\Plugin\ViewsHandlerManager;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Filter to show only the latest revision of an entity.
|
||||
*
|
||||
* @ingroup views_filter_handlers
|
||||
*
|
||||
* @ViewsFilter("latest_revision")
|
||||
*/
|
||||
class LatestRevision extends FilterPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* Entity Type Manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Views Handler Plugin Manager.
|
||||
*
|
||||
* @var \Drupal\views\Plugin\ViewsHandlerManager
|
||||
*/
|
||||
protected $joinHandler;
|
||||
|
||||
/**
|
||||
* Constructs a new LatestRevision.
|
||||
*
|
||||
* @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.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* Entity Type Manager Service.
|
||||
* @param \Drupal\views\Plugin\ViewsHandlerManager $join_handler
|
||||
* Views Handler Plugin Manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ViewsHandlerManager $join_handler) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->joinHandler = $join_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration, $plugin_id, $plugin_definition,
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('plugin.manager.views.join')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function adminSummary() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function operatorForm(&$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canExpose() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
/** @var \Drupal\views\Plugin\views\query\Sql $query */
|
||||
$query = $this->query;
|
||||
$query_base_table = $this->relationship ?: $this->view->storage->get('base_table');
|
||||
|
||||
$entity_type = $this->entityTypeManager->getDefinition($this->getEntityType());
|
||||
$keys = $entity_type->getKeys();
|
||||
|
||||
$definition = [
|
||||
'table' => $query_base_table,
|
||||
'type' => 'LEFT',
|
||||
'field' => $keys['id'],
|
||||
'left_table' => $query_base_table,
|
||||
'left_field' => $keys['id'],
|
||||
'extra' => [
|
||||
['left_field' => $keys['revision'], 'field' => $keys['revision'], 'operator' => '>'],
|
||||
],
|
||||
];
|
||||
|
||||
$join = $this->joinHandler->createInstance('standard', $definition);
|
||||
|
||||
$join_table_alias = $query->addTable($query_base_table, $this->relationship, $join);
|
||||
$query->addWhere($this->options['group'], "$join_table_alias.{$keys['id']}", NULL, 'IS NULL');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -129,6 +129,9 @@ class ManyToOne extends InOperator {
|
||||
if (empty($this->value)) {
|
||||
return;
|
||||
}
|
||||
// Form API returns unchecked options in the form of option_id => 0. This
|
||||
// breaks the generated query for "is all of" filters so we remove them.
|
||||
$this->value = array_filter($this->value, 'static::arrayFilterZero');
|
||||
$this->helper->addFilter();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Drupal\views\Plugin\views\filter;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
@@ -265,7 +266,7 @@ class StringFilter extends FilterPluginBase {
|
||||
}
|
||||
|
||||
protected function opContainsWord($field) {
|
||||
$where = $this->operator == 'word' ? db_or() : db_and();
|
||||
$where = $this->operator == 'word' ? new Condition('OR') : new Condition('AND');
|
||||
|
||||
// Don't filter on empty strings.
|
||||
if (empty($this->value)) {
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Plugin\views\join;
|
||||
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
|
||||
/**
|
||||
* Implementation for the "field OR language" join.
|
||||
*
|
||||
* If the extra conditions contain either ".langcode" or ".bundle", they will be
|
||||
* grouped and joined with OR instead of AND. The entire group will then be
|
||||
* joined to the other conditions with AND.
|
||||
*
|
||||
* This is needed for configurable fields that are translatable on some bundles
|
||||
* and untranslatable on others. The correct field values to fetch in this case
|
||||
* have a langcode that matches the entity record *or* have a bundle on which
|
||||
* the field is untranslatable. Thus, the entity base table (or data table, or
|
||||
* revision data table, respectively) must join the field data table (or field
|
||||
* revision table) on a matching langcode *or* a bundle where the field is
|
||||
* untranslatable. The following example views data achieves this for a node
|
||||
* field named 'field_tags' which is translatable on an 'article' node type, but
|
||||
* not on the 'news' and 'page' node types:
|
||||
*
|
||||
* @code
|
||||
* $data['node__field_tags']['table']['join']['node_field_data'] = [
|
||||
* 'join_id' => 'field_or_language_join',
|
||||
* 'table' => 'node__field_tags',
|
||||
* 'left_field' => 'nid',
|
||||
* 'field' => 'entity_id',
|
||||
* 'extra' => [
|
||||
* [
|
||||
* 'field' => 'deleted',
|
||||
* 'value' => 0,
|
||||
* 'numeric' => TRUE,
|
||||
* ],
|
||||
* [
|
||||
* 'left_field' => 'langcode',
|
||||
* 'field' => 'langcode',
|
||||
* ],
|
||||
* [
|
||||
* 'field' => 'bundle',
|
||||
* 'value' => ['news', 'page'],
|
||||
* ],
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
*
|
||||
* The resulting join condition for this example would be the following:
|
||||
*
|
||||
* @code
|
||||
* ON node__field_tags.deleted = 0
|
||||
* AND (
|
||||
* node_field_data.langcode = node__field_tags.langcode
|
||||
* OR node__field.tags.bundle IN ['news', 'page']
|
||||
* )
|
||||
* @endcode
|
||||
*
|
||||
* @see views_field_default_views_data()
|
||||
*
|
||||
* @ingroup views_join_handlers
|
||||
*
|
||||
* @ViewsJoin("field_or_language_join")
|
||||
*/
|
||||
class FieldOrLanguageJoin extends JoinPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function joinAddExtra(&$arguments, &$condition, $table, SelectInterface $select_query, $left_table = NULL) {
|
||||
if (empty($this->extra)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($this->extra)) {
|
||||
$extras = [];
|
||||
foreach ($this->extra as $extra) {
|
||||
$extras[] = $this->buildExtra($extra, $arguments, $table, $select_query, $left_table);
|
||||
}
|
||||
|
||||
// Remove and store the langcode OR bundle join condition extra.
|
||||
$language_bundle_conditions = [];
|
||||
foreach ($extras as $key => $extra) {
|
||||
if (strpos($extra, '.langcode') !== FALSE || strpos($extra, '.bundle') !== FALSE) {
|
||||
$language_bundle_conditions[] = $extra;
|
||||
unset($extras[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($extras) > 1) {
|
||||
$condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')';
|
||||
}
|
||||
elseif ($extras) {
|
||||
$condition .= ' AND ' . array_shift($extras);
|
||||
}
|
||||
|
||||
// Tack on the langcode OR bundle join condition extra.
|
||||
if (!empty($language_bundle_conditions)) {
|
||||
$condition .= ' AND (' . implode(' OR ', $language_bundle_conditions) . ')';
|
||||
}
|
||||
}
|
||||
elseif (is_string($this->extra)) {
|
||||
$condition .= " AND ($this->extra)";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Drupal\views\Plugin\views\join;
|
||||
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\Plugin\PluginBase;
|
||||
|
||||
/**
|
||||
@@ -261,12 +262,13 @@ class JoinPluginBase extends PluginBase implements JoinPluginInterface {
|
||||
}
|
||||
|
||||
if ($this->leftTable) {
|
||||
$left = $view_query->getTableInfo($this->leftTable);
|
||||
$left_field = "$left[alias].$this->leftField";
|
||||
$left_table = $view_query->getTableInfo($this->leftTable);
|
||||
$left_field = "$left_table[alias].$this->leftField";
|
||||
}
|
||||
else {
|
||||
// This can be used if left_field is a formula or something. It should be used only *very* rarely.
|
||||
$left_field = $this->leftField;
|
||||
$left_table = NULL;
|
||||
}
|
||||
|
||||
$condition = "$left_field = $table[alias].$this->field";
|
||||
@@ -274,89 +276,123 @@ class JoinPluginBase extends PluginBase implements JoinPluginInterface {
|
||||
|
||||
// Tack on the extra.
|
||||
if (isset($this->extra)) {
|
||||
if (is_array($this->extra)) {
|
||||
$extras = [];
|
||||
foreach ($this->extra as $info) {
|
||||
// Do not require 'value' to be set; allow for field syntax instead.
|
||||
$info += [
|
||||
'value' => NULL,
|
||||
];
|
||||
// Figure out the table name. Remember, only use aliases provided
|
||||
// if at all possible.
|
||||
$join_table = '';
|
||||
if (!array_key_exists('table', $info)) {
|
||||
$join_table = $table['alias'] . '.';
|
||||
}
|
||||
elseif (isset($info['table'])) {
|
||||
// If we're aware of a table alias for this table, use the table
|
||||
// alias instead of the table name.
|
||||
if (isset($left) && $left['table'] == $info['table']) {
|
||||
$join_table = $left['alias'] . '.';
|
||||
}
|
||||
else {
|
||||
$join_table = $info['table'] . '.';
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a single-valued array of values to the single-value case,
|
||||
// and transform from IN() notation to = notation
|
||||
if (is_array($info['value']) && count($info['value']) == 1) {
|
||||
$info['value'] = array_shift($info['value']);
|
||||
}
|
||||
if (is_array($info['value'])) {
|
||||
// We use an SA-CORE-2014-005 conformant placeholder for our array
|
||||
// of values. Also, note that the 'IN' operator is implicit.
|
||||
// @see https://www.drupal.org/node/2401615.
|
||||
$operator = !empty($info['operator']) ? $info['operator'] : 'IN';
|
||||
$placeholder = ':views_join_condition_' . $select_query->nextPlaceholder() . '[]';
|
||||
$placeholder_sql = "( $placeholder )";
|
||||
}
|
||||
else {
|
||||
// With a single value, the '=' operator is implicit.
|
||||
$operator = !empty($info['operator']) ? $info['operator'] : '=';
|
||||
$placeholder = $placeholder_sql = ':views_join_condition_' . $select_query->nextPlaceholder();
|
||||
}
|
||||
// Set 'field' as join table field if available or set 'left field' as
|
||||
// join table field is not set.
|
||||
if (isset($info['field'])) {
|
||||
$join_table_field = "$join_table$info[field]";
|
||||
// Allow the value to be set either with the 'value' element or
|
||||
// with 'left_field'.
|
||||
if (isset($info['left_field'])) {
|
||||
$placeholder_sql = "$left[alias].$info[left_field]";
|
||||
}
|
||||
else {
|
||||
$arguments[$placeholder] = $info['value'];
|
||||
}
|
||||
}
|
||||
// Set 'left field' as join table field is not set.
|
||||
else {
|
||||
$join_table_field = "$left[alias].$info[left_field]";
|
||||
$arguments[$placeholder] = $info['value'];
|
||||
}
|
||||
// Render out the SQL fragment with parameters.
|
||||
$extras[] = "$join_table_field $operator $placeholder_sql";
|
||||
}
|
||||
|
||||
if ($extras) {
|
||||
if (count($extras) == 1) {
|
||||
$condition .= ' AND ' . array_shift($extras);
|
||||
}
|
||||
else {
|
||||
$condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($this->extra && is_string($this->extra)) {
|
||||
$condition .= " AND ($this->extra)";
|
||||
}
|
||||
$this->joinAddExtra($arguments, $condition, $table, $select_query, $left_table);
|
||||
}
|
||||
|
||||
$select_query->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments);
|
||||
}
|
||||
/**
|
||||
* Adds the extras to the join condition.
|
||||
*
|
||||
* @param array $arguments
|
||||
* Array of query arguments.
|
||||
* @param string $condition
|
||||
* The condition to be built.
|
||||
* @param array $table
|
||||
* The right table.
|
||||
* @param \Drupal\Core\Database\Query\SelectInterface $select_query
|
||||
* The current select query being built.
|
||||
* @param array $left_table
|
||||
* The left table.
|
||||
*/
|
||||
protected function joinAddExtra(&$arguments, &$condition, $table, SelectInterface $select_query, $left_table = NULL) {
|
||||
if (is_array($this->extra)) {
|
||||
$extras = [];
|
||||
foreach ($this->extra as $info) {
|
||||
$extras[] = $this->buildExtra($info, $arguments, $table, $select_query, $left_table);
|
||||
}
|
||||
|
||||
if ($extras) {
|
||||
if (count($extras) == 1) {
|
||||
$condition .= ' AND ' . array_shift($extras);
|
||||
}
|
||||
else {
|
||||
$condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($this->extra && is_string($this->extra)) {
|
||||
$condition .= " AND ($this->extra)";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a single extra condition.
|
||||
*
|
||||
* @param array $info
|
||||
* The extra information. See JoinPluginBase::$extra for details.
|
||||
* @param array $arguments
|
||||
* Array of query arguments.
|
||||
* @param array $table
|
||||
* The right table.
|
||||
* @param \Drupal\Core\Database\Query\SelectInterface $select_query
|
||||
* The current select query being built.
|
||||
* @param array $left
|
||||
* The left table.
|
||||
*
|
||||
* @return string
|
||||
* The extra condition
|
||||
*/
|
||||
protected function buildExtra($info, &$arguments, $table, SelectInterface $select_query, $left) {
|
||||
// Do not require 'value' to be set; allow for field syntax instead.
|
||||
$info += [
|
||||
'value' => NULL,
|
||||
];
|
||||
// Figure out the table name. Remember, only use aliases provided
|
||||
// if at all possible.
|
||||
$join_table = '';
|
||||
if (!array_key_exists('table', $info)) {
|
||||
$join_table = $table['alias'] . '.';
|
||||
}
|
||||
elseif (isset($info['table'])) {
|
||||
// If we're aware of a table alias for this table, use the table
|
||||
// alias instead of the table name.
|
||||
if (isset($left) && $left['table'] == $info['table']) {
|
||||
$join_table = $left['alias'] . '.';
|
||||
}
|
||||
else {
|
||||
$join_table = $info['table'] . '.';
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a single-valued array of values to the single-value case,
|
||||
// and transform from IN() notation to = notation
|
||||
if (is_array($info['value']) && count($info['value']) == 1) {
|
||||
$info['value'] = array_shift($info['value']);
|
||||
}
|
||||
if (is_array($info['value'])) {
|
||||
// We use an SA-CORE-2014-005 conformant placeholder for our array
|
||||
// of values. Also, note that the 'IN' operator is implicit.
|
||||
// @see https://www.drupal.org/node/2401615.
|
||||
$operator = !empty($info['operator']) ? $info['operator'] : 'IN';
|
||||
$placeholder = ':views_join_condition_' . $select_query->nextPlaceholder() . '[]';
|
||||
$placeholder_sql = "( $placeholder )";
|
||||
}
|
||||
else {
|
||||
// With a single value, the '=' operator is implicit.
|
||||
$operator = !empty($info['operator']) ? $info['operator'] : '=';
|
||||
$placeholder = $placeholder_sql = ':views_join_condition_' . $select_query->nextPlaceholder();
|
||||
}
|
||||
// Set 'field' as join table field if available or set 'left field' as
|
||||
// join table field is not set.
|
||||
if (isset($info['field'])) {
|
||||
$join_table_field = "$join_table$info[field]";
|
||||
// Allow the value to be set either with the 'value' element or
|
||||
// with 'left_field'.
|
||||
if (isset($info['left_field'])) {
|
||||
$placeholder_sql = "$left[alias].$info[left_field]";
|
||||
}
|
||||
else {
|
||||
$arguments[$placeholder] = $info['value'];
|
||||
}
|
||||
}
|
||||
// Set 'left field' as join table field is not set.
|
||||
else {
|
||||
$join_table_field = "$left[alias].$info[left_field]";
|
||||
$arguments[$placeholder] = $info['value'];
|
||||
}
|
||||
// Render out the SQL fragment with parameters.
|
||||
return "$join_table_field $operator $placeholder_sql";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -114,12 +114,12 @@ abstract class PagerPluginBase extends PluginBase {
|
||||
/**
|
||||
* Provide the default form form for validating options
|
||||
*/
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Provide the default form form for submitting options
|
||||
*/
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Return a string to display as the clickable title for the
|
||||
@@ -156,6 +156,8 @@ abstract class PagerPluginBase extends PluginBase {
|
||||
if (!empty($this->options['offset'])) {
|
||||
$this->total_items -= $this->options['offset'];
|
||||
}
|
||||
// Prevent from being negative.
|
||||
$this->total_items = max(0, $this->total_items);
|
||||
|
||||
return $this->total_items;
|
||||
}
|
||||
@@ -173,22 +175,22 @@ abstract class PagerPluginBase extends PluginBase {
|
||||
*
|
||||
* This is called during the build phase and can directly modify the query.
|
||||
*/
|
||||
public function query() { }
|
||||
public function query() {}
|
||||
|
||||
/**
|
||||
* Perform any needed actions just prior to the query executing.
|
||||
*/
|
||||
public function preExecute(&$query) { }
|
||||
public function preExecute(&$query) {}
|
||||
|
||||
/**
|
||||
* Perform any needed actions just after the query executing.
|
||||
*/
|
||||
public function postExecute(&$result) { }
|
||||
public function postExecute(&$result) {}
|
||||
|
||||
/**
|
||||
* Perform any needed actions just before rendering.
|
||||
*/
|
||||
public function preRender(&$result) { }
|
||||
public function preRender(&$result) {}
|
||||
|
||||
/**
|
||||
* Return the renderable array of the pager.
|
||||
@@ -199,7 +201,7 @@ abstract class PagerPluginBase extends PluginBase {
|
||||
* Any extra GET parameters that should be retained, such as exposed
|
||||
* input.
|
||||
*/
|
||||
public function render($input) { }
|
||||
public function render($input) {}
|
||||
|
||||
/**
|
||||
* Determine if there are more records available.
|
||||
@@ -211,11 +213,11 @@ abstract class PagerPluginBase extends PluginBase {
|
||||
&& $this->total_items > (intval($this->current_page) + 1) * $this->getItemsPerPage();
|
||||
}
|
||||
|
||||
public function exposedFormAlter(&$form, FormStateInterface $form_state) { }
|
||||
public function exposedFormAlter(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function exposedFormValidate(&$form, FormStateInterface $form_state) { }
|
||||
public function exposedFormValidate(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function exposedFormSubmit(&$form, FormStateInterface $form_state, &$exclude) { }
|
||||
public function exposedFormSubmit(&$form, FormStateInterface $form_state, &$exclude) {}
|
||||
|
||||
public function usesExposed() {
|
||||
return FALSE;
|
||||
|
||||
@@ -362,7 +362,7 @@ abstract class SqlBase extends PagerPluginBase implements CacheableDependencyInt
|
||||
public function exposedFormValidate(&$form, FormStateInterface $form_state) {
|
||||
if (!$form_state->isValueEmpty('offset') && trim($form_state->getValue('offset'))) {
|
||||
if (!is_numeric($form_state->getValue('offset')) || $form_state->getValue('offset') < 0) {
|
||||
$form_state->setErrorByName('offset', $this->t('Offset must be an number greater or equal than 0.'));
|
||||
$form_state->setErrorByName('offset', $this->t('Offset must be a number greater than or equal to 0.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ abstract class QueryPluginBase extends PluginBase implements CacheableDependency
|
||||
* @param $get_count
|
||||
* Provide a countquery if this is true, otherwise provide a normal query.
|
||||
*/
|
||||
public function query($get_count = FALSE) { }
|
||||
public function query($get_count = FALSE) {}
|
||||
|
||||
/**
|
||||
* Let modules modify the query just prior to finalizing it.
|
||||
@@ -62,7 +62,7 @@ abstract class QueryPluginBase extends PluginBase implements CacheableDependency
|
||||
* @param view $view
|
||||
* The view which is executed.
|
||||
*/
|
||||
public function alter(ViewExecutable $view) { }
|
||||
public function alter(ViewExecutable $view) {}
|
||||
|
||||
/**
|
||||
* Builds the necessary info to execute the query.
|
||||
@@ -70,7 +70,7 @@ abstract class QueryPluginBase extends PluginBase implements CacheableDependency
|
||||
* @param view $view
|
||||
* The view which is executed.
|
||||
*/
|
||||
public function build(ViewExecutable $view) { }
|
||||
public function build(ViewExecutable $view) {}
|
||||
|
||||
/**
|
||||
* Executes the query and fills the associated view object with according
|
||||
@@ -85,7 +85,7 @@ abstract class QueryPluginBase extends PluginBase implements CacheableDependency
|
||||
* @param view $view
|
||||
* The view which is executed.
|
||||
*/
|
||||
public function execute(ViewExecutable $view) { }
|
||||
public function execute(ViewExecutable $view) {}
|
||||
|
||||
/**
|
||||
* Add a signature to the query, if such a thing is feasible.
|
||||
@@ -96,18 +96,18 @@ abstract class QueryPluginBase extends PluginBase implements CacheableDependency
|
||||
* @param view $view
|
||||
* The view which is executed.
|
||||
*/
|
||||
public function addSignature(ViewExecutable $view) { }
|
||||
public function addSignature(ViewExecutable $view) {}
|
||||
|
||||
/**
|
||||
* Get aggregation info for group by queries.
|
||||
*
|
||||
* If NULL, aggregation is not allowed.
|
||||
*/
|
||||
public function getAggregationInfo() { }
|
||||
public function getAggregationInfo() {}
|
||||
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function summaryTitle() {
|
||||
return $this->t('Settings');
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Drupal\views\Plugin\views\query;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
@@ -830,7 +831,7 @@ class Sql extends QueryPluginBase {
|
||||
* @code
|
||||
* $this->query->addWhere(
|
||||
* $this->options['group'],
|
||||
* db_or()
|
||||
* (new Condition('OR'))
|
||||
* ->condition($field, $value, 'NOT IN')
|
||||
* ->condition($field, $value, 'IS NULL')
|
||||
* );
|
||||
@@ -1056,13 +1057,13 @@ class Sql extends QueryPluginBase {
|
||||
$has_arguments = FALSE;
|
||||
$has_filter = FALSE;
|
||||
|
||||
$main_group = db_and();
|
||||
$filter_group = $this->groupOperator == 'OR' ? db_or() : db_and();
|
||||
$main_group = new Condition('AND');
|
||||
$filter_group = $this->groupOperator == 'OR' ? new Condition('OR') : new Condition('AND');
|
||||
|
||||
foreach ($this->$where as $group => $info) {
|
||||
|
||||
if (!empty($info['conditions'])) {
|
||||
$sub_group = $info['type'] == 'OR' ? db_or() : db_and();
|
||||
$sub_group = $info['type'] == 'OR' ? new Condition('OR') : new Condition('AND');
|
||||
foreach ($info['conditions'] as $clause) {
|
||||
if ($clause['operator'] == 'formula') {
|
||||
$has_condition = TRUE;
|
||||
@@ -1468,7 +1469,7 @@ class Sql extends QueryPluginBase {
|
||||
|
||||
// Setup the result row objects.
|
||||
$view->result = iterator_to_array($result);
|
||||
array_walk($view->result, function(ResultRow $row, $index) {
|
||||
array_walk($view->result, function (ResultRow $row, $index) {
|
||||
$row->index = $index;
|
||||
});
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ class GroupwiseMax extends RelationshipPluginBase {
|
||||
* - subquery_order: either ASC or DESC.
|
||||
*
|
||||
* @return string
|
||||
* The subquery SQL string, ready for use in the main query.
|
||||
* The subquery SQL string, ready for use in the main query.
|
||||
*/
|
||||
protected function leftQuery($options) {
|
||||
// Either load another view, or create one on the fly.
|
||||
|
||||
@@ -37,7 +37,7 @@ class EntityReference extends Fields {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
|
||||
// Expand the description of the 'Inline field' checkboxes.
|
||||
$form['inline']['#description'] .= '<br />' . $this->t("<strong>Note:</strong> In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here." );
|
||||
$form['inline']['#description'] .= '<br />' . $this->t("<strong>Note:</strong> In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -122,13 +122,13 @@ abstract class RowPluginBase extends PluginBase {
|
||||
/**
|
||||
* Validate the options form.
|
||||
*/
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Perform any necessary changes to the form values prior to storage.
|
||||
* There is no need for this function to actually store the data.
|
||||
*/
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) { }
|
||||
public function submitOptionsForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -151,7 +151,7 @@ abstract class RowPluginBase extends PluginBase {
|
||||
* @param $result
|
||||
* The full array of results from the query.
|
||||
*/
|
||||
public function preRender($result) { }
|
||||
public function preRender($result) {}
|
||||
|
||||
/**
|
||||
* Render a row object. This usually passes through to a theme template
|
||||
|
||||
@@ -28,7 +28,9 @@ abstract class SortPluginBase extends HandlerBase implements CacheableDependency
|
||||
/**
|
||||
* Determine if a sort can be exposed.
|
||||
*/
|
||||
public function canExpose() { return TRUE; }
|
||||
public function canExpose() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to add the sort to a query.
|
||||
@@ -175,9 +177,9 @@ abstract class SortPluginBase extends HandlerBase implements CacheableDependency
|
||||
}
|
||||
}
|
||||
|
||||
protected function sortValidate(&$form, FormStateInterface $form_state) { }
|
||||
protected function sortValidate(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function sortSubmit(&$form, FormStateInterface $form_state) { }
|
||||
public function sortSubmit(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Provide a list of options for the default sort form.
|
||||
|
||||
@@ -385,7 +385,7 @@ abstract class StylePluginBase extends PluginBase {
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
* @param string $type
|
||||
* The display type, either block or page.
|
||||
* The display type, either block or page.
|
||||
*/
|
||||
public function wizardForm(&$form, FormStateInterface $form_state, $type) {
|
||||
}
|
||||
@@ -413,13 +413,15 @@ abstract class StylePluginBase extends PluginBase {
|
||||
* interfere with the sorts. If so it should build; if it returns
|
||||
* any non-TRUE value, normal sorting will NOT be added to the query.
|
||||
*/
|
||||
public function buildSort() { return TRUE; }
|
||||
public function buildSort() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the view builder to let the style build a second set of
|
||||
* sorts that will come after any other sorts in the view.
|
||||
*/
|
||||
public function buildSortPost() { }
|
||||
public function buildSortPost() {}
|
||||
|
||||
/**
|
||||
* Allow the style to do stuff before each row is rendered.
|
||||
@@ -788,7 +790,7 @@ abstract class StylePluginBase extends PluginBase {
|
||||
* @param $index
|
||||
* The index count of the row.
|
||||
* @param $field
|
||||
* The id of the field.
|
||||
* The id of the field.
|
||||
*/
|
||||
public function getFieldValue($index, $field) {
|
||||
$this->view->row_index = $index;
|
||||
|
||||
@@ -160,7 +160,7 @@ class Table extends StylePluginBase implements CacheableDependencyInterface {
|
||||
* display has listed due to access control or other changes.
|
||||
*
|
||||
* @return array
|
||||
* An array of all the sanitized columns.
|
||||
* An array of all the sanitized columns.
|
||||
*/
|
||||
public function sanitizeColumns($columns, $fields = NULL) {
|
||||
$sanitized = [];
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Drupal\views\Tests;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
@@ -5,6 +5,11 @@ namespace Drupal\views\Tests;
|
||||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Tests\Views\FieldTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\language\Entity\ContentLanguageSettings;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the Field Views data.
|
||||
@@ -13,10 +18,27 @@ use Drupal\field\Tests\Views\FieldTestBase;
|
||||
*/
|
||||
class FieldApiDataTest extends FieldTestBase {
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['language'];
|
||||
|
||||
$field_names = $this->setUpFieldStorages(1);
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $testViews = ['test_field_config_translation_filter'];
|
||||
|
||||
/**
|
||||
* The nodes used by the translation filter tests.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $translationNodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp(FALSE);
|
||||
|
||||
$field_names = $this->setUpFieldStorages(4);
|
||||
|
||||
// Attach the field to nodes only.
|
||||
$field = [
|
||||
@@ -43,6 +65,109 @@ class FieldApiDataTest extends FieldTestBase {
|
||||
];
|
||||
$nodes[] = $this->drupalCreateNode($edit);
|
||||
}
|
||||
|
||||
$bundles = [];
|
||||
$bundles[] = $bundle = NodeType::create(['type' => 'bundle1']);
|
||||
$bundle->save();
|
||||
$bundles[] = $bundle = NodeType::create(['type' => 'bundle2']);
|
||||
$bundle->save();
|
||||
|
||||
// Make the first field translatable on all bundles.
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_names[1],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $bundles[0]->id(),
|
||||
'translatable' => TRUE,
|
||||
]);
|
||||
$field->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_names[1],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $bundles[1]->id(),
|
||||
'translatable' => TRUE,
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
// Make the second field not translatable on any bundle.
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_names[2],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $bundles[0]->id(),
|
||||
'translatable' => FALSE,
|
||||
]);
|
||||
$field->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_names[2],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $bundles[1]->id(),
|
||||
'translatable' => FALSE,
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
// Make the last field translatable on some bundles.
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_names[3],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $bundles[0]->id(),
|
||||
'translatable' => TRUE,
|
||||
]);
|
||||
$field->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_names[3],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $bundles[1]->id(),
|
||||
'translatable' => FALSE,
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
// Create some example content.
|
||||
ConfigurableLanguage::create([
|
||||
'id' => 'es',
|
||||
])->save();
|
||||
ConfigurableLanguage::create([
|
||||
'id' => 'fr',
|
||||
])->save();
|
||||
|
||||
$config = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundles[0]->id());
|
||||
$config->setDefaultLangcode('es')
|
||||
->setLanguageAlterable(TRUE)
|
||||
->save();
|
||||
$config = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundles[1]->id());
|
||||
$config->setDefaultLangcode('es')
|
||||
->setLanguageAlterable(TRUE)
|
||||
->save();
|
||||
|
||||
$node = Node::create([
|
||||
'title' => 'Test title ' . $bundles[0]->id(),
|
||||
'type' => $bundles[0]->id(),
|
||||
'langcode' => 'es',
|
||||
$field_names[1] => 'field name 1: es',
|
||||
$field_names[2] => 'field name 2: es',
|
||||
$field_names[3] => 'field name 3: es',
|
||||
]);
|
||||
$node->save();
|
||||
$this->translationNodes[] = $node;
|
||||
$translation = $node->addTranslation('fr');
|
||||
$translation->{$field_names[1]}->value = 'field name 1: fr';
|
||||
$translation->{$field_names[3]}->value = 'field name 3: fr';
|
||||
$translation->title->value = $node->title->value;
|
||||
$translation->save();
|
||||
|
||||
$node = Node::create([
|
||||
'title' => 'Test title ' . $bundles[1]->id(),
|
||||
'type' => $bundles[1]->id(),
|
||||
'langcode' => 'es',
|
||||
$field_names[1] => 'field name 1: es',
|
||||
$field_names[2] => 'field name 2: es',
|
||||
$field_names[3] => 'field name 3: es',
|
||||
]);
|
||||
$node->save();
|
||||
$this->translationNodes[] = $node;
|
||||
$translation = $node->addTranslation('fr');
|
||||
$translation->{$field_names[1]}->value = 'field name 1: fr';
|
||||
$translation->title->value = $node->title->value;
|
||||
$translation->save();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,4 +262,118 @@ class FieldApiDataTest extends FieldTestBase {
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filtering entries with different translatabilty.
|
||||
*/
|
||||
public function testEntityFieldFilter() {
|
||||
$map = [
|
||||
'nid' => 'nid',
|
||||
'langcode' => 'langcode',
|
||||
];
|
||||
|
||||
$view = Views::getView('test_field_config_translation_filter');
|
||||
|
||||
// Filter by 'field name 1: es'.
|
||||
$view->setDisplay('embed_1');
|
||||
$this->executeView($view);
|
||||
$expected = [
|
||||
[
|
||||
'nid' => $this->translationNodes[0]->id(),
|
||||
'langcode' => 'es',
|
||||
],
|
||||
[
|
||||
'nid' => $this->translationNodes[1]->id(),
|
||||
'langcode' => 'es',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertIdenticalResultset($view, $expected, $map);
|
||||
$view->destroy();
|
||||
|
||||
// Filter by 'field name 1: fr'.
|
||||
$view->setDisplay('embed_2');
|
||||
$this->executeView($view);
|
||||
$expected = [
|
||||
[
|
||||
'nid' => $this->translationNodes[0]->id(),
|
||||
'langcode' => 'fr',
|
||||
],
|
||||
[
|
||||
'nid' => $this->translationNodes[1]->id(),
|
||||
'langcode' => 'fr',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertIdenticalResultset($view, $expected, $map);
|
||||
$view->destroy();
|
||||
|
||||
// Filter by 'field name 2: es'.
|
||||
$view->setDisplay('embed_3');
|
||||
$this->executeView($view);
|
||||
$expected = [
|
||||
[
|
||||
'nid' => $this->translationNodes[0]->id(),
|
||||
'langcode' => 'es',
|
||||
],
|
||||
[
|
||||
'nid' => $this->translationNodes[0]->id(),
|
||||
'langcode' => 'fr',
|
||||
],
|
||||
[
|
||||
'nid' => $this->translationNodes[1]->id(),
|
||||
'langcode' => 'es',
|
||||
],
|
||||
[
|
||||
'nid' => $this->translationNodes[1]->id(),
|
||||
'langcode' => 'fr',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertIdenticalResultset($view, $expected, $map);
|
||||
$view->destroy();
|
||||
|
||||
// Filter by 'field name 2: fr', which doesn't exist.
|
||||
$view->setDisplay('embed_4');
|
||||
$this->executeView($view);
|
||||
$expected = [];
|
||||
|
||||
$this->assertIdenticalResultset($view, $expected, $map);
|
||||
$view->destroy();
|
||||
|
||||
// Filter by 'field name 3: es'.
|
||||
$view->setDisplay('embed_5');
|
||||
$this->executeView($view);
|
||||
$expected = [
|
||||
[
|
||||
'nid' => $this->translationNodes[0]->id(),
|
||||
'langcode' => 'es',
|
||||
],
|
||||
[
|
||||
'nid' => $this->translationNodes[1]->id(),
|
||||
'langcode' => 'es',
|
||||
],
|
||||
// Why is this one returned?
|
||||
[
|
||||
'nid' => $this->translationNodes[1]->id(),
|
||||
'langcode' => 'fr',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertIdenticalResultset($view, $expected, $map);
|
||||
$view->destroy();
|
||||
|
||||
// Filter by 'field name 3: fr'.
|
||||
$view->setDisplay('embed_6');
|
||||
$this->executeView($view);
|
||||
$expected = [
|
||||
[
|
||||
'nid' => $this->translationNodes[0]->id(),
|
||||
'langcode' => 'fr',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertIdenticalResultset($view, $expected, $map);
|
||||
$view->destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Tests\Handler;
|
||||
|
||||
@trigger_error('\Drupal\views\Tests\Handler\HandlerTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\views\Functional\ViewTestBase', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
|
||||
@@ -45,10 +45,12 @@ class DisplayFeedTest extends PluginTestBase {
|
||||
$node_title = 'This "cool" & "neat" article\'s title';
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => $node_title,
|
||||
'body' => [0 => [
|
||||
'value' => 'A paragraph',
|
||||
'format' => filter_default_format(),
|
||||
]],
|
||||
'body' => [
|
||||
0 => [
|
||||
'value' => 'A paragraph',
|
||||
'format' => filter_default_format(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Test the site name setting.
|
||||
@@ -103,10 +105,12 @@ class DisplayFeedTest extends PluginTestBase {
|
||||
$node_title = 'This "cool" & "neat" article\'s title';
|
||||
$this->drupalCreateNode([
|
||||
'title' => $node_title,
|
||||
'body' => [0 => [
|
||||
'value' => 'A paragraph',
|
||||
'format' => filter_default_format(),
|
||||
]],
|
||||
'body' => [
|
||||
0 => [
|
||||
'value' => 'A paragraph',
|
||||
'format' => filter_default_format(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalGet('test-feed-display-fields.xml');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Tests\Plugin;
|
||||
|
||||
@trigger_error('\Drupal\views\Tests\Plugin\PluginTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\views\Functional\ViewTestBase', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
|
||||
@@ -126,6 +126,8 @@ abstract class ViewKernelTestBase extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Returns the schema definition.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function schemaDefinition() {
|
||||
return ViewTestData::schemaDefinition();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Tests;
|
||||
|
||||
@trigger_error('\Drupal\views\Tests\ViewTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\views\Functional\ViewTestBase', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
@@ -95,7 +96,7 @@ abstract class ViewTestBase extends WebTestBase {
|
||||
*
|
||||
* @param string $id
|
||||
* The HTML ID of the button
|
||||
* @param string $label
|
||||
* @param string $expected_label
|
||||
* The expected label for the button.
|
||||
* @param string $message
|
||||
* (optional) A custom message to display with the assertion. If no custom
|
||||
@@ -131,6 +132,8 @@ abstract class ViewTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Returns the schema definition.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function schemaDefinition() {
|
||||
return ViewTestData::schemaDefinition();
|
||||
|
||||
@@ -58,6 +58,8 @@ class ViewTestData {
|
||||
|
||||
/**
|
||||
* Returns the schema definition.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function schemaDefinition() {
|
||||
$schema['views_test_data'] = [
|
||||
@@ -80,7 +82,8 @@ class ViewTestData {
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0],
|
||||
'default' => 0,
|
||||
],
|
||||
'job' => [
|
||||
'description' => "The person's job",
|
||||
'type' => 'varchar',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\views\Tests\Wizard;
|
||||
|
||||
@trigger_error('\Drupal\views\Tests\Wizard\WizardTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\views\Functional\Wizard\WizardTestBase', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace Drupal\views;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\views\Plugin\views\display\DisplayRouterInterface;
|
||||
@@ -17,9 +17,14 @@ use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
*
|
||||
* An object to contain all of the data to generate a view, plus the member
|
||||
* functions to build the view query, execute the query and render the output.
|
||||
*
|
||||
* This class does not implement the Serializable interface since problems
|
||||
* occurred when using the serialize method.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2849674
|
||||
* @see https://bugs.php.net/bug.php?id=66052
|
||||
*/
|
||||
class ViewExecutable implements \Serializable {
|
||||
use DependencySerializationTrait;
|
||||
class ViewExecutable {
|
||||
|
||||
/**
|
||||
* The config entity in which the view is stored.
|
||||
@@ -434,6 +439,13 @@ class ViewExecutable implements \Serializable {
|
||||
*/
|
||||
protected $baseEntityType;
|
||||
|
||||
/**
|
||||
* Holds all necessary data for proper unserialization.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $serializationData;
|
||||
|
||||
/**
|
||||
* Constructs a new ViewExecutable object.
|
||||
*
|
||||
@@ -788,7 +800,7 @@ class ViewExecutable implements \Serializable {
|
||||
|
||||
// Ensure the requested display exists.
|
||||
if (!$this->displayHandlers->has($display_id)) {
|
||||
debug(format_string('setDisplay() called with invalid display ID "@display".', ['@display' => $display_id]));
|
||||
trigger_error(new FormattableMarkup('setDisplay() called with invalid display ID "@display".', ['@display' => $display_id]), E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1327,8 +1339,8 @@ class ViewExecutable implements \Serializable {
|
||||
* @todo Some filter needs this function, even it is internal.
|
||||
*
|
||||
* @param string $key
|
||||
* The type of handlers (filter etc.) which should be iterated over to
|
||||
* build the relationship and query information.
|
||||
* The type of handlers (filter etc.) which should be iterated over to build
|
||||
* the relationship and query information.
|
||||
*/
|
||||
public function _build($key) {
|
||||
$handlers = &$this->$key;
|
||||
@@ -1746,7 +1758,7 @@ class ViewExecutable implements \Serializable {
|
||||
|
||||
// We can't use choose_display() here because that function
|
||||
// calls this one.
|
||||
$displays = (array)$displays;
|
||||
$displays = (array) $displays;
|
||||
foreach ($displays as $display_id) {
|
||||
if ($this->displayHandlers->has($display_id)) {
|
||||
if (($display = $this->displayHandlers->get($display_id)) && $display->access($account)) {
|
||||
@@ -2466,52 +2478,68 @@ class ViewExecutable implements \Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Magic method implementation to serialize the view executable.
|
||||
*
|
||||
* @return array
|
||||
* The names of all variables that should be serialized.
|
||||
*/
|
||||
public function serialize() {
|
||||
return serialize([
|
||||
// Only serialize the storage entity ID.
|
||||
$this->storage->id(),
|
||||
$this->current_display,
|
||||
$this->args,
|
||||
$this->current_page,
|
||||
$this->exposed_input,
|
||||
$this->exposed_raw_input,
|
||||
$this->exposed_data,
|
||||
$this->dom_id,
|
||||
$this->executed,
|
||||
]);
|
||||
public function __sleep() {
|
||||
// Limit to only the required data which is needed to properly restore the
|
||||
// state during unserialization.
|
||||
$this->serializationData = [
|
||||
'storage' => $this->storage->id(),
|
||||
'views_data' => $this->viewsData->_serviceId,
|
||||
'route_provider' => $this->routeProvider->_serviceId,
|
||||
'current_display' => $this->current_display,
|
||||
'args' => $this->args,
|
||||
'current_page' => $this->current_page,
|
||||
'exposed_input' => $this->exposed_input,
|
||||
'exposed_raw_input' => $this->exposed_raw_input,
|
||||
'exposed_data' => $this->exposed_data,
|
||||
'dom_id' => $this->dom_id,
|
||||
'executed' => $this->executed,
|
||||
];
|
||||
return ['serializationData'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Magic method implementation to unserialize the view executable.
|
||||
*/
|
||||
public function unserialize($serialized) {
|
||||
list($storage, $current_display, $args, $current_page, $exposed_input, $exposed_raw_input, $exposed_data, $dom_id, $executed) = unserialize($serialized);
|
||||
|
||||
// There are cases, like in testing, where we don't have a container
|
||||
public function __wakeup() {
|
||||
// There are cases, like in testing where we don't have a container
|
||||
// available.
|
||||
if (\Drupal::hasContainer()) {
|
||||
$this->setRequest(\Drupal::request());
|
||||
if (\Drupal::hasContainer() && !empty($this->serializationData)) {
|
||||
// Load and reference the storage.
|
||||
$this->storage = \Drupal::entityTypeManager()->getStorage('view')
|
||||
->load($this->serializationData['storage']);
|
||||
$this->storage->set('executable', $this);
|
||||
|
||||
// Attach all necessary services.
|
||||
$this->user = \Drupal::currentUser();
|
||||
$this->viewsData = \Drupal::service($this->serializationData['views_data']);
|
||||
$this->routeProvider = \Drupal::service($this->serializationData['route_provider']);
|
||||
|
||||
$this->storage = \Drupal::entityManager()->getStorage('view')->load($storage);
|
||||
|
||||
$this->setDisplay($current_display);
|
||||
$this->setArguments($args);
|
||||
$this->setCurrentPage($current_page);
|
||||
$this->setExposedInput($exposed_input);
|
||||
$this->exposed_data = $exposed_data;
|
||||
$this->exposed_raw_input = $exposed_raw_input;
|
||||
$this->dom_id = $dom_id;
|
||||
// Restore the state of this executable.
|
||||
if ($request = \Drupal::request()) {
|
||||
$this->setRequest($request);
|
||||
}
|
||||
$this->setDisplay($this->serializationData['current_display']);
|
||||
$this->setArguments($this->serializationData['args']);
|
||||
$this->setCurrentPage($this->serializationData['current_page']);
|
||||
$this->setExposedInput($this->serializationData['exposed_input']);
|
||||
$this->exposed_data = $this->serializationData['exposed_data'];
|
||||
$this->exposed_raw_input = $this->serializationData['exposed_raw_input'];
|
||||
$this->dom_id = $this->serializationData['dom_id'];
|
||||
|
||||
$this->initHandlers();
|
||||
|
||||
// If the display was previously executed, execute it now.
|
||||
if ($executed) {
|
||||
if ($this->serializationData['executed']) {
|
||||
$this->execute($this->current_display);
|
||||
}
|
||||
}
|
||||
// Unset serializationData since it serves no further purpose.
|
||||
unset($this->serializationData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -283,8 +283,8 @@ class Views {
|
||||
* Filters the views on status. Can either be 'all' (default), 'enabled' or
|
||||
* 'disabled'
|
||||
* @param mixed $exclude_view
|
||||
* view or current display to exclude
|
||||
* either a
|
||||
* View or current display to exclude.
|
||||
* Either a:
|
||||
* - views object (containing $exclude_view->storage->name and $exclude_view->current_display)
|
||||
* - views name as string: e.g. my_view
|
||||
* - views name and display id (separated by ':'): e.g. my_view:default
|
||||
@@ -512,7 +512,7 @@ class Views {
|
||||
throw new \Exception('Invalid plugin type used. Valid types are "plugin" or "handler".');
|
||||
}
|
||||
|
||||
return array_keys(array_filter(static::$plugins, function($plugin_type) use ($type) {
|
||||
return array_keys(array_filter(static::$plugins, function ($plugin_type) use ($type) {
|
||||
return $plugin_type == $type;
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user