Needs work
Project:
Drupal core
Version:
main
Component:
plugin system
Priority:
Normal
Category:
Plan
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
25 Oct 2017 at 00:08 UTC
Updated:
25 Oct 2018 at 22:52 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
eclipsegc commentedLet's start with a simple patch and see what goes wrong.
Eclipse
Comment #3
eclipsegc commentedTestbot, show me what I broke!
Comment #5
dawehnerI'm curious, don't we need to add the cacheability metadata always?
Comment #6
eclipsegc commentedFor what? The lack of a context doesn't represent data that we need to cache. You don't visit /user/1 and need to cache "nope, no node here". The system cache what is where, not what isn't where. This isn't to be confused with "yes there's a node here, but you don't have access". In that case, of course we'd need to cache that there was a node there and that our response is dependent upon who has access to the node. But these are different things.
As an example of what I'm saying, there's not a context provider (yet) that accounts for all possible entities. If there were, it'd not need to inform Drupal that there were no terms/users/comments/etc on a given page, it need only inform when there ARE entities. (And I intend on writing that code, so yeah we should establish this quickly)
Eclipse
Comment #7
wim leers@dawehner is right, you'd still need the
routecache context. Because the value returned bygetRuntimeContexts()still depends on the route that was matched. Since that return value (and the cacheability of it) affect Condition plugins, which are used by block visibility, which is central in block access checking, and therefore hugely important in caching of blocks (which cached variant of a block to retrieve, and which cached partial page to retrieve from Dynamic Page Cache), cacheability metadata even for the case of "nope, no node" at/user/1(or/foobarfor that matter) is essential.You've asked basically the same question at #2375695-69: Condition plugins should provide cache contexts AND cacheability metadata needs to be exposed.4, in June 2015. @Berdir answered it in #70.4. This patch is forgetting the discussion that was had there, and is effectively reverting that change (which was a critical bugfix).
NodeRouteContextis indeed returning aContextobject, but it's not erroneous, it's correct AFAICT: it's necessary to ensure that everything consuming those contexts (i.e. using them as inputs) can be cached correctly. The value that is associated with thatContextobject isNULL. This is also whyContextInterface::hasContextValue()was added in #2513244: ContextHandler incorrectly checks required/optional contexts of plugins, which was a blocker for #2375695.Is it possible you forgot about that? 😳 I feel like I'm missing something…
Comment #8
eclipsegc commentedYeah... this is a difference between how core and contrib generally want to make use of contexts. Since the core block system is horribly naive, this sort of solution is fundamentally broken for contrib, which means they have to know that, understand that, and manually disregard the node context from core. We'll have to circle back around to this when we stop misusing blocks and contexts in this way, so I guess I'll postpone it till D9 for the time being.
So, to reiterate, yeah ok, but it needs to change.
Eclipse
Comment #9
wim leersPlease act more constructively. Simply postponing this to 9.x is not going to solve this.
Especially because Drupal 9 is not allowed to break backwards compatibility — we can only drop deprecated APIs. So we should already look into any potential deprecations here.
#2375695: Condition plugins should provide cache contexts AND cacheability metadata needs to be exposed was a critical bugfix to ensure that things using the context system would still be cacheable. #8 is saying as far as I can tell that we should give up on cacheability to get back the DX you imagined. (Today's
if ($result['node']->hasContextValue()) {…}vsif (!empty($result)) {…}which you prefer.) But in either case, the calling code needs to know how to interpret the result ofgetRuntimeContexts(). So I'm not sure the difference is that big?An initial idea/suggestion: what if we'd add a
class NoContext implements ContextInterface {…}? ThenNodeRouteContextcouldreturn new NoContext(['route']). That'd make theNodeRouteContext:getRuntimeContexts()code clearer. It'd still require similar calling code though — which makes sense: we can't break BC.Comment #10
eclipsegc commented@wim,
Not trying to be unconstructive, an no, I don't "prefer" the boolean approach. Yes I did 3 years ago before I understood what you'd built and the nuances involved, but I generally understand what you've built, and I have no desire to abandon it. That being said, let's actually address my comment since it was instructive of my position:
This isn't an opinion, it's absolutely true, and this issue we are discussing is a perfect example of why and how. Block placement outside of core collects the actual contexts on a page, and then uses that list of contexts to inform itself about what blocks (and conditions) are even viable in a given environment. If there's no node, there won't be node context consuming blocks. The same is true of conditions. In this case, there's no need to store the "negative" data that core needs.
So why does core need this?
My fatal flaw in filing this issue was that I'd gotten used to how contrib thinks. I got a bit ahead of myself on this issue. The simple fact of the matter is that Core's page block layout tool doesn't ever try to assert when and where contexts are ACTUALLY available. A point I forgot over the last 3 years. So our NodeRouteContext is instructive in this regard. It says "well, a user might want to place a block but only show it when a node is available and that node is of type page". Thus we're into this negative logic.
Unfortunately, even though I appreciate your suggested solution Wim, I don't think it's workable. The returned context would still need to identify as a node context in order to be passed into the condition/block that uses it, and it's only from the conditions or blocks that the cache tags/context/max-ages are retrieved.
I'm super happy to discuss viable next steps if you still feel like there might be one, but in my mind I just need to do the long-hard work of replacing our core block placement tools with viable solutions that people want to adopt so that we can deprecate the entire block module's way of block placement. In the mean time, I'll simply manually remove this context from block placement tools with better insight into their actual present contexts.
Thanks!
Eclipse
Comment #11
eclipsegc commentedAlso, I didn't intend that move to D9 as a "screw this" or anything. I was just trying to acknowledge that you were correct and I didn't have the time to work on a bigger solution right now since that's what it'd take. That's all. Sorry if I caused any offense.
Eclipse
Comment #12
wim leersThis is not true. We still need to know that this "no context" result varies by the
routecache context, i.e. that if a different route were requested, that it may not be a "no context" result, but in fact there may be a context!That's totally possible 🙂 It was just an initial suggestion to get the discussion going.
Well, that is going to have to happen in a way that does not break BC. So postponing this to D9 is not actually going to help, because all that D9 is going to be allowed to do is remove things that are
@deprecated. See https://dri.es/making-drupal-upgrades-easy-forever.In other words: we'll have to start doing the work of a better system during the Drupal 8 cycle anyway. So there's no point in waiting :)
This is definitely (VERY!) hard for Drupal core developers, but it makes things much easier for the end users of Drupal of course. I've been doing this for the REST module for the past ~1.5 year now, and in that time, we've accumulated >2000 LoC that will be deleted in Drupal 9. I last updated that "remove BC layers" patch a few days ago: #2893804-6: Remove rest.module BC layers.
I'm sorry, I'm not familiar enough with those tools and these APIs to understand this 100%. Does this mean you are you going to start relying on the API that #2513244: ContextHandler incorrectly checks required/optional contexts of plugins introduced, or that you're going to work around it by limiting what the user is allowed to do?
So, why not use this issue to do the analysis of what's broken in the current system, and come up with a step-by-step plan that would not break BC that would get us to a place where everything is working? We would be able to mark existing APIs
@deprecated, and they'd disappear in 9.0.0.It sounds like it'll be impossible to have everything work as nicely and simply as we'd want, but that is the cost we have to pay for not breaking BC. But we can make plugins opt in to improved APIs one-by-one, and then offer a better user experience for those, perhaps. That'd be an incentive to update to the new APIs. Plus, there's the
trigger_error('Some message saying why you should not be using this anymore but the other thing instead', E_USER_DEPRECATED), which will show up in A) test runs, B) people's actual dev environments, which is another incentive.In any case, there's nothing stopping us from looking into what the problems are and articulating a plan to fix it for 9. I currently don't fully understand what the problems are. You're the main Context component maintainer AFAIK, so you have the most complete insight.
P.S.: why isn't there a Context component in MAINTAINERS.txt or on d.o?
Comment #13
eclipsegc commentedBecause Context is part of plugins, so in that regard, Tim Plunkett and I are the maintainers of it because plugins. :-D
Ok, that sounds like "Change the IS & title drastically and turn this into a META so you can solve the stuff that's driving this issue." which seems like the next obvious step to take, so I'll begin that work. Thanks for the input!
Eclipse
Comment #15
andres.torres commentedWhen creating an image field for a simple contentype (node), create a new user role, non admin, assign the proper permissions to the role so it can create/edit/delete, when creating a new node as this new role, the issue is also present:
The website encountered an unexpected error. Please try again later.
Error: Call to a member function getType() on null in
The Alt text is not available for non-admins, see screenshot for reference, so it triggers the error described.
Comment #16
andres.torres commentedPlease ignore my last comment since it was a bad implementation of a hook causing the issue.
Comment #18
andypostJust workaround like #2921859: "Call to a member function getType() on null" when the NodeType condition plugin gets an empty context but with route cache context
Comment #20
tim.plunkettIsn't that the same patch from #2?
Anyway, retitling.