core/lib/Drupal/Core/Entity/Entity.php | 7 ++ core/lib/Drupal/Core/Entity/EntityInterface.php | 11 ++ .../aggregator/src/Plugin/views/row/Rss.php | 30 +----- core/modules/comment/src/Plugin/views/row/Rss.php | 41 ++------ .../modules/field/src/Plugin/views/field/Field.php | 10 +- core/modules/node/src/Plugin/views/row/Rss.php | 58 +++-------- core/modules/node/src/Tests/NodeTestBase.php | 3 + .../modules/node/src/Tests/Views/FrontPageTest.php | 14 +++ .../node/src/Tests/Views/NodeLanguageTest.php | 4 +- core/modules/node/src/Tests/Views/NodeTestBase.php | 8 +- .../src/Plugin/views/filter/TaxonomyIndexTid.php | 71 ++++++++++++- .../src/Plugin/views/relationship/NodeTermData.php | 66 +++++++++++- .../Tests/Views/RelationshipNodeTermDataTest.php | 15 ++- .../src/Tests/Views/TaxonomyIndexTidUiTest.php | 53 +++++++--- .../views.view.test_filter_taxonomy_index_tid.yml | 2 +- .../views.view.test_taxonomy_node_term_data.yml | 6 +- core/modules/user/src/Plugin/views/access/Role.php | 54 ++++++++++ .../user/src/Tests/Views/AccessRoleTest.php | 13 +++ core/modules/views/src/Entity/View.php | 3 +- core/modules/views/src/Plugin/views/area/View.php | 15 +++ .../src/Plugin/views/argument_validator/Entity.php | 19 ++++ .../views/src/Plugin/views/display/Page.php | 67 +++++++++++- .../views/src/Plugin/views/filter/Bundle.php | 57 ++++++++++ .../views/src/Plugin/views/row/EntityRow.php | 16 +++ .../views/src/Plugin/views/row/RssPluginBase.php | 116 +++++++++++++++++++++ .../src/Tests/Entity/FilterEntityBundleTest.php | 18 +++- .../views/src/Tests/Handler/AreaViewTest.php | 5 +- .../views/src/Tests/Plugin/DisplayPageTest.php | 26 ++++- core/modules/views/src/Tests/ViewTestData.php | 9 +- core/modules/views/src/Tests/ViewUnitTestBase.php | 7 +- .../views.view.test_entity_type_filter.yml | 1 - .../views.view.test_page_display_menu.yml | 12 +-- .../test_views/views.view.test_tag_cache.yml | 41 -------- core/modules/views_ui/src/ViewUI.php | 6 ++ .../tests/src/Unit/ViewListBuilderTest.php | 3 +- .../views_ui/tests/src/Unit/ViewUIObjectTest.php | 2 +- 36 files changed, 695 insertions(+), 194 deletions(-) diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index d9b7b4b..a867053 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -553,6 +553,13 @@ public function __sleep() { /** * {@inheritdoc} */ + public function getConfigDependencyKey() { + return $this->getEntityType()->getConfigDependencyKey(); + } + + /** + * {@inheritdoc} + */ public function getConfigDependencyName() { return $this->getEntityTypeId() . ':' . $this->bundle() . ':' . $this->uuid(); } diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 674078d..d8e8e3e 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -405,6 +405,17 @@ public function getTypedData(); public function getCacheTags(); /** + * Gets the key that is used to store configuration dependencies. + * + * @return string + * The key to be used in configuration dependencies when storing + * dependencies on entities of this type. + * + * @see \Drupal\Core\Entity\EntityTypeInterface::getConfigDependencyKey() + */ + public function getConfigDependencyKey(); + + /** * Gets the configuration dependency name. * * Configuration entities can depend on content and configuration entities. diff --git a/core/modules/aggregator/src/Plugin/views/row/Rss.php b/core/modules/aggregator/src/Plugin/views/row/Rss.php index 2b6dba1..72410e5 100644 --- a/core/modules/aggregator/src/Plugin/views/row/Rss.php +++ b/core/modules/aggregator/src/Plugin/views/row/Rss.php @@ -7,8 +7,7 @@ namespace Drupal\aggregator\Plugin\views\row; -use Drupal\Core\Form\FormStateInterface; -use Drupal\views\Plugin\views\row\RowPluginBase; +use Drupal\views\Plugin\views\row\RssPluginBase; /** * Defines a row plugin which loads an aggregator item and renders as RSS. @@ -22,7 +21,7 @@ * display_types = {"feed"} * ) */ -class Rss extends RowPluginBase { +class Rss extends RssPluginBase { /** * The table the aggregator item is using for storage. @@ -41,30 +40,7 @@ class Rss extends RowPluginBase { /** * {@inheritdoc} */ - protected function defineOptions() { - $options = parent::defineOptions(); - - $options['view_mode'] = array('default' => 'default'); - - return $options; - } - - /** - * {@inheritdoc} - */ - public function buildOptionsForm(&$form, FormStateInterface $form_state) { - $form['view_mode'] = array( - '#type' => 'select', - '#title' => $this->t('Display type'), - '#options' => array( - 'fulltext' => $this->t('Full text'), - 'teaser' => $this->t('Title plus teaser'), - 'title' => $this->t('Title only'), - 'default' => $this->t('Use default RSS settings'), - ), - '#default_value' => $this->options['view_mode'], - ); - } + protected $entityTypeId = 'aggregator_item'; /** * {@inheritdoc} diff --git a/core/modules/comment/src/Plugin/views/row/Rss.php b/core/modules/comment/src/Plugin/views/row/Rss.php index 1dc6c8b..bbbce01 100644 --- a/core/modules/comment/src/Plugin/views/row/Rss.php +++ b/core/modules/comment/src/Plugin/views/row/Rss.php @@ -7,8 +7,7 @@ namespace Drupal\comment\Plugin\views\row; -use Drupal\Core\Form\FormStateInterface; -use Drupal\views\Plugin\views\row\RowPluginBase; +use Drupal\views\Plugin\views\row\RssPluginBase; /** * Plugin which formats the comments as RSS items. @@ -23,29 +22,15 @@ * display_types = {"feed"} * ) */ -class Rss extends RowPluginBase { +class Rss extends RssPluginBase { var $base_table = 'comment'; var $base_field = 'cid'; - protected function defineOptions() { - $options = parent::defineOptions(); - - $options['view_mode'] = array('default' => 'default'); - - return $options; - } - - public function buildOptionsForm(&$form, FormStateInterface $form_state) { - parent::buildOptionsForm($form, $form_state); - - $form['view_mode'] = array( - '#type' => 'select', - '#title' => $this->t('Display type'), - '#options' => $this->options_form_summary_options(), - '#default_value' => $this->options['view_mode'], - ); - } + /** + * {@inheritdoc} + */ + protected $entityTypeId = 'comment'; public function preRender($result) { $cids = array(); @@ -62,18 +47,10 @@ public function preRender($result) { } /** - * Return the main options, which are shown in the summary title - * - * @see views_plugin_row_node_rss::options_form_summary_options() - * @todo: Maybe provide a views_plugin_row_rss_entity and reuse this method - * in views_plugin_row_comment|node_rss.inc + * {@inheritdoc} */ - function options_form_summary_options() { - $view_modes = \Drupal::entityManager()->getViewModes('node'); - $options = array(); - foreach ($view_modes as $mode => $settings) { - $options[$mode] = $settings['label']; - } + public function buildOptionsForm_summary_options() { + $options = parent::buildOptionsForm_summary_options(); $options['title'] = $this->t('Title only'); $options['default'] = $this->t('Use site default RSS settings'); return $options; diff --git a/core/modules/field/src/Plugin/views/field/Field.php b/core/modules/field/src/Plugin/views/field/Field.php index 106ce87..7fdc28b 100644 --- a/core/modules/field/src/Plugin/views/field/Field.php +++ b/core/modules/field/src/Plugin/views/field/Field.php @@ -942,8 +942,16 @@ function field_langcode(EntityInterface $entity) { * {@inheritdoc} */ public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + // Add the module providing the configured field storage as a dependency. - return array('config' => array($this->getFieldStorageConfig()->getConfigDependencyName())); + $dependencies['config'][] = $this->getFieldStorageConfig()->getConfigDependencyName(); + // Add the module providing the formatter. + if ($this->options['type']) { + $dependencies['module'][] = $this->formatterPluginManager->getDefinition($this->options['type'])['provider']; + } + + return $dependencies; } /** diff --git a/core/modules/node/src/Plugin/views/row/Rss.php b/core/modules/node/src/Plugin/views/row/Rss.php index 4ee566e..0b1acac 100644 --- a/core/modules/node/src/Plugin/views/row/Rss.php +++ b/core/modules/node/src/Plugin/views/row/Rss.php @@ -9,8 +9,8 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\String; -use Drupal\Core\Form\FormStateInterface; -use Drupal\views\Plugin\views\row\RowPluginBase; +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\views\Plugin\views\row\RssPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\node\NodeStorageInterface; @@ -28,7 +28,7 @@ * display_types = {"feed"} * ) */ -class Rss extends RowPluginBase { +class Rss extends RssPluginBase { // Basic properties that let the row style follow relationships. var $base_table = 'node'; @@ -39,6 +39,11 @@ class Rss extends RowPluginBase { var $nodes = array(); /** + * {@inheritdoc} + */ + protected $entityTypeId = 'node'; + + /** * The node storage * * @var \Drupal\node\NodeStorageInterface @@ -54,54 +59,19 @@ class Rss extends RowPluginBase { * The plugin_id for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. - * @param NodeStorageInterface $node_storage - * The node storage. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, NodeStorageInterface $node_storage) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->nodeStorage = $node_storage; + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager); + $this->nodeStorage = $entity_manager->getStorage('node'); } /** * {@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')->getStorage('node') - ); - } - - protected function defineOptions() { - $options = parent::defineOptions(); - - $options['view_mode'] = array('default' => 'default'); - - return $options; - } - - public function buildOptionsForm(&$form, FormStateInterface $form_state) { - parent::buildOptionsForm($form, $form_state); - - $form['view_mode'] = array( - '#type' => 'select', - '#title' => $this->t('Display type'), - '#options' => $this->buildOptionsForm_summary_options(), - '#default_value' => $this->options['view_mode'], - ); - } - - /** - * Return the main options, which are shown in the summary title. - */ public function buildOptionsForm_summary_options() { - $view_modes = \Drupal::entityManager()->getViewModes('node'); - $options = array(); - foreach ($view_modes as $mode => $settings) { - $options[$mode] = $settings['label']; - } + $options = parent::buildOptionsForm_summary_options(); $options['title'] = $this->t('Title only'); $options['default'] = $this->t('Use site default RSS settings'); return $options; diff --git a/core/modules/node/src/Tests/NodeTestBase.php b/core/modules/node/src/Tests/NodeTestBase.php index 764d0a8..7d38bb5 100644 --- a/core/modules/node/src/Tests/NodeTestBase.php +++ b/core/modules/node/src/Tests/NodeTestBase.php @@ -29,6 +29,9 @@ */ protected $accessHandler; + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); diff --git a/core/modules/node/src/Tests/Views/FrontPageTest.php b/core/modules/node/src/Tests/Views/FrontPageTest.php index 0760231..ac93dd3 100644 --- a/core/modules/node/src/Tests/Views/FrontPageTest.php +++ b/core/modules/node/src/Tests/Views/FrontPageTest.php @@ -49,6 +49,20 @@ public function testFrontPage() { ->save(); $view = Views::getView('frontpage'); + + // Tests \Drupal\node\Plugin\views\row\RssPluginBase::calculateDependencies(). + $expected = [ + 'config' => [ + 'core.entity_view_mode.node.rss', + 'core.entity_view_mode.node.teaser', + ], + 'module' => [ + 'node', + 'user', + ], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); + $view->setDisplay('page_1'); $this->executeView($view); $view->preview(); diff --git a/core/modules/node/src/Tests/Views/NodeLanguageTest.php b/core/modules/node/src/Tests/Views/NodeLanguageTest.php index b4d9891..edf5ae8 100644 --- a/core/modules/node/src/Tests/Views/NodeLanguageTest.php +++ b/core/modules/node/src/Tests/Views/NodeLanguageTest.php @@ -10,6 +10,7 @@ use Drupal\field\Entity\FieldStorageConfig; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\views\Plugin\views\PluginBase; +use Drupal\views\Tests\ViewTestData; /** * Tests node language fields, filters, and sorting. @@ -41,11 +42,12 @@ class NodeLanguageTest extends NodeTestBase { * {@inheritdoc} */ protected function setUp() { - parent::setUp(); + parent::setUp(FALSE); // Create Page content type. if ($this->profile != 'standard') { $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); + ViewTestData::createTestViews(get_class($this), array('node_test_views')); } // Add two new languages. diff --git a/core/modules/node/src/Tests/Views/NodeTestBase.php b/core/modules/node/src/Tests/Views/NodeTestBase.php index 1c634bb..765f257 100644 --- a/core/modules/node/src/Tests/Views/NodeTestBase.php +++ b/core/modules/node/src/Tests/Views/NodeTestBase.php @@ -22,10 +22,12 @@ */ public static $modules = array('node_test_views'); - protected function setUp() { - parent::setUp(); + protected function setUp($import_test_views = TRUE) { + parent::setUp($import_test_views); - ViewTestData::createTestViews(get_class($this), array('node_test_views')); + if ($import_test_views) { + ViewTestData::createTestViews(get_class($this), array('node_test_views')); + } } } diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php index cf57b6f..5d7252a 100644 --- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php +++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php @@ -2,18 +2,22 @@ /** * @file - * Definition of views_handler_filter_term_node_tid. + * Contains \Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid. */ namespace Drupal\taxonomy\Plugin\views\filter; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\TermStorageInterface; +use Drupal\taxonomy\VocabularyStorageInterface; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\Plugin\views\filter\ManyToOne; use Drupal\Component\Utility\String; use Drupal\Component\Utility\Tags; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Filter by term id. @@ -28,6 +32,54 @@ class TaxonomyIndexTid extends ManyToOne { var $validated_exposed_input = NULL; /** + * The vocabulary storage. + * + * @var \Drupal\taxonomy\VocabularyStorageInterface + */ + protected $vocabularyStorage; + + /** + * The term storage. + * + * @var \Drupal\taxonomy\TermStorageInterface + */ + protected $termStorage; + + /** + * Constructs a TaxonomyIndexTid 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\taxonomy\VocabularyStorageInterface $vocabulary_storage + * The vocabulary storage. + * @param \Drupal\taxonomy\TermStorageInterface $term_storage + * The term storage. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, VocabularyStorageInterface $vocabulary_storage, TermStorageInterface $term_storage) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->is_handler = TRUE; + $this->vocabularyStorage = $vocabulary_storage; + $this->termStorage = $term_storage; + } + + /** + * {@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')->getStorage('taxonomy_vocabulary'), + $container->get('entity.manager')->getStorage('taxonomy_term') + ); + } + + /** * Overrides \Drupal\views\Plugin\views\filter\ManyToOne::init(). */ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { @@ -374,4 +426,21 @@ public function getCacheContexts() { return $contexts; } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + $vocabulary = $this->vocabularyStorage->load($this->options['vid']); + $dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName(); + + foreach ($this->options['value'] as $tid) { + $term = $this->termStorage->load($tid); + $dependencies[$term->getConfigDependencyKey()][] = $term->getConfigDependencyName(); + } + + return $dependencies; + } + } diff --git a/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php b/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php index c0629c9..b57a940 100644 --- a/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php +++ b/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php @@ -2,15 +2,17 @@ /** * @file - * Definition of Drupal\taxonomy\Plugin\views\relationship\NodeTermData. + * Contains \Drupal\taxonomy\Plugin\views\relationship\NodeTermData. */ namespace Drupal\taxonomy\Plugin\views\relationship; use Drupal\Core\Form\FormStateInterface; +use Drupal\taxonomy\VocabularyStorageInterface; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\Plugin\views\relationship\RelationshipPluginBase; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Relationship handler to return the taxonomy terms of nodes. @@ -22,6 +24,43 @@ class NodeTermData extends RelationshipPluginBase { /** + * The vocabulary storage. + * + * @var \Drupal\taxonomy\VocabularyStorageInterface + */ + protected $vocabularyStorage; + + /** + * Constructs a NodeTermData 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\taxonomy\VocabularyStorageInterface $vocabulary_storage + * The vocabulary storage. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, VocabularyStorageInterface $vocabulary_storage) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->is_handler = TRUE; + $this->vocabularyStorage = $vocabulary_storage; + } + + /** + * {@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')->getStorage('taxonomy_vocabulary') + ); + } + + /** * Overrides \Drupal\views\Plugin\views\relationship\RelationshipPluginBase::init(). */ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { @@ -63,6 +102,16 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { } /** + * {@inheritdoc} + */ + public function submitOptionsForm(&$form, FormStateInterface $form_state) { + // Transform the #type = checkboxes value to a numerically indexed array, + // because the config schema expects a sequence, not a mapping. + $vids = $form_state->getValue(['options', 'vids']); + $form_state->setValue(['options', 'vids'], array_values(array_filter($vids))); + } + + /** * Called to implement a relationship in a query. */ public function query() { @@ -103,4 +152,19 @@ public function query() { $this->alias = $this->query->addRelationship($alias, $join, 'taxonomy_term_data', $this->relationship); } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + foreach ($this->options['vids'] as $vocabulary_id) { + if ($vocabulary = $this->vocabularyStorage->load($vocabulary_id)) { + $dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName(); + } + } + + return $dependencies; + } + } diff --git a/core/modules/taxonomy/src/Tests/Views/RelationshipNodeTermDataTest.php b/core/modules/taxonomy/src/Tests/Views/RelationshipNodeTermDataTest.php index 930990f..9208a28 100644 --- a/core/modules/taxonomy/src/Tests/Views/RelationshipNodeTermDataTest.php +++ b/core/modules/taxonomy/src/Tests/Views/RelationshipNodeTermDataTest.php @@ -25,6 +25,16 @@ class RelationshipNodeTermDataTest extends TaxonomyTestBase { function testViewsHandlerRelationshipNodeTermData() { $view = Views::getView('test_taxonomy_node_term_data'); + // Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies(). + $expected = [ + 'config' => ['core.entity_view_mode.node.teaser'], + 'module' => [ + 'node', + 'taxonomy', + 'user', + ], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); $this->executeView($view, array($this->term1->id(), $this->term2->id())); $expected_result = array( array( @@ -39,10 +49,13 @@ function testViewsHandlerRelationshipNodeTermData() { // Change the view to test relation limited by vocabulary. \Drupal::config('views.view.test_taxonomy_node_term_data') - ->set('display.default.display_options.relationships.term_node_tid.vids.tags', 'views_testing_tags') + ->set('display.default.display_options.relationships.term_node_tid.vids', ['views_testing_tags']) ->save(); $view = Views::getView('test_taxonomy_node_term_data'); + // Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies(). + $expected['config'][] = 'taxonomy.vocabulary.views_testing_tags'; + $this->assertIdentical($expected, $view->calculateDependencies()); $this->executeView($view, array($this->term1->id(), $this->term2->id())); $this->assertIdenticalResultset($view, $expected_result, $column_map); } diff --git a/core/modules/taxonomy/src/Tests/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/src/Tests/Views/TaxonomyIndexTidUiTest.php index fb4cad2..8c9c231 100644 --- a/core/modules/taxonomy/src/Tests/Views/TaxonomyIndexTidUiTest.php +++ b/core/modules/taxonomy/src/Tests/Views/TaxonomyIndexTidUiTest.php @@ -7,6 +7,8 @@ namespace Drupal\taxonomy\Tests\Views; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\Entity\Vocabulary; use Drupal\views\Tests\ViewTestData; use Drupal\views_ui\Tests\UITestBase; @@ -33,24 +35,23 @@ class TaxonomyIndexTidUiTest extends UITestBase { public static $modules = array('node', 'taxonomy', 'taxonomy_test_views'); /** + * A nested array of \Drupal\taxonomy\TermInterface objects. + * + * @var \Drupal\taxonomy\TermInterface[][] + */ + protected $terms = []; + + /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); - ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views')); - } - - /** - * Tests the filter UI. - */ - public function testFilterUI() { - entity_create('taxonomy_vocabulary', array( + Vocabulary::create([ 'vid' => 'tags', 'name' => 'Tags', - ))->save(); + ])->save(); - $terms = array(); // Setup a hierarchy which looks like this: // term 0.0 // term 1.0 @@ -60,15 +61,21 @@ public function testFilterUI() { // - term 2.2 for ($i = 0; $i < 3; $i++) { for ($j = 0; $j <= $i; $j++) { - $terms[$i][$j] = $term = entity_create('taxonomy_term', array( + $this->terms[$i][$j] = $term = Term::create([ 'vid' => 'tags', 'name' => "Term $i.$j", 'parent' => isset($terms[$i][0]) ? $terms[$i][0]->id() : 0, - )); + ]); $term->save(); } } + ViewTestData::createTestViews(get_class($this), array('taxonomy_test_views')); + } + /** + * Tests the filter UI. + */ + public function testFilterUI() { $this->drupalGet('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid'); $result = $this->xpath('//select[@id="edit-options-value"]/option'); @@ -78,12 +85,12 @@ public function testFilterUI() { for ($i = 0; $i < 3; $i++) { for ($j = 0; $j <= $i; $j++) { $option = $result[$counter++]; - $prefix = $terms[$i][$j]->parent->target_id ? '-' : ''; + $prefix = $this->terms[$i][$j]->parent->target_id ? '-' : ''; $attributes = $option->attributes(); $tid = (string) $attributes->value; - $this->assertEqual($prefix . $terms[$i][$j]->getName(), (string) $option); - $this->assertEqual($terms[$i][$j]->id(), $tid); + $this->assertEqual($prefix . $this->terms[$i][$j]->getName(), (string) $option); + $this->assertEqual($this->terms[$i][$j]->id(), $tid); } } @@ -96,6 +103,22 @@ public function testFilterUI() { $this->drupalGet('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid'); $result = $this->xpath('//input[@id="edit-options-value"]/@data-autocomplete-path'); $this->assertEqual((string) $result[0], \Drupal::url('taxonomy.autocomplete_vid', ['taxonomy_vocabulary' => 'tags'])); + + // Tests \Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid::calculateDependencies(). + $expected = [ + 'config' => [ + 'taxonomy.vocabulary.tags', + ], + 'content' => [ + 'taxonomy_term:tags:' . Term::load(2)->uuid(), + ], + 'module' => [ + 'node', + 'taxonomy', + 'user', + ], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); } } diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml index 0157b91..430f6f9 100644 --- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml +++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml @@ -136,7 +136,7 @@ display: admin_label: '' operator: or value: - 2: '2' + - '2' group: 1 exposed: false expose: diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml index c4c306d..c96c7da 100644 --- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml +++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml @@ -61,16 +61,14 @@ display: id: term_node_tid admin_label: 'Term #1' table: node - vids: - tags: '' + vids: {} plugin_id: node_term_data term_node_tid_1: field: term_node_tid id: term_node_tid_1 admin_label: 'Term #2' table: node - vids: - tags: '' + vids: {} plugin_id: node_term_data sorts: nid: diff --git a/core/modules/user/src/Plugin/views/access/Role.php b/core/modules/user/src/Plugin/views/access/Role.php index d821b11..954ea4f 100644 --- a/core/modules/user/src/Plugin/views/access/Role.php +++ b/core/modules/user/src/Plugin/views/access/Role.php @@ -9,7 +9,9 @@ use Drupal\Component\Utility\String; use Drupal\Core\Form\FormStateInterface; +use Drupal\user\RoleStorageInterface; use Drupal\views\Plugin\views\access\AccessPluginBase; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Routing\Route; use Drupal\Core\Session\AccountInterface; @@ -32,6 +34,43 @@ class Role extends AccessPluginBase { protected $usesOptions = TRUE; /** + * The role storage. + * + * @var \Drupal\user\RoleStorageInterface + */ + protected $roleStorage; + + /** + * Constructs a Role 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\user\RoleStorageInterface $role_storage + * The role storage. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RoleStorageInterface $role_storage) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->is_handler = TRUE; + $this->roleStorage = $role_storage; + } + + /** + * {@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')->getStorage('user_role') + ); + } + + /** * {@inheritdoc} */ public function access(AccountInterface $account) { @@ -92,4 +131,19 @@ public function validateOptionsForm(&$form, FormStateInterface $form_state) { $form_state->setValue(array('access_options', 'role'), $role); } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + foreach (array_keys($this->options['role']) as $rid) { + if ($role = $this->roleStorage->load($rid)) { + $dependencies[$role->getConfigDependencyKey()][] = $role->getConfigDependencyName(); + } + } + + return $dependencies; + } + } diff --git a/core/modules/user/src/Tests/Views/AccessRoleTest.php b/core/modules/user/src/Tests/Views/AccessRoleTest.php index b4086bd..f01f412 100644 --- a/core/modules/user/src/Tests/Views/AccessRoleTest.php +++ b/core/modules/user/src/Tests/Views/AccessRoleTest.php @@ -38,6 +38,11 @@ function testAccessRole() { $this->normalRole => $this->normalRole, ); $view->save(); + $expected = [ + 'config' => ['user.role.' . $this->normalRole], + 'module' => ['user'], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); $executable = Views::executableFactory()->get($view); $executable->setDisplay('page_1'); @@ -65,6 +70,14 @@ function testAccessRole() { 'anonymous' => 'anonymous', ); $view->save(); + $expected = [ + 'config' => [ + 'user.role.anonymous', + 'user.role.' . $this->normalRole, + ], + 'module' => ['user'], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); $this->drupalLogin($this->webUser); $this->drupalGet('test-role'); $this->assertResponse(403); diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php index f0d10ea..c3690ed 100644 --- a/core/modules/views/src/Entity/View.php +++ b/core/modules/views/src/Entity/View.php @@ -287,8 +287,7 @@ public function calculateDependencies() { foreach ($executable->displayHandlers as $display) { // Add dependency for the display itself. - /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase $display */ - $this->addDependency('module', $display->getProvider()); + $this->calculatePluginDependencies($display); // Collect all dependencies of all handlers. foreach ($handler_types as $handler_type) { diff --git a/core/modules/views/src/Plugin/views/area/View.php b/core/modules/views/src/Plugin/views/area/View.php index 4e228bc..4f3af1c 100644 --- a/core/modules/views/src/Plugin/views/area/View.php +++ b/core/modules/views/src/Plugin/views/area/View.php @@ -151,4 +151,19 @@ public function isEmpty() { } } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + list($view_id) = explode(':', $this->options['view_to_insert'], 2); + if ($view_id) { + $view = $this->viewStorage->load($view_id); + $dependencies[$view->getConfigDependencyKey()][] = $view->getConfigDependencyName(); + } + + return $dependencies; + } + } diff --git a/core/modules/views/src/Plugin/views/argument_validator/Entity.php b/core/modules/views/src/Plugin/views/argument_validator/Entity.php index ee2ab8c..110b5bb 100644 --- a/core/modules/views/src/Plugin/views/argument_validator/Entity.php +++ b/core/modules/views/src/Plugin/views/argument_validator/Entity.php @@ -7,6 +7,7 @@ namespace Drupal\views\Plugin\views\argument_validator; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\FormStateInterface; @@ -211,4 +212,22 @@ protected function validateEntity(EntityInterface $entity) { return TRUE; } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + $entity_type_id = $this->definition['entity_type']; + $bundle_entity_type = $this->entityManager->getDefinition($entity_type_id)->getBundleEntityType(); + $bundle_entity_storage = $this->entityManager->getStorage($bundle_entity_type); + + foreach (array_keys($this->options['bundles']) as $bundle) { + $bundle_entity = $bundle_entity_storage->load($bundle); + $dependencies[$bundle_entity->getConfigDependencyKey()][] = $bundle_entity->getConfigDependencyName(); + } + + return $dependencies; + } + } diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php index 3dd9a3d..540f6db 100644 --- a/core/modules/views/src/Plugin/views/display/Page.php +++ b/core/modules/views/src/Plugin/views/display/Page.php @@ -8,7 +8,11 @@ namespace Drupal\views\Plugin\views\display; use Drupal\Component\Utility\Xss; +use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\State\StateInterface; +use Drupal\Core\Routing\RouteProviderInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -38,6 +42,51 @@ class Page extends PathPluginBase { protected $usesAttachments = TRUE; /** + * The menu storage. + * + * @var \Drupal\Core\Entity\EntityStorageInterface + */ + protected $menuStorage; + + /** + * Constructs a Page 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\Routing\RouteProviderInterface $route_provider + * The route provider. + * @param \Drupal\Core\State\StateInterface $state + * The state key value store. + * @param \Drupal\Core\Entity\EntityStorageInterface $menu_storage + * The menu storage. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, EntityStorageInterface $menu_storage) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider, $state); + + $this->routeProvider = $route_provider; + $this->state = $state; + $this->menuStorage = $menu_storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('router.route_provider'), + $container->get('state'), + $container->get('entity.manager')->getStorage('menu') + ); + } + + /** * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::defineOptions(). */ protected function defineOptions() { @@ -202,7 +251,8 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { // Only display the parent selector if Menu UI module is enabled. $menu_parent = $menu['menu_name'] . ':' . $menu['parent']; if (\Drupal::moduleHandler()->moduleExists('menu_ui')) { - $form['menu']['parent'] = \Drupal::service('menu.parent_form_selector')->parentSelectElement($menu_parent); + $menu_link = 'views_view:views.' . $form_state->get('view')->id() . '.' . $form_state->get('display_id'); + $form['menu']['parent'] = \Drupal::service('menu.parent_form_selector')->parentSelectElement($menu_parent, $menu_link); $form['menu']['parent'] += array( '#title' => $this->t('Parent'), '#description' => $this->t('The maximum depth for a link and all its children is fixed. Some menu links may not be available as parents if selecting them would exceed this limit.'), @@ -425,4 +475,19 @@ public function getPagerText() { ); } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + $menu = $this->getOption('menu'); + if ($menu['type'] === 'normal') { + $menu_entity = \Drupal::entityManager()->getStorage('menu')->load($menu['menu_name']); + $dependencies[$menu_entity->getConfigDependencyKey()][] = $menu_entity->getConfigDependencyName(); + } + + return $dependencies; + } + } diff --git a/core/modules/views/src/Plugin/views/filter/Bundle.php b/core/modules/views/src/Plugin/views/filter/Bundle.php index 614a75c..b518354 100644 --- a/core/modules/views/src/Plugin/views/filter/Bundle.php +++ b/core/modules/views/src/Plugin/views/filter/Bundle.php @@ -7,8 +7,11 @@ namespace Drupal\views\Plugin\views\filter; +use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\display\DisplayPluginBase; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Filter class which allows filtering by entity bundles. @@ -34,6 +37,43 @@ class Bundle extends InOperator { protected $entityType; /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** + * Constructs a Bundle 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. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->entityManager = $entity_manager; + } + + /** + * {@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') + ); + } + + /** * Overrides \Drupal\views\Plugin\views\filter\InOperator::init(). */ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { @@ -73,4 +113,21 @@ public function query() { parent::query(); } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + $bundle_entity_type = $this->entityType->getBundleEntityType(); + $bundle_entity_storage = $this->entityManager->getStorage($bundle_entity_type); + + foreach (array_keys($this->value) as $bundle) { + $bundle_entity = $bundle_entity_storage->load($bundle); + $dependencies[$bundle_entity->getConfigDependencyKey()][] = $bundle_entity->getConfigDependencyName(); + } + + return $dependencies; + } + } diff --git a/core/modules/views/src/Plugin/views/row/EntityRow.php b/core/modules/views/src/Plugin/views/row/EntityRow.php index 77f8a85..7a24818 100644 --- a/core/modules/views/src/Plugin/views/row/EntityRow.php +++ b/core/modules/views/src/Plugin/views/row/EntityRow.php @@ -213,4 +213,20 @@ public function render($row) { return $this->getRenderer()->render($row); } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + $view_mode = $this->entityManager + ->getStorage('entity_view_mode') + ->load($this->entityTypeId . '.' . $this->options['view_mode']); + if ($view_mode) { + $dependencies[$view_mode->getConfigDependencyKey()][] = $view_mode->getConfigDependencyName(); + } + + return $dependencies; + } + } diff --git a/core/modules/views/src/Plugin/views/row/RssPluginBase.php b/core/modules/views/src/Plugin/views/row/RssPluginBase.php new file mode 100644 index 0000000..b8187be --- /dev/null +++ b/core/modules/views/src/Plugin/views/row/RssPluginBase.php @@ -0,0 +1,116 @@ +entityManager = $entity_manager; + } + + /** + * {@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') + ); + } + + /** + * The ID of the entity type for which this is an RSS row plugin. + * + * @var string + */ + protected $entityTypeId; + + /** + * {@inheritdoc} + */ + protected function defineOptions() { + $options = parent::defineOptions(); + + $options['view_mode'] = array('default' => 'default'); + + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + parent::buildOptionsForm($form, $form_state); + + $form['view_mode'] = array( + '#type' => 'select', + '#title' => $this->t('Display type'), + '#options' => $this->buildOptionsForm_summary_options(), + '#default_value' => $this->options['view_mode'], + ); + } + + /** + * Return the main options, which are shown in the summary title. + */ + public function buildOptionsForm_summary_options() { + $view_modes = \Drupal::entityManager()->getViewModes($this->entityTypeId); + $options = array(); + foreach ($view_modes as $mode => $settings) { + $options[$mode] = $settings['label']; + } + return $options; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + + $view_mode = $this->entityManager + ->getStorage('entity_view_mode') + ->load($this->entityTypeId . '.' . $this->options['view_mode']); + if ($view_mode) { + $dependencies[$view_mode->getConfigDependencyKey()][] = $view_mode->getConfigDependencyName(); + } + + return $dependencies; + } + +} diff --git a/core/modules/views/src/Tests/Entity/FilterEntityBundleTest.php b/core/modules/views/src/Tests/Entity/FilterEntityBundleTest.php index cde6f75..808c8a4 100644 --- a/core/modules/views/src/Tests/Entity/FilterEntityBundleTest.php +++ b/core/modules/views/src/Tests/Entity/FilterEntityBundleTest.php @@ -8,6 +8,7 @@ namespace Drupal\views\Tests\Entity; use Drupal\views\Tests\ViewTestBase; +use Drupal\views\Tests\ViewTestData; use Drupal\views\Views; /** @@ -46,11 +47,13 @@ class FilterEntityBundleTest extends ViewTestBase { protected $entities = array(); protected function setUp() { - parent::setUp(); + parent::setUp(FALSE); $this->drupalCreateContentType(array('type' => 'test_bundle')); $this->drupalCreateContentType(array('type' => 'test_bundle_2')); + ViewTestData::createTestViews(get_class($this), array('views_test_config')); + $this->entityBundles = entity_get_bundles('node'); $this->entities['count'] = 0; @@ -70,6 +73,19 @@ protected function setUp() { */ public function testFilterEntity() { $view = Views::getView('test_entity_type_filter'); + + // Tests \Drupal\views\Plugin\views\filter\Bundle::calculateDependencies(). + $expected = [ + 'config' => [ + 'node.type.test_bundle', + 'node.type.test_bundle_2', + ], + 'module' => [ + 'node' + ], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); + $this->executeView($view); // Test we have all the results, with all types selected. diff --git a/core/modules/views/src/Tests/Handler/AreaViewTest.php b/core/modules/views/src/Tests/Handler/AreaViewTest.php index 16bd12e..ef7498b 100644 --- a/core/modules/views/src/Tests/Handler/AreaViewTest.php +++ b/core/modules/views/src/Tests/Handler/AreaViewTest.php @@ -30,7 +30,7 @@ class AreaViewTest extends ViewUnitTestBase { * * @var array */ - public static $testViews = array('test_area_view', 'test_simple_argument'); + public static $testViews = array('test_simple_argument', 'test_area_view'); /** * Tests the view area handler. @@ -38,6 +38,9 @@ class AreaViewTest extends ViewUnitTestBase { public function testViewArea() { $view = Views::getView('test_area_view'); + // Tests \Drupal\views\Plugin\views\area\View::calculateDependencies(). + $this->assertIdentical(['config' => ['views.view.test_simple_argument']], $view->calculateDependencies()); + $this->executeView($view); $output = $view->render(); $output = drupal_render($output); diff --git a/core/modules/views/src/Tests/Plugin/DisplayPageTest.php b/core/modules/views/src/Tests/Plugin/DisplayPageTest.php index 7f5ebe4..4222f17 100644 --- a/core/modules/views/src/Tests/Plugin/DisplayPageTest.php +++ b/core/modules/views/src/Tests/Plugin/DisplayPageTest.php @@ -137,7 +137,31 @@ public function testMenuLinks() { $tree = \Drupal::menuTree()->load('admin', new MenuTreeParameters()); $this->assertTrue(isset($tree['system.admin']->subtree['views_view:views.test_page_display_menu.page_4'])); $menu_link = $tree['system.admin']->subtree['views_view:views.test_page_display_menu.page_4']->link; - $this->assertEqual($menu_link->getTitle(), 'Test child'); + $this->assertEqual($menu_link->getTitle(), 'Test child (with parent)'); + } + + /** + * Tests the calculated dependencies for various views using Page displays. + */ + public function testDependencies() { + $view = Views::getView('test_page_display'); + $this->assertIdentical([], $view->calculateDependencies()); + + $view = Views::getView('test_page_display_route'); + $expected = [ + 'content' => ['StaticTest'], + 'module' => ['views_test_data'], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); + + $view = Views::getView('test_page_display_menu'); + $expected = [ + 'config' => [ + 'system.menu.admin', + 'system.menu.tools', + ], + ]; + $this->assertIdentical($expected, $view->calculateDependencies()); } } diff --git a/core/modules/views/src/Tests/ViewTestData.php b/core/modules/views/src/Tests/ViewTestData.php index 97f2d66..03c4bae 100644 --- a/core/modules/views/src/Tests/ViewTestData.php +++ b/core/modules/views/src/Tests/ViewTestData.php @@ -23,7 +23,7 @@ class ViewTestData { * Create test views from config. * * @param string $class - * The name of the test class. + * The name of the test class. Installs the listed test views *in order*. * @param array $modules * The module directories to look in for test views. */ @@ -45,9 +45,10 @@ public static function createTestViews($class, array $modules) { } $file_storage = new FileStorage($config_dir); - foreach ($file_storage->listAll('views.view.') as $config_name) { - $id = str_replace('views.view.', '', $config_name); - if (in_array($id, $views)) { + $available_views = $file_storage->listAll('views.view.'); + foreach ($views as $id) { + $config_name = 'views.view.' . $id; + if (in_array($config_name, $available_views)) { $storage ->create($file_storage->read($config_name)) ->save(); diff --git a/core/modules/views/src/Tests/ViewUnitTestBase.php b/core/modules/views/src/Tests/ViewUnitTestBase.php index 0d07484..86ed262 100644 --- a/core/modules/views/src/Tests/ViewUnitTestBase.php +++ b/core/modules/views/src/Tests/ViewUnitTestBase.php @@ -44,6 +44,10 @@ protected function setUp() { * using it, it cannot be enabled normally. */ protected function setUpFixtures() { + // First install the system module. Many Views have Page displays have menu + // links, and for those to work, the system menus must already be present. + $this->installConfig(array('system')); + // Define the schema and views data variable before enabling the test module. \Drupal::state()->set('views_test_data_schema', $this->schemaDefinition()); \Drupal::state()->set('views_test_data_views_data', $this->viewsData()); @@ -66,9 +70,6 @@ protected function setUpFixtures() { } $query->execute(); - // Tests implementing ViewUnitTestBase depend on the theme system being - // properly configured. - $this->installConfig(array('system')); ViewTestData::createTestViews(get_class($this), array('views_test_config')); } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml index ad5f178..98e061c 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml @@ -87,7 +87,6 @@ display: field: type relationship: none value: - all: all test_bundle: test_bundle test_bundle_2: test_bundle_2 plugin_id: bundle diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_page_display_menu.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_page_display_menu.yml index c9b40a5..6d524b9 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_page_display_menu.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_page_display_menu.yml @@ -97,10 +97,10 @@ display: title: 'Test page as child' menu: type: normal - title: 'Test child' + title: 'Test child (with parent)' parent: system.admin description: '' - menu_name: tools + menu_name: admin weight: 0 context: '0' defaults: @@ -117,10 +117,10 @@ display: title: 'Tests a menu with a non-existing parent' menu: type: normal - title: 'Test child' - parent: system.admin + title: 'Test child with non-existing parent' + parent: llamasarelame description: '' - menu_name: not-existing-menu-name + menu_name: admin weight: 0 context: '0' defaults: @@ -129,5 +129,5 @@ display: field_langcode_add_to_query: null display_plugin: page display_title: Page - id: page_4 + id: page_5 position: 0 diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml index 4399c42..802f06f 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml @@ -57,47 +57,6 @@ display: plugin_id: node entity_type: node entity_field: title - filters: - type: - id: type - table: node_field_data - field: type - relationship: none - group_type: group - admin_label: '' - operator: in - value: - page: page - group: 1 - exposed: false - expose: - operator_id: '' - label: '' - description: '' - use_operator: false - operator: '' - identifier: '' - required: false - remember: false - multiple: false - remember_roles: - authenticated: authenticated - reduce: false - is_grouped: false - group_info: - label: '' - description: '' - identifier: '' - optional: true - widget: select - multiple: false - remember: false - default_group: All - default_group_multiple: { } - group_items: { } - plugin_id: bundle - entity_type: node - entity_field: type group_by: true pager: type: some diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 4a08788..ef9da7f 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -1129,6 +1129,12 @@ public function calculateDependencies() { /** * {@inheritdoc} */ + public function getConfigDependencyKey() { + } + + /** + * {@inheritdoc} + */ public function getConfigDependencyName() { } diff --git a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php index c04c32e..b77f595 100644 --- a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php +++ b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php @@ -82,9 +82,10 @@ public function testBuildRowEntityList() { ); $route_provider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface'); $state = $this->getMock('\Drupal\Core\State\StateInterface'); + $menu_storage = $this->getMock('\Drupal\Core\Entity\EntityStorageInterface'); $page_display = $this->getMock('Drupal\views\Plugin\views\display\Page', array('initDisplay', 'getPath'), - array(array(), 'default', $display_manager->getDefinition('page'), $route_provider, $state) + array(array(), 'default', $display_manager->getDefinition('page'), $route_provider, $state, $menu_storage) ); $page_display->expects($this->any()) ->method('getPath') diff --git a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php index e125d3b..60a9d16 100644 --- a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php +++ b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php @@ -42,7 +42,7 @@ public function testEntityDecoration() { // process. EntityInterface::getConfigDependencyName() and // ConfigEntityInterface::calculateDependencies() are only used for // dependency management. - if (!in_array($reflection_method->getName(), ['isNew', 'isSyncing', 'isUninstalling', 'getConfigDependencyName', 'calculateDependencies'])) { + if (!in_array($reflection_method->getName(), ['isNew', 'isSyncing', 'isUninstalling', 'getConfigDependencyKey', 'getConfigDependencyName', 'calculateDependencies'])) { if (count($reflection_method->getParameters()) == 0) { $method_args[$reflection_method->getName()] = array(); }