Issue #2413753 by alexpott, olli: Views recalculating the dependencies for non overridden handlers and plugins multiple times

8.0.x
catch 2015-02-19 16:13:12 +00:00
parent 3f7f953ff8
commit 161d80f94a
4 changed files with 229 additions and 19 deletions

View File

@ -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;

View File

@ -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}
*/

View File

@ -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());
}
}
}

View File

@ -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