Problem/Motivation

#2216071: Views plugins need a way to store additional dependencies went in, which is good. However, this only really has a mechanism in place for storing dependencies for handlers, not all views plugins. We need this for other plugins such as display, style, row, cache, etc..

Proposed resolution

Calculate all the plugin dependencies when a view is saved. This makes the View configuration entity behave more like other configuration entities with configured plugins (eg blocks and filter formats). On save, the view will instantiate all of its plugins and add the provider as a dependency, any config dependencies from the definition and any dependencies as a result of calling calculateDependencies. This means that we no longer have to store provider or dependency information for each plugin in the view configuration.

Remaining tasks

Review and commit.

User interface changes

None

API changes

Views plugins implement DependentPluginInterface

CommentFileSizeAuthor
#75 2267453-2.75.patch260.12 KBalexpott
#75 73-75-interdiff.txt820 bytesalexpott
#73 2267453-2.73.patch260.16 KBalexpott
#63 2267453-2.63.patch304.68 KBalexpott
#63 58-63-interdiff.txt7.54 KBalexpott
#58 2267453-2.58.patch256.72 KBalexpott
#58 55-58-interdiff.txt1.46 KBalexpott
#55 interdiff.txt2.34 KBdawehner
#55 2267453-55.patch255.65 KBdawehner
#54 2267453-2.54.patch256.71 KBalexpott
#54 51-54-interdiff.txt213.93 KBalexpott
#51 2267453-2.51.patch51.42 KBalexpott
#51 49-51-interdiff.txt1.43 KBalexpott
#49 2267453-2.49.patch50.78 KBalexpott
#49 48-49-interdiff.txt859 bytesalexpott
#48 2267453-2.48.patch50.74 KBalexpott
#48 47-48-interdiff.txt3.88 KBalexpott
#47 2267453-2.47.patch51.11 KBalexpott
#47 46-47-interdiff.txt9.65 KBalexpott
#46 2267453-2.46.patch49.37 KBalexpott
#46 42-46-interdiff.txt2.7 KBalexpott
#42 2267453-2.42.patch48.89 KBalexpott
#42 39-42-interdiff.txt9.37 KBalexpott
#39 interdiff-2267453-39.txt9.09 KBdamiankloip
#39 2267453-39.patch46.35 KBdamiankloip
#36 interdiff.txt777 bytesdawehner
#36 2267453-36.patch43.43 KBdawehner
#34 2267453-34.patch43.22 KBdawehner
#34 interdiff.txt3.07 KBdawehner
#32 interdiff.txt17.42 KBdawehner
#32 2267453-32.patch42.54 KBdawehner
#25 interdiff-2267453025.txt3.18 KBdamiankloip
#25 2267453-25.patch42.27 KBdamiankloip
#22 interdiff-2267453-21.txt22.52 KBdamiankloip
#22 2267453-21.patch43.52 KBdamiankloip
#17 interdiff-2267453-17.txt3.57 KBdamiankloip
#17 2267453-17.patch23.17 KBdamiankloip
#14 2267453-14.patch21.43 KBdamiankloip
#8 interdiff.txt4.03 KBdawehner
#8 views_plugin_dependencies-2267453-8.patch21.73 KBdawehner
#7 plugin_dependencies-2267453-7.patch20.55 KBdawehner
#3 2267453.patch11.89 KBdamiankloip

Comments

tim.plunkett’s picture

I'll work on this. I think we'll want the other issue to go in first.

damiankloip’s picture

That issue does not affect this one too much IMO :/ as that PluginDependencyTrait will not be usable in views. We currently store the dependencies with the rest of the options, so they are saved etc.. and we have them all in configuration. I am not too keen on changing everything about how dependencies are stored for views plugins so we can use a trait.

EDIT: It's probably also worth pointing out that this issue was not meant solely for config entity deps, but entity dependencies that views has too.

damiankloip’s picture

StatusFileSize
new11.89 KB

Here is some local work I already have for this. Dependencies also collect any entity type not just config entities. Which I think may be wrong. Either way, we will need these sorts of changes for this functionality.

gábor hojtsy’s picture

#2309247: Views do not depend on modules providing their displays is a solution for a very limited subset of this issue by inheriting the provider form the display like it is from handlers. That causes direct schema validation issues with existing shipped views in core, and big enough in itself to resolve that its fine in its own issue IMHO.

catch’s picture

Issue tags: +D8 upgrade path

I think this should probably be critical - if we start validating something after release that we previously didn't, then sites are going to get into an invalid state that they either need to fix themselves or we have to write an upgrade path.

Tagging with D8 upgrade path and moving to major for now anyway, since this requires resaving all the views in the system to add the correct dependencies to the config YAML once it's been added.

tim.plunkett’s picture

Priority: Normal » Major
dawehner’s picture

Assigned: tim.plunkett » Unassigned
StatusFileSize
new20.55 KB

Some more work.

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new21.73 KB
new4.03 KB

A little bit more work.

damiankloip’s picture

The way things stand with calculating dependencies right now, these should only include config dependencies. This is not how I did the original patch. We ideally need to just list all dependencies like we are here. We need to summon @alexpott here, as we spoke about how we can handle this.

So this is almost postponed until we get some clear path forward on that IMO.

Status: Needs review » Needs work

The last submitted patch, 8: views_plugin_dependencies-2267453-8.patch, failed testing.

dawehner’s picture

@damiankloip
Ah I see. I wonder whether we have to split these dependencies then?

damiankloip’s picture

Yes, that is the one million dollar question :)

damiankloip’s picture

.

damiankloip’s picture

StatusFileSize
new21.43 KB

Let's start with a reroll.

damiankloip’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 14: 2267453-14.patch, failed testing.

damiankloip’s picture

StatusFileSize
new23.17 KB
new3.57 KB

Let's get tests passing. Then I will merge some of the work from #2304479: Dependency on entity-type providing module missing in views into here.

damiankloip’s picture

Status: Needs work » Needs review
dawehner’s picture

@damiankloip
Now that you will merge the two issues together, can we mark the other issue as duplicate and move this on to be critical?

damiankloip’s picture

Priority: Major » Critical

Yes. We sure can!

damiankloip’s picture

.

damiankloip’s picture

StatusFileSize
new43.52 KB
new22.52 KB

Here is some worked merged in from #2304479: Dependency on entity-type providing module missing in views.

Not sure if we want to keep the explicit base table? I think we should let the query plugin do this? I changed things round a bit in that area too.

damiankloip’s picture

Self review/observations:

  1. +++ b/core/modules/views/src/Entity/View.php
    @@ -100,6 +100,13 @@ class View extends ConfigEntityBase implements ViewStorageInterface {
    +   * The views data.
    +   *
    +   * @var \Drupal\views\ViewsData
    +   */
    +  protected $viewsData;
    
    @@ -122,6 +129,18 @@ public function getExecutable() {
    +   * Gets the views data.
    +   *
    +   * @return \Drupal\views\ViewsData
    +   */
    +  protected function getViewsData() {
    +    if (!isset($this->viewsData)) {
    +      $this->viewsData = Views::viewsData();
    +    }
    +    return $this->viewsData;
    +  }
    

    We can prob remove this now if we delegate table responsibility to the query plugin?

  2. +++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
    @@ -118,6 +118,22 @@ public function summaryTitle() {
    +    foreach ($this->getEntityTableInfo() as $entity_type => $info) {
    +      if (!empty($info['provider'])) {
    +        $dependencies['module'][] = $info['provider'];
    +        $dependencies['entity'][] = $entity_type;
    +      }
    +    }
    

    This looks really simple now if getEntityTableInfo has what we need.

    Note to self: Need to move the entity type dependency outside that conditional.

  3. +++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
    @@ -260,7 +276,13 @@ public function getEntityTableInfo() {
    +      // Include the entity provider.
    +      if (!empty($table_data['table']['provider'])) {
    +        $entity_tables[$table_data['table']['entity type']]['provider'] = $table_data['table']['provider'];
    

    If we add this to the getEntityTableInfo() method, we are already getting similar data. So can be easily used in getDependencies

  4. +++ b/core/modules/views/src/Entity/View.php
    @@ -279,15 +290,22 @@ public function calculateDependencies() {
    +      // @todo This totally does not work for argument validator/default
    +      //   plugins.
    

    Certainly still need to resolve this one.

Also, something I am pretty sure the config system does with dependencies is get the provider based on the entity type. So should we do something like this and just provide entity types? Could be a problem with non-entity table data?

wim leers’s picture

Apologies if I miss the mark on some things in my review. I probably need a walkthrough of the patch to fully grok it.

  1. +++ b/core/modules/views/src/Entity/View.php
    @@ -279,15 +290,22 @@ public function calculateDependencies() {
    +        if (!empty($display['display_options'][$plugin_type]['dependencies'])) {
    

    Missing comment: Add (inherit) the plugin's dependencies.

  2. +++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
    @@ -118,6 +118,22 @@ public function summaryTitle() {
    +    foreach ($this->getEntityTableInfo() as $entity_type => $info) {
    +      if (!empty($info['provider'])) {
    +        $dependencies['module'][] = $info['provider'];
    +        $dependencies['entity'][] = $entity_type;
    +      }
    +    }
    

    So once getEntityTableInfo() (or its successor) returns metadata about what the current view filters by (e.g. "only article nodes"), we will add dependencies on the bundle's config entity type?

  3. +++ b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
    @@ -163,6 +163,22 @@ public function query() {
    +   * @todo Just remove this and rely on query dependencies?
    +   */
    +  public function getDependencies() {
    

    If that's possible, then yes!

  4. +++ b/core/modules/views/src/Tests/Entity/ViewEntityDependenciesTest.php
    @@ -15,56 +16,57 @@
    -class ViewEntityDependenciesTest extends ViewTestBase {
    +class ViewEntityDependenciesTest extends ViewUnitTestBase {
    

    Nice! :)

  5. +++ b/core/modules/views/src/Tests/Entity/ViewEntityDependenciesTest.php
    @@ -15,56 +16,57 @@
    +      'test_dependency' => array(
    +        'row', 'style',
    +      )
    

    Extreme nitpick: strange code formatting.

  6. +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_plugin_dependencies.yml
    @@ -0,0 +1,60 @@
    +core: 8.0-dev
    
    +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_relationship_dependency.yml
    @@ -0,0 +1,51 @@
    +core: 8.0-dev
    

    We probably don't want these.

  7. Could be a problem with non-entity table data?

    Interesting! And I definitely don't fully understand this, but… doesn't Views need some sort of plugin to tell it to use a certain DB table, otherwise Views will never use it anyway? if that's the case, why can't that plugin provide the necessary dependency information?

damiankloip’s picture

StatusFileSize
new42.27 KB
new3.18 KB

reroll and addressed a few small points.

We probably don't want these.

Let's leave those for now as they are generated by the view. I would like to remove that property though for all. So let's do that separately.

catch’s picture

Issue tags: +beta target
dawehner’s picture

  1. +++ b/core/modules/views/src/Entity/View.php
    @@ -279,15 +278,23 @@ public function calculateDependencies() {
    +
    +      // @todo This totally does not work for argument validator/default
    +      //   plugins.
     
           // Collect all dependencies of plugins.
    

    Do you think we can do this as part of this patch? It seems odd to not support a specific subset. Wait, but can't we add getDependencies() those dependencies?

  2. +++ b/core/modules/views/src/Entity/View.php
    @@ -383,11 +390,4 @@ public function mergeDefaultDisplaysOptions() {
     
    -  /**
    -   * Wraps drupal_get_schema().
    -   */
    -  protected function drupalGetSchema($table = NULL, $rebuild = FALSE) {
    -    return drupal_get_schema($table, $rebuild);
    -  }
    -
    

    Yeah!

  3. +++ b/core/modules/views/src/Plugin/views/PluginBase.php
    @@ -392,6 +392,9 @@ public function getDependencies() {
        *
    +   * @todo Update this docblock to reflect the dependencies structure for module,
    +   *   entity etc..
    

    Yeah just remove that todo, noone will see it and we don't really like honest todos.

  4. +++ b/core/modules/views/src/ViewExecutable.php
    @@ -297,7 +297,7 @@ class ViewExecutable {
        *
        * @var array
        */
    -  public $relationship;
    +  public $relationship = array();
    

    A new issue to use new Type[] on there would be cool for all those handler types.

mgifford’s picture

dawehner’s picture

+1 for decoupling it!

+++ b/core/modules/views/src/ViewsData.php
index 34167b0..33925df 100644
--- a/core/modules/views/views.views.inc

--- a/core/modules/views/views.views.inc
+++ b/core/modules/views/views.views.inc

+++ b/core/modules/views/views.views.inc
+++ b/core/modules/views/views.views.inc
@@ -160,8 +160,13 @@ function views_views_data() {

@@ -160,8 +160,13 @@ function views_views_data() {
   foreach (\Drupal::entityManager()->getDefinitions() as $entity_type_id => $entity_type) {
     if ($entity_type->hasHandlerClass('views_data')) {
       /** @var \Drupal\views\EntityViewsDataInterface $views_data */
-      $views_data = \Drupal::entityManager()->getHandler($entity_type_id, 'views_data');
-      $data = NestedArray::mergeDeep($data, $views_data->getViewsData());
+      $views_data = \Drupal::entityManager()->getHandler($entity_type_id, 'views_data')->getViewsData();
+      // Make sure each table has a provider.
+      $provider = $entity_type->getProvider();
+      array_walk($views_data, function(&$table_data) use ($provider){
+        $table_data['table']['provider'] = $provider;
+      });
+      $data = NestedArray::mergeDeep($data, $views_data);
     }
   }

Should we also move that code into the generic EntityViewsData implementation somehow?

damiankloip’s picture

Hmm. Not sure really. The main reason it is there are for EntityViewsData extended classes. We can then not enforce a provider is on every table. Take Node as an example. What do you think?

dawehner’s picture

Can't we take the provider the from entity type definition and be done?

dawehner’s picture

Do you think we can do this as part of this patch? It seems odd to not support a specific subset. Wait, but can't we add getDependencies() those dependencies?

Let's first sort out the storage we use, #2356181: Unify the storage of argument default/validator/summary plugins. will allow us to do that.

A new issue to use new Type[] on there would be cool for all those handler types.

Let's add another follow up

Some tiny work here and there.

Status: Needs review » Needs work

The last submitted patch, 32: 2267453-32.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new3.07 KB
new43.22 KB

Let's fix the failures ...

Status: Needs review » Needs work

The last submitted patch, 34: 2267453-34.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new43.43 KB
new777 bytes

So yeah I would prefer the casting here over the default value of the ViewExecutable as we might want to distinct between
no relationship and no initialized relationships.

mgifford’s picture

In an effort to nudge this along. This applies nicely in simplytest.me - it's unclear to me though what the steps are for testing this.

What are the steps required to bring this to RTBC?

damiankloip’s picture

+++ b/core/modules/views/tests/modules/views_test_data/views_test_data.views.inc
@@ -23,7 +23,7 @@ function views_test_data_views_data() {
+  return $state->get('views_test_data_views_data') ?: [];

You can just pass [] as the second parameter to $state->get().

I am ok with leaving $relationship as null for that reason.

And.. Moving the additional of the table provider to the viewsData class is fine by me, I don;t see that in any interdiff though... :D

damiankloip’s picture

StatusFileSize
new46.35 KB
new9.09 KB

Sorry about the delay, got taken a bit ill yesterday, plus $day_job!

Alex, can you try this? This should work better I think. Will still need some tidy after. Just did what I had time for right now. Should save dependencies more like you would expect though.

Status: Needs review » Needs work

The last submitted patch, 39: 2267453-39.patch, failed testing.

damiankloip’s picture

Those failures were expected. Will fix them in the next patch iteration.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new9.37 KB
new48.89 KB

Bringing the patch more inline with ConfigEntityBase::calculatePluginDependencies() - I think views plugins should use the DependentPluginInterface from #2271419: Allow field types, widgets, formatters to specify config dependencies

We have a problem with relationship plugins are working out their dependencies.

Removed Drupal\Tests\views\Unit\Entity\ViewTest because setting up the dependencies to test under PHPUnit is just not worth it.

Status: Needs review » Needs work

The last submitted patch, 42: 2267453-2.42.patch, failed testing.

dawehner’s picture

Removed Drupal\Tests\views\Unit\Entity\ViewTest because setting up the dependencies to test under PHPUnit is just not worth it.

What?!

alexpott’s picture

re #44 the current test shows precisely why this is not worth it - dependencies on entity provided schemas has been broken for a couple of months and this test did not tell us (or force the entity schema patch to fix) because of the way it was mocking stuff. Dependency management is 99.9% about integrating across different types of things - in views case those type of things are more than any other config entity. If we mock stuff and think we have this tested we are leading ourselves to have a false sense of security.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new2.7 KB
new49.37 KB

relationship plugins now add dependencies based on the base table they bring to the party!

alexpott’s picture

StatusFileSize
new9.65 KB
new51.11 KB

renamed the geDependencies() method to calculateDependencies() so we use DependentPluginInterface once #2271419: Allow field types, widgets, formatters to specify config dependencies lands. Also this means views plugins are one step closer ConfigurablePluginInterface.

Added test assertion for the dependency added by Drupal\field\Plugin\views\field\Field

alexpott’s picture

StatusFileSize
new3.88 KB
new50.74 KB

Now that #2271419: Allow field types, widgets, formatters to specify config dependencies has landed we can just use regular plugin dependency code :)

@damiankloip / @dawehner do you think we need to do anything else here? I'd be in favour of handling anything else in followups since this is already a massive improvement over what we have.

alexpott’s picture

StatusFileSize
new859 bytes
new50.78 KB

Opened #2368767: Implement calculateDependencies() in ArgumentPluginBase to get dependencies from validator and default plugins to handle argument validator/default plugins. Patch attached fixes the @todo.

jibran’s picture

Status: Needs review » Needs work

Thank you for the nice work on the patch @alexpott. I think this patch is almost ready. Just two minor issues.

  1. +++ b/core/modules/views/src/Entity/View.php
    @@ -100,6 +100,13 @@ class View extends ConfigEntityBase implements ViewStorageInterface {
    +  protected $viewsData;
    

    Not used anywhere in the class.

  2. +++ b/core/modules/views/src/ViewsData.php
    @@ -230,7 +231,18 @@ protected function getData() {
    +            $table['table']['provider'] = $module;
    

    We should add this in docs of hook_views_data().

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new1.43 KB
new51.42 KB

Thanks for the review @jibran!

Patch addresses both points in #50.

jibran’s picture

Thanks for the fix it is RTBC for me but I let @dawehner and @damiankloip to have a go at it.

dawehner’s picture

  1. +++ b/core/modules/comment/src/Plugin/views/wizard/Comment.php
    @@ -150,6 +150,7 @@ protected function defaultDisplayOptions() {
    +    $display_options['relationships']['node']['dependencies'] = [];
    
    @@ -159,6 +160,7 @@ protected function defaultDisplayOptions() {
    +    $display_options['fields']['subject']['dependencies'] = [];
    

    Can't we drop those entries now?

  2. +++ b/core/modules/file/src/Plugin/views/wizard/File.php
    @@ -54,6 +54,7 @@ protected function defaultDisplayOptions() {
    +    $display_options['fields']['filename']['dependencies'] = [];
    
    +++ b/core/modules/node/src/Plugin/views/wizard/Node.php
    @@ -138,6 +138,7 @@ protected function defaultDisplayOptions() {
    +    $display_options['fields']['title']['dependencies'] = [];
    
    +++ b/core/modules/node/src/Plugin/views/wizard/NodeRevision.php
    @@ -99,6 +99,7 @@ protected function defaultDisplayOptions() {
    +    $display_options['fields']['changed']['dependencies'] = [];
         $display_options['fields']['changed']['alter']['alter_text'] = FALSE;
    
    @@ -115,6 +116,7 @@ protected function defaultDisplayOptions() {
    +    $display_options['fields']['title']['dependencies'] = [];
    
    +++ b/core/modules/taxonomy/src/Plugin/views/wizard/TaxonomyTerm.php
    @@ -52,6 +52,7 @@ protected function defaultDisplayOptions() {
         $display_options['fields']['name']['label'] = '';
         $display_options['fields']['name']['alter']['alter_text'] = 0;
         $display_options['fields']['name']['alter']['make_link'] = 0;
    diff --git a/core/modules/user/src/Plugin/views/wizard/Users.php b/core/modules/user/src/Plugin/views/wizard/Users.php
    
    diff --git a/core/modules/user/src/Plugin/views/wizard/Users.php b/core/modules/user/src/Plugin/views/wizard/Users.php
    index 127b84b..24b71df 100644
    
    index 127b84b..24b71df 100644
    --- a/core/modules/user/src/Plugin/views/wizard/Users.php
    
    --- a/core/modules/user/src/Plugin/views/wizard/Users.php
    +++ b/core/modules/user/src/Plugin/views/wizard/Users.php
    
    +++ b/core/modules/user/src/Plugin/views/wizard/Users.php
    +++ b/core/modules/user/src/Plugin/views/wizard/Users.php
    @@ -75,6 +75,7 @@ protected function defaultDisplayOptions() {
    
    @@ -75,6 +75,7 @@ protected function defaultDisplayOptions() {
         $display_options['fields']['name']['table'] = 'users_field_data';
         $display_options['fields']['name']['field'] = 'name';
         $display_options['fields']['name']['provider'] = 'user';
    +    $display_options['fields']['name']['dependencies'] = [];
         $display_options['fields']['name']['label'] = '';
         $display_options['fields']['name']['alter']['alter_text'] = 0;
         $display_options['fields']['name']['alter']['make_link'] = 0;
    

    more places ...

  3. +++ b/core/modules/views/src/Plugin/views/PluginBase.php
    index df5de7a..352aaf0 100644
    --- a/core/modules/views/src/Plugin/views/ViewsPluginInterface.php
    
    --- a/core/modules/views/src/Plugin/views/ViewsPluginInterface.php
    +++ b/core/modules/views/src/Plugin/views/ViewsPluginInterface.php
    
    +++ b/core/modules/views/src/Plugin/views/ViewsPluginInterface.php
    @@ -20,14 +20,11 @@
    +  public function getProvider();
    

    Its super confusing that PluginInspectionInterfacedoes not provide getProvider() itself.

  4. +++ b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
    @@ -164,6 +164,18 @@ public function query() {
    +    return [
    +      'module' => [$table_data['table']['provider']],
    +    ];
    

    Wow this mixup between module and provider is super confusing ... Is there an issue to rename module to provider on there?

alexpott’s picture

StatusFileSize
new213.93 KB
new256.71 KB

re #53
1,2. Fixed - also we can remove provider from being saved as well - there's no need for it.
3. I think this is out of scope
4. I don;t think it is a mix up - provider can be "core" or a module - in config dependencies they are always modules and it would not make sense to call a dependency a provider.

This patch has got big because we no longer store dependencies and the provider of all the plugins used by a view.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new255.65 KB
new2.34 KB

4. I don;t think it is a mix up - provider can be "core" or a module - in config dependencies they are always modules and it would not make sense to call a dependency a provider.

The only thing is that its kinda inconvenient to read, anyway yeah we should focus here.

  1. +++ b/core/modules/comment/config/install/views.view.comments_recent.yml
    --- a/core/modules/comment/src/Plugin/views/wizard/Comment.php
    +++ b/core/modules/comment/src/Plugin/views/wizard/Comment.php
    
    +++ b/core/modules/comment/src/Plugin/views/wizard/Comment.php
    +++ b/core/modules/comment/src/Plugin/views/wizard/Comment.php
    @@ -150,6 +150,7 @@ protected function defaultDisplayOptions() {
    
    @@ -150,6 +150,7 @@ protected function defaultDisplayOptions() {
         $display_options['relationships']['node']['required'] = 1;
         $display_options['relationships']['node']['plugin_id'] = 'standard';
         $display_options['relationships']['node']['provider'] = 'views';
    +    $display_options['relationships']['node']['dependencies'] = [];
     
    

    Meh, here is a leftover.

  2. +++ b/core/modules/node/src/Plugin/views/wizard/NodeRevision.php
    @@ -115,6 +114,7 @@ protected function defaultDisplayOptions() {
         $display_options['fields']['title']['provider'] = 'node';
    +    $display_options['fields']['title']['dependencies'] = [];
         $display_options['fields']['title']['label'] = '';
    

    meh2

  3. +++ b/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php
    @@ -20,10 +20,7 @@
    -    $args = array(
    -      '@module' => $this->definition['original_configuration']['provider'],
    -    );
    -    return t('Broken/missing handler (Module: @module) …', $args);
    +    return t('Broken/missing handler');
    
    @@ -61,7 +58,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    -      t('Module: @module', array('@module' => $this->definition['original_configuration']['provider'])),
    +//      t('Module: @module', array('@module' => $this->definition['original_configuration']['provider'])),
    

    This is really sad ...

dawehner’s picture

tim.plunkett’s picture

  1. +++ b/core/modules/field/src/Plugin/views/field/Field.php
    @@ -938,9 +938,11 @@ function field_langcode(EntityInterface $entity) {
    +    return [
    +      'config' => [$this->getFieldStorageConfig()->getConfigDependencyName()]
    +    ];
    

    Random change? Missing trailing comma.

  2. +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
    @@ -908,7 +908,7 @@ public function getHandlers($type) {
    -      foreach ($this->getOption($plural) as $id => $info) {
    +      foreach ((array) $this->getOption($plural) as $id => $info) {
    
    +++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
    @@ -260,9 +275,15 @@ public function getEntityTableInfo() {
    -    foreach ($this->view->relationship as $relationship_id => $relationship) {
    +    foreach ((array) $this->view->relationship as $relationship_id => $relationship) {
    

    Why the added cast?

alexpott’s picture

StatusFileSize
new1.46 KB
new256.72 KB

re #57

  1. Fixed
  2. Added a comment
damiankloip’s picture

Did we really need to do all the yaml changes here too?! :)

alexpott’s picture

re #59 yep these are necessary because provider and dependencies are no longer used.

damiankloip’s picture

Yes but all of this code still works without. It just wouldn't be used. So not entirely necessary. could just be removed when views are updated etc...I just hate patches that get too big! Anyway it's done now.

Also, it is a shame we are removing the useful information for broken handlers...

damiankloip’s picture

Status: Reviewed & tested by the community » Needs work

Did a review, sorry in advance!

  1. +++ b/core/modules/comment/src/Plugin/views/wizard/Comment.php
    @@ -150,6 +150,7 @@ protected function defaultDisplayOptions() {
         $display_options['relationships']['node']['provider'] = 'views';
    +    $display_options['relationships']['node']['dependencies'] = [];
    
    @@ -158,7 +159,6 @@ protected function defaultDisplayOptions() {
    -    $display_options['fields']['subject']['provider'] = 'comment';
    
    +++ b/core/modules/node/src/Plugin/views/wizard/NodeRevision.php
    @@ -115,6 +114,7 @@ protected function defaultDisplayOptions() {
         $display_options['fields']['title']['provider'] = 'node';
    +    $display_options['fields']['title']['dependencies'] = [];
    
    +++ b/core/modules/taxonomy/src/Plugin/views/wizard/TaxonomyTerm.php
    @@ -51,7 +51,6 @@ protected function defaultDisplayOptions() {
    -    $display_options['fields']['name']['provider'] = 'taxonomy';
    

    Some are removed and some are added in wizards. Data added here will make it's way into the configuration for each handler. Isn't that what you want to remove from all the yml files?

  2. +++ b/core/modules/views/src/EntityViewsData.php
    @@ -129,6 +129,7 @@ public function getViewsData() {
    +    $data[$base_table]['table']['provider'] = $this->entityType->getProvider();
    
    @@ -157,10 +158,12 @@ public function getViewsData() {
    +      $data[$data_table]['table']['provider'] = $this->entityType->getProvider();
    ...
    +      $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();
    

    Weren't we adding this somewhere else before, in views_views_data() maybe? The flaw with this approach is that any ViewsData class extending this can easily break things if they forget to add provider. I think before we had it so this is always added to every table. Or did we do this in another patch?

  3. +++ b/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php
    @@ -20,10 +20,7 @@
    +    return t('Broken/missing handler');
    

    We should be able to at least use some of the data from the view to help people work out which handler this might be.

  4. +++ b/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php
    @@ -61,7 +58,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    -      t('Module: @module', array('@module' => $this->definition['original_configuration']['provider'])),
    +//      t('Module: @module', array('@module' => $this->definition['original_configuration']['provider'])),
    

    Seems like we need to do something here then.

  5. +++ b/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php
    @@ -97,4 +94,15 @@ public function broken() {
    +  public function calculateDependencies() {
    +    return array();
    
    +++ b/core/modules/views/src/Plugin/views/PluginBase.php
    @@ -386,8 +387,16 @@ public static function preRenderFlattenData($form) {
    +  public function calculateDependencies() {
    +    return [];
    

    Stick with new or old style?

  6. +++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
    @@ -118,6 +118,21 @@ public function summaryTitle() {
    +    foreach ($this->getEntityTableInfo() as $entity_type => $info) {
    +      if (!empty($info['provider'])) {
    +        $dependencies['module'][] = $info['provider'];
    +      }
    

    This means we essentially add relationship dependencies twice (I know they will get filtered anyway, so no dupes).

  7. +++ b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
    @@ -164,6 +164,18 @@ public function query() {
    +    $table_data = $this->getViewsData()->get($this->definition['base']);
    

    This is the part that is re getting info we already have. Not sure why you were not seeing that data from the query plugin. It does make sense to ask the relationship plugin. If that's the case, maybe the query plugin (or somewhere else) should only care about the base table?

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new7.54 KB
new304.68 KB

Thanks for the review @damiankloip

  1. Fixed
  2. Yep we have code that automatically adds this see ViewsData::getData()
  3. I have improved the information on the options form - BUT we should never get into this situation if the config dependency system is working properly.
  4. See point 3 above
  5. Stuck with the new style
  6. It didn't seem to mean that. In testing without the implementation of calculateDependencies() in the relationship plugin this info was not being added (by the query plugin)
  7. See point 6 above
damiankloip’s picture

+++ b/core/modules/views/src/EntityViewsData.php
@@ -129,6 +129,7 @@ public function getViewsData() {
+    $data[$base_table]['table']['provider'] = $this->entityType->getProvider();

@@ -157,10 +158,12 @@ public function getViewsData() {
+      $data[$data_table]['table']['provider'] = $this->entityType->getProvider();
...
+      $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();

2. Oh yes, I added that code :).. In #22.

What I mean adding these here is not necessary.

It didn't seem to mean that. In testing without the implementation of calculateDependencies() in the relationship plugin this info was not being added (by the query plugin)

I think what is happening is that the view is not built at this time (ViewExecutable::build() > ViewExecutable::_build('relationship')) So $view->relationship would always be empty at that point. So e.g. after a view has been executed it would be there. So if we did want to use this we could just build() the view here? Using the relationships directly is ok though I think. I just think we should do it in both places like that maybe. what do you think?

alexpott’s picture

I had a look at calling build() - this turns out to be quite a big problem for ViewsUnitTestBase and ViewsTestBase. Basically we have a problem with the fact that these abstract classes create views before the concrete test has a had a chance to set up all the necessary dependencies of the views - eg comment fields etc. I think we should handle this is a followup since the patch does what it necessary to unblock the configuration issues and this will involve changing many ViewsUnitTestBase and ViewsTestBase tests. I've created to #2371751: Build the view executable in View::calculateDependencies() to explore this.

damiankloip’s picture

Yeah. It does quite some stuff. That's for sure!

So just remove those provider keys as per my first comment? And I think we're done.

alexpott’s picture

re #66 these are needed because this data is loaded through the views module - so it makes the provider of the node table views if I remove them. So I think we are done here.

damiankloip’s picture

Status: Needs review » Reviewed & tested by the community

OK. Yes. I remember that being an issue now! We can follow up that. Not a problem of this patch.

In a nutshell, it's just too fragile.

catch’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs issue summary update

Sorry folks this needs a better issue summary.

+ // Figure out what base table this relationship brings to the party and add
+ // a dependency on its provider.

Not sure about 'brings to the party'.

In general is it really the case that while we're removing the provider key from the YAML we don't get any additional dependencies in the default views from these changes at all? i.e. what we end up in the YAML is just the removal of duplicate information that happens to be already covered? Assuming this wouldn't be the case with a more complex default view in core.

alexpott’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs issue summary update

The dependencies of the default views are recalculated on config install so in some ways what is in the config/install directory does not matter. I think we should revisit all the default configuration entities before release and re-export so that the yaml matches what would be exported (without the UUID of course).

alexpott’s picture

Issue summary: View changes
tstoeckler’s picture

Status: Reviewed & tested by the community » Needs work
diff --git a/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php b/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php
index c2abc3b..2462eaf 100644
--- a/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php
+++ b/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php
@@ -18,22 +18,16 @@ class BootstrapConfigStorageFactory {
   /**
    * Returns a configuration storage implementation.
    *
-   * @param $class_loader
-   *   The class loader. Normally Composer's ClassLoader, as included by the
-   *   front controller, but may also be decorated; e.g.,
-   *   \Symfony\Component\ClassLoader\ApcClassLoader.
-   *
    * @return \Drupal\Core\Config\StorageInterface
    *   A configuration storage implementation.
    */
-  public static function get($class_loader = NULL) {
+  public static function get() {
     $bootstrap_config_storage = Settings::get('bootstrap_config_storage');
-    $storage_backend = FALSE;
     if (!empty($bootstrap_config_storage) && is_callable($bootstrap_config_storage)) {
-      $storage_backend = call_user_func($bootstrap_config_storage, $class_loader);
+      return call_user_func($bootstrap_config_storage);
     }
     // Fallback to the DatabaseStorage.
-    return $storage_backend ?: self::getDatabaseStorage();
+    return self::getDatabaseStorage();
   }
 
   /**

Faulty merge.

Edit: The DrupalKernel hunk as well.

Edit 2: In fact this patch simply seems to be generated without having merge 8.0.x first, there's a lot of reverts of recent patches in there.

alexpott’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new260.16 KB

Rebased - how embarrassing :(

wim leers’s picture

relationship plugins now add dependencies based on the base table they bring to the party!

YAY!!!

260.16 KB

GASP!

I don't want to hold up this patch, but I was always under the impression that this patch would bring support for config entity dependencies as well? I.e. if a view lists entities in a certain view mode (the front page lists entities in 'teaser' view mode) it should depend on the view mode entities in question. If it filters to article nodes, it should depend on the article node type config entity. And so on. I suppose that is now out of scope? Or perhaps I'm mistaken and that's a different issue?

It's essential that we can figure out those config entity dependencies as well, because we'll need to make sure that cached views are invalidated when any of those config entities change. It is also essential to use more granular entity list cache tags in the future (i.e. if we know we're only listing 'Blog' nodes, then we can use a Blog node-specific list cache tag so that we invalidate as rarely as possible).


Manually tested, works as expected!


  1. +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
    @@ -281,10 +251,6 @@ display:
    -          dependencies:
    -            module:
    -              - views
    -              - views
    

    Hah!

  2. +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
    @@ -352,11 +315,6 @@ display:
    -          dependencies:
    -            module:
    -              - views
    -              - views
    -              - views
    

    Hahaha!

  3. +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
    @@ -200,12 +181,6 @@ display:
    -          dependencies:
    -            module:
    -              - views
    -              - views
    -              - views
    -              - views
    

    This keeps getting better.

  4. +++ b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
    @@ -164,6 +164,18 @@ public function query() {
    +    // Figure out what base table this relationship brings to the party and add
    +    // a dependency on its provider.
    

    Like catch said, this comment should probably be more … sec. :)

alexpott’s picture

StatusFileSize
new820 bytes
new260.12 KB
  1. :)
  2. :) :)
  3. :) :) :)
  4. Fixed

Created #2372855: Add content & config entity dependencies to views to handle the additional dependencies from using entity displays.

dawehner’s picture

+1.1

wim leers’s picture

RTBC+1

tstoeckler’s picture

-          provider: views
-        uid:
-          admin_label: ''
-          field: uid
-          group_type: group
-          id: uid
-          label: author
-          relationship: node
-          required: '0'
-          table: node_field_data
-          plugin_id: standard
-          provider: views

Is this hunk intentional?

alexpott’s picture

#78 yes - the test view was completely invalid. And this test view exists purely for the test and now it tested.

tstoeckler’s picture

OK, awesome. Thanks!

catch’s picture

Status: Reviewed & tested by the community » Fixed

Looks great now. Committed/pushed to 8.0.x, thanks!

  • catch committed 29817e4 on 8.0.x
    Issue #2267453 by alexpott, dawehner, damiankloip: Fixed Views plugins...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.