From 161d80f94a3b419d65e40b9f685d199b5ef76079 Mon Sep 17 00:00:00 2001 From: catch Date: Thu, 19 Feb 2015 16:13:12 +0000 Subject: [PATCH] Issue #2413753 by alexpott, olli: Views recalculating the dependencies for non overridden handlers and plugins multiple times --- core/modules/views/src/Entity/View.php | 18 +-- .../views/display/DisplayPluginBase.php | 64 ++++++++- .../Entity/ViewEntityDependenciesTest.php | 45 ++++++- .../views.view.test_argument_dependency.yml | 121 ++++++++++++++++++ 4 files changed, 229 insertions(+), 19 deletions(-) diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php index ba3d0eeb8c4..05bc393d70f 100644 --- a/core/modules/views/src/Entity/View.php +++ b/core/modules/views/src/Entity/View.php @@ -267,26 +267,10 @@ class View extends ConfigEntityBase implements ViewEntityInterface { $executable = $this->getExecutable(); $executable->initDisplay(); $executable->initStyle(); - $handler_types = array_keys(Views::getHandlerTypes()); foreach ($executable->displayHandlers as $display) { - // Add dependency for the display itself. + // Calculate the dependencies each display has. $this->calculatePluginDependencies($display); - - // Collect all dependencies of all handlers. - foreach ($handler_types as $handler_type) { - foreach ($display->getHandlers($handler_type) as $handler) { - $this->calculatePluginDependencies($handler); - } - } - - // Collect all dependencies of plugins. - foreach (Views::getPluginTypes('plugin') as $plugin_type) { - if (!$plugin = $display->getPlugin($plugin_type)) { - continue; - } - $this->calculatePluginDependencies($plugin); - } } return $this->dependencies; diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 93bd846eb0c..267a4237e12 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -7,11 +7,13 @@ namespace Drupal\views\Plugin\views\display; +use Drupal\Component\Plugin\DependentPluginInterface; use Drupal\Component\Utility\String; use Drupal\Component\Utility\Unicode; use Drupal\Core\Cache\Cache; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Plugin\PluginDependencyTrait; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Theme\Registry; use Drupal\Core\Url; @@ -27,7 +29,8 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException as Dependen /** * Base class for views display plugins. */ -abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInterface { +abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInterface, DependentPluginInterface { + use PluginDependencyTrait; /** * The top object of a view. @@ -890,6 +893,65 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte return $this->handlers[$type]; } + /** + * Gets all the handlers used by the display. + * + * @param bool $only_overrides + * Whether to include only overridden handlers. + * + * @return \Drupal\views\Plugin\views\ViewsHandlerInterface[] + */ + protected function getAllHandlers($only_overrides = FALSE) { + $handler_types = Views::getHandlerTypes(); + $handlers = []; + // Collect all dependencies of all handlers. + foreach ($handler_types as $handler_type => $handler_type_info) { + if ($only_overrides && $this->isDefaulted($handler_type_info['plural'])) { + continue; + } + $handlers = array_merge($handlers, array_values($this->getHandlers($handler_type))); + } + return $handlers; + } + + /** + * Gets all the plugins used by the display. + * + * @param bool $only_overrides + * Whether to include only overridden plugins. + * + * @return \Drupal\views\Plugin\views\ViewsPluginInterface[] + */ + protected function getAllPlugins($only_overrides = FALSE) { + $plugins = []; + // Collect all dependencies of plugins. + foreach (Views::getPluginTypes('plugin') as $plugin_type) { + $plugin = $this->getPlugin($plugin_type); + if (!$plugin) { + continue; + } + if ($only_overrides && $this->isDefaulted($plugin_type)) { + continue; + } + $plugins[] = $plugin; + } + return $plugins; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $this->addDependencies(parent::calculateDependencies()); + // Collect all the dependencies of handlers and plugins. Only calculate + // their dependencies if they are configured by this display. + $plugins = array_merge($this->getAllHandlers(TRUE), $this->getAllPlugins(TRUE)); + array_walk($plugins, array($this, 'calculatePluginDependencies')); + + return $this->dependencies; + } + + /** * {@inheritdoc} */ diff --git a/core/modules/views/src/Tests/Entity/ViewEntityDependenciesTest.php b/core/modules/views/src/Tests/Entity/ViewEntityDependenciesTest.php index cc750fa7ba7..44930ed552f 100644 --- a/core/modules/views/src/Tests/Entity/ViewEntityDependenciesTest.php +++ b/core/modules/views/src/Tests/Entity/ViewEntityDependenciesTest.php @@ -8,6 +8,7 @@ namespace Drupal\views\Tests\Entity; use Drupal\Component\Utility\Unicode; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\views\Tests\ViewUnitTestBase; use Drupal\views\Views; @@ -74,6 +75,12 @@ class ViewEntityDependenciesTest extends ViewUnitTestBase { 'comment_type' => $comment_type->id(), ), ))->save(); + entity_create('field_config', array( + 'field_storage' => FieldStorageConfig::loadByName('node', 'body'), + 'bundle' => $content_type->id(), + 'label' => $this->randomMachineName() . '_body', + 'settings' => array('display_summary' => TRUE), + ))->save(); // Force a flush of the in-memory storage. $this->container->get('views.views_data')->clear(); @@ -107,7 +114,8 @@ class ViewEntityDependenciesTest extends ViewUnitTestBase { $expected['test_argument_dependency'] = [ 'config' => [ - 'core.entity_view_mode.node.teaser' + 'core.entity_view_mode.node.teaser', + 'field.storage.node.body' ], 'content' => [ 'ArgumentDefaultTest', @@ -117,6 +125,7 @@ class ViewEntityDependenciesTest extends ViewUnitTestBase { 'node', // The argument handler is provided by the search module. 'search', + 'text', 'user' ], ]; @@ -129,6 +138,40 @@ class ViewEntityDependenciesTest extends ViewUnitTestBase { $config = $this->config('views.view.' . $view_id); \Drupal::service('config.storage.staging')->write($view_id, $config->get()); } + + // Ensure that dependencies are calculated on the display level. + $expected_display['default'] = [ + 'config' => [ + 'core.entity_view_mode.node.teaser', + ], + 'content' => [ + 'ArgumentDefaultTest', + 'ArgumentValidatorTest' + ], + 'module' => [ + 'node', + 'search', + 'user', + 'views' + ], + ]; + $expected_display['page'] = [ + 'config' => [ + 'field.storage.node.body' + ], + 'module' => [ + 'node', + 'text', + 'views' + ], + ]; + + $view = Views::getView('test_argument_dependency'); + $view->initDisplay(); + foreach ($view->displayHandlers as $display) { + // Calculate the dependencies each display has. + $this->assertEqual($expected_display[$display->getPluginId()], $display->calculateDependencies()); + } } } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml index 8ed98fbd0bd..9b8ac579131 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml @@ -3,12 +3,14 @@ status: true dependencies: config: - core.entity_view_mode.node.teaser + - field.storage.node.body content: - ArgumentDefaultTest - ArgumentValidatorTest module: - node - search + - text - user id: test_argument_dependency label: test_argument_dependency @@ -216,3 +218,122 @@ display: entity_field: uid plugin_id: numeric display_extenders: { } + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: test_argument_dependency + style: + type: default + options: { } + defaults: + style: false + row: false + fields: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + fields: + title: + id: title + table: node_field_data + field: title + entity_type: node + entity_field: title + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + link_to_node: true + plugin_id: node + relationship: none + group_type: group + admin_label: '' + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + body: + id: body + table: node__body + field: body + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: text_default + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + plugin_id: field