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
| Comment | File | Size | Author |
|---|---|---|---|
| #75 | 2267453-2.75.patch | 260.12 KB | alexpott |
| #75 | 73-75-interdiff.txt | 820 bytes | alexpott |
| #73 | 2267453-2.73.patch | 260.16 KB | alexpott |
| #63 | 2267453-2.63.patch | 304.68 KB | alexpott |
| #63 | 58-63-interdiff.txt | 7.54 KB | alexpott |
Comments
Comment #1
tim.plunkettI'll work on this. I think we'll want the other issue to go in first.
Comment #2
damiankloip commentedThat 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.
Comment #3
damiankloip commentedHere 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.
Comment #4
gábor hojtsy#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.
Comment #5
catchI 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.
Comment #6
tim.plunkettComment #7
dawehnerSome more work.
Comment #8
dawehnerA little bit more work.
Comment #9
damiankloip commentedThe 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.
Comment #11
dawehner@damiankloip
Ah I see. I wonder whether we have to split these dependencies then?
Comment #12
damiankloip commentedYes, that is the one million dollar question :)
Comment #13
damiankloip commented.
Comment #14
damiankloip commentedLet's start with a reroll.
Comment #15
damiankloip commentedComment #17
damiankloip commentedLet'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.
Comment #18
damiankloip commentedComment #19
dawehner@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?
Comment #20
damiankloip commentedYes. We sure can!
Comment #21
damiankloip commented.
Comment #22
damiankloip commentedHere 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.
Comment #23
damiankloip commentedSelf review/observations:
We can prob remove this now if we delegate table responsibility to the query plugin?
This looks really simple now if getEntityTableInfo has what we need.
Note to self: Need to move the entity type dependency outside that conditional.
If we add this to the getEntityTableInfo() method, we are already getting similar data. So can be easily used in getDependencies
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?
Comment #24
wim leersApologies if I miss the mark on some things in my review. I probably need a walkthrough of the patch to fully grok it.
Missing comment:
Add (inherit) the plugin's dependencies.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?If that's possible, then
Nice! :)
Extreme nitpick: strange code formatting.
We probably don't want these.
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?
Comment #25
damiankloip commentedreroll and addressed a few small points.
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.
Comment #26
catchComment #27
dawehnerDo 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?
Yeah!
Yeah just remove that todo, noone will see it and we don't really like honest todos.
A new issue to use new Type[] on there would be cool for all those handler types.
Comment #28
mgiffordComment #29
dawehner+1 for decoupling it!
Should we also move that code into the generic EntityViewsData implementation somehow?
Comment #30
damiankloip commentedHmm. 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?
Comment #31
dawehnerCan't we take the provider the from entity type definition and be done?
Comment #32
dawehnerLet's first sort out the storage we use, #2356181: Unify the storage of argument default/validator/summary plugins. will allow us to do that.
Let's add another follow up
Some tiny work here and there.
Comment #34
dawehnerLet's fix the failures ...
Comment #36
dawehnerSo yeah I would prefer the casting here over the default value of the
ViewExecutableas we might want to distinct betweenno relationship and no initialized relationships.
Comment #37
mgiffordIn 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?
Comment #38
damiankloip commentedYou 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
Comment #39
damiankloip commentedSorry 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.
Comment #41
damiankloip commentedThose failures were expected. Will fix them in the next patch iteration.
Comment #42
alexpottBringing 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\ViewTestbecause setting up the dependencies to test under PHPUnit is just not worth it.Comment #44
dawehnerWhat?!
Comment #45
alexpottre #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.
Comment #46
alexpottrelationship plugins now add dependencies based on the base table they bring to the party!
Comment #47
alexpottrenamed 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\FieldComment #48
alexpottNow 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.
Comment #49
alexpottOpened #2368767: Implement calculateDependencies() in ArgumentPluginBase to get dependencies from validator and default plugins to handle argument validator/default plugins. Patch attached fixes the @todo.
Comment #50
jibranThank you for the nice work on the patch @alexpott. I think this patch is almost ready. Just two minor issues.
Not used anywhere in the class.
We should add this in docs of hook_views_data().
Comment #51
alexpottThanks for the review @jibran!
Patch addresses both points in #50.
Comment #52
jibranThanks for the fix it is RTBC for me but I let @dawehner and @damiankloip to have a go at it.
Comment #53
dawehnerCan't we drop those entries now?
more places ...
Its super confusing that
PluginInspectionInterfacedoes not providegetProvider()itself.Wow this mixup between module and provider is super confusing ... Is there an issue to rename module to provider on there?
Comment #54
alexpottre #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.
Comment #55
dawehnerThe only thing is that its kinda inconvenient to read, anyway yeah we should focus here.
Meh, here is a leftover.
meh2
This is really sad ...
Comment #56
dawehnerHere is a follow up
Comment #57
tim.plunkettRandom change? Missing trailing comma.
Why the added cast?
Comment #58
alexpottre #57
Comment #59
damiankloip commentedDid we really need to do all the yaml changes here too?! :)
Comment #60
alexpottre #59 yep these are necessary because provider and dependencies are no longer used.
Comment #61
damiankloip commentedYes 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...
Comment #62
damiankloip commentedDid a review, sorry in advance!
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?
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?
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.
Seems like we need to do something here then.
Stick with new or old style?
This means we essentially add relationship dependencies twice (I know they will get filtered anyway, so no dupes).
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?
Comment #63
alexpottThanks for the review @damiankloip
Comment #64
damiankloip commented2. Oh yes, I added that code :).. In #22.
What I mean adding these here is not necessary.
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?
Comment #65
alexpottI 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.
Comment #66
damiankloip commentedYeah. 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.
Comment #67
alexpottre #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.
Comment #68
damiankloip commentedOK. 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.
Comment #69
catchSorry folks this needs a better issue summary.
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.
Comment #70
alexpottThe 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).
Comment #71
alexpottComment #72
tstoecklerFaulty merge.
Edit: The
DrupalKernelhunk 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.
Comment #73
alexpottRebased - how embarrassing :(
Comment #74
wim leersYAY!!!
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!
Hah!
Hahaha!
This keeps getting better.
Like catch said, this comment should probably be more … sec. :)
Comment #75
alexpottCreated #2372855: Add content & config entity dependencies to views to handle the additional dependencies from using entity displays.
Comment #76
dawehner+1.1
Comment #77
wim leersRTBC+1
Comment #78
tstoecklerIs this hunk intentional?
Comment #79
alexpott#78 yes - the test view was completely invalid. And this test view exists purely for the test and now it tested.
Comment #80
tstoecklerOK, awesome. Thanks!
Comment #81
catchLooks great now. Committed/pushed to 8.0.x, thanks!