Updated: Comment #N
Problem/Motivation
Since Drupal 7, there is a hook_admin_paths() to define which menu links/routes are "admin" and which aren't. We use that logic for various things, including selecting the active theme and soon for route preloading. But that's silly to have a hook for, as it moves the definition of admin-path far away from the actual definition of the routes themselves.
Proposed resolution
Replace the hook with a boolean property on the route definition.
my.route:
options:
_admin_route: TRUE
...
Remaining tasks
Get the patch passing and committed.
One could argue that we shouldn't have yet-another-boolean-toggle and should instead define some way of letting routes classify themselves arbitrarily (to "admin", "front-end", "rest only", or whatever), but that requires more thought. @Crell is OK with proceeding as-is for now. (Adding route tagging/categories is probably an 8.1-safe thing to do.)
User interface changes
None.
API changes
hook_admin_paths() goes away, and is replaced by a property on the route definition.
Comment | File | Size | Author |
---|---|---|---|
#56 | interdiff.txt | 3.33 KB | tim.plunkett |
#56 | hook_admin_paths-1316692-56.patch | 36.31 KB | tim.plunkett |
Comments
Comment #1
TR CreditAttribution: TR commentedI'm willing to write a patch to remove hook_admin_paths() and hook_admin_paths_alter() - I'd just like some feedback from the community first about whether I'm way off base here or not.
Comment #2
westie CreditAttribution: westie commentedSeems to make a lot of sense to me. Does anyone know if there is a technical reason the functions were spilt?
Comment #3
gagarine CreditAttribution: gagarine commentedThis make lot more sens than the hook_admin_paths. With hook_admin_paths I can find a way to create set admin theme to false only for a content type on edit...
Comment #4
Damien Tournoud CreditAttribution: Damien Tournoud commentedThat sounds good, but we currently do *not* save arbitrary metadata attached to menu routers. I would definitely support doing so.
Comment #5
RobLoachWhat determines whether a path is an "admin path" though? I'd say that's up to the menu's
user_access()
callback to decide. We should get rid of the hook entirely and use the menu'suser_access()
context.Comment #6
gagarine CreditAttribution: gagarine commentedadmin path mean you use the admin theme it have nothing to do with access. So what about using a theme key.
So in the theme key you can chose a theme or use "admin" to chose the admin theme and "default" for the default one (or just not give the key)
Comment #7
sunRelated issue: #1032700-27: Add caching to hook_admin_paths()
In D8, we should convert these declarations into properties on routes, and only keep the alter hook (or equivalent) for dynamic or page/route-specific adjustments.
Comment #8
nod_For info
path_is_admin()
is now used by the back to site button which replaces the overlay. We rely on it to know if the current page is an admin page or not and display the button appropriately. As long as there is a way to know ifcurrent_path()
is admin or not we're cool.Comment #9
dawehnerI am not really sure how to deal with user/%/translations taxonomy_term/%/translations ... it feels like we might should just set it on all content/config translation routes.
Comment #11
dawehnerI cannot even remember on how many issues I added that bit.
Comment #13
tim.plunkettThe last patch seems like a good direction to go in. The issue summary is way out of date though.
Comment #14
Crell CreditAttribution: Crell commentedI've updated the summary based on the latest patch. This is entirely sensible to me.
Comment #15
dawehnerRerolled.
Comment #17
tim.plunkettI fixed up a couple things...
It'd be nice to have the internals of path_is_admin moved somewhere, like AdminContext::isAdminPath($path), but I didn't want to make AdminContext dependent on the router...
Also we should probably go ahead and make an interface for AdminContext...
Comment #19
tim.plunkettThe new d.o comment form is awesome!
Comment #20
tim.plunkettExcept the part where it misattributes stuff. #19 and #20 are tim.plunkett.
Comment #22
tim.plunkettOkay, had to add code to handle the node setting.
Comment #25
tim.plunkettWrong interface!
Comment #27
dawehner25: admin-paths-1316692-25.patch queued for re-testing.
Comment #29
tim.plunkettIf LanguageRequestSubscriber runs before the router, it doesn't have the route object available, and then LanguageNegotiationUserAdmin will break when it calls isAdminRoute().
I'm not sure if there are other service priorities that need to be adjusted, or if this makes a loop between the router and language, but we'll find out soon.
Comment #30
tim.plunkettComment #31
dawehnerIs that a leftover?
Comment #33
tim.plunkettThis is unfortunate, but it is only needed because the language *has* to come before the RouterListener. I think we're better off special casing the language here than making the AdminContext class dependent on the router.
Comment #36
tim.plunkett33: admin-paths-1316692-33.patch queued for re-testing.
Comment #37
dawehnerWe seriously cannot run the router twice. Do we know whether we actually need to be able to set the language like that?
Comment #38
tim.plunkettTrying this just for fun. I think I may have misunderstood @dawehner in IRC, but let's see what fails.
Comment #40
dawehnerJust an idea: You could try to call LanguageNegotiatorInterface::reset() on the second running listener, this might fix some of the negotiation.
Comment #41
tim.plunkettI want to take a look at this again soon.
Comment #42
tim.plunkettReroll of #33, just to get back to passing.
Comment #43
tim.plunkettThese are the parts @dawehner objects to, and I have no idea how to work around.
Comment #44
Crell CreditAttribution: Crell commentedThis is a service. Pass in the route. Don't provide a stateful, state-changing default. That way lies madness.
Why? Does this not force people to implement it?
Hrm. This makes me wonder if we really do need a route_type or something instead of multiple booleans. I won't block this issue on that question but I think we'll be there soon.
I agree this feels very wrong. The problem is that this class is depending on where in the request it's called. That suggests the problem is elsewhere; eg, why is this class being called from unknown places? Should it be different classes then?
Comment #45
David_Rothstein CreditAttribution: David_Rothstein commentedThe original rationale for a hook was performance (https://drupal.org/node/517688?page=1#comment-2171240).
Does the patch here avoid that by removing the path_get_admin_paths() functionality altogether? ... So would something like Overlay be impossible in Drupal 8?
Comment #46
dawehnerNo, it uses routes instead of paths. For admin paths it sets a flag during compile-time of the routes, so there is no performance needed during runtime.
Comment #47
Crell CreditAttribution: Crell commentedComment #48
tim.plunkett#44.1
Yes, it's a service now, but it probably doesn't need to be. I think it could actually build on top of #2103301: Add a helper class to introspect a given request nicely...
#44.2
RouteSubscriberBase has devolved into a base class that is only useful for those wanting to alter routes. But that said, I don't know why @dawehner made that change here.
#44.3
In all of core and contrib, this is the only other very common pattern (did the user choose to use the admin theme for content creation).
And classes like this will all boil it down to _admin_route anyway.
#44.4
The places are not unknown. In fact, I state right here where the problem is:
If called from an event subscriber
LanguageNegotiationUserAdmin determines what language to use, which is required by the URL generator any other early services (think /de/admin/content), and yet LanguageNegotiationUserAdmin also needs to know if this is an admin path.
So what do we do? How do we break that circle?
This is just a reroll of #42 to keep it fresh, no changes.
Comment #49
catch@David the reason there's no longer a performance penalty is because we already have that penalty - routes have to be loaded to generate internal URLs, which is exactly what the hook was avoiding in 7.x. #2058845: Pre-load non-admin routes and #1805054: Cache localized, access filtered, URL resolved, and rendered menu trees should claw some of that back though.
Comment #50
David_Rothstein CreditAttribution: David_Rothstein commentedAh, thanks, that's what I was missing. It looks like even calling url('some/path') now loads the route...
So assuming that's there to stay, I agree there's no performance hit on top of it here, nor any need for path_get_admin_paths() to stay (which would presumably be a big performance hit if it did because it would need to load, well, everything)... modules which want to identify every admin path link on the current page should have other ways to do that going forward if the route is already available when the link is generated.
Comment #51
dawehnerYeah, in case we get the other issue in we can easily reiterate.
Comment #53
tim.plunkettPatch context conflict with #2219891: Duplicate declaration of hook_menu_link_defaults(), no changes.
Comment #54
dawehnerback to RTBC
Comment #55
catchIt's a bit minor but could this use something like _node_operation_route instead of _node_admin_route? I didn't immediately figure out why we need both _admin_route and _node_admin_route. Cannot think of another way to do it that's better than this, but something without 'admin' would make it clearer that this might or might not be treated as administrative depending on the site.
Comment #56
tim.plunkettFine by me. And _node_operation_route is only converted to _admin_route when configured to, otherwise its non-admin. Makes sense.
Comment #57
dawehner+1 for the better name.
Comment #59
catchI committed/pushed this to 8.x, then ten seconds later remembered to look for a draft change notice, which this does not have. So doing old style I guess..
Comment #60
znerol CreditAttribution: znerol commentedNew code should use the
request_stack
service instead of therequest
service. Can we have a (trivial) follow-up on that?Comment #61
andypostalso field ui subscriber does not set admin option
Comment #62
kim.pepperChange record created [#2224207]
Comment #63
dawehner@znerol
You are totally right here. You can create one and tag it as "Quickfix".
@kim
It would be actually also be great if your example could include an addition to menu links instead of just the removal part of it.
Comment #64
kim.pepper@dawehner Done!
Comment #65
swentel CreditAttribution: swentel commentedWe forgot admin/content and all manage fields / form / display paths, they don't show up in the admin screen.
Comment #66
andypostFiled follow-up for that #2224553: Add _admin_route for field manager and admin/content
Comment #67
kfritscheNew follow-up for translations paths #2225577: Add _admin_route for translations
Comment #68
znerol CreditAttribution: znerol commentedFollow up for the
request
torequest_stack
conversion: #2225539: Use request stack in admin context service