Suggested commit message
Issue #2301273 by pwolanin, dawehner, Wim Leers, effulgentsia, joelpittet, larowlan, YesCT, kgoel: MenuLinkNG part2 (no UI or conversions): MenuLinkTree API and unit tests.
Problem/Motivation
This is a follow-up to #2301239: MenuLinkNG part1 (no UI or conversions): plugins (static + MenuLinkContent) + MenuLinkManager + MenuTreeStorage top add the next step of code from #2256521: [META] New plan, Phase 2: Implement menu links as plugins, including static admin links and views, and custom links with menu_link_content entity, all managed via menu_ui module
Proposed resolution
Adds 4 more services and supporting classes that use the code added in step1:
+ menu.link_tree:
+ menu.default_tree_manipulators:
+ menu.active_trail:
+ menu.parent_form_selector:
The main addition is MenuLinkTreeInterface and the MenuLinkTree implementation of that interface for the menu.link_tree service.
The menu.active_trail and menu.parent_form_selector services are split out so that they can be replaced on sites that need to customize those portions of the menu link system. In particular, the latter menu.parent_form_selector is where you would e.g. substitute a hierarchical select widget instead of a simple select form element.
Remaining tasks
final review and commit
User interface changes
None
API changes
Adds MenuLinkTree API and unit tests.
Original report by @effulgentsia
Next chunk after #2301239: MenuLinkNG part1 (no UI or conversions): plugins (static + MenuLinkContent) + MenuLinkManager + MenuTreeStorage.
The "-do-not-test" patch does not include the stuff from #2301239: MenuLinkNG part1 (no UI or conversions): plugins (static + MenuLinkContent) + MenuLinkManager + MenuTreeStorage. The "-combined" patch does.
Comment | File | Size | Author |
---|---|---|---|
#30 | 2301273-30.patch | 71.48 KB | Wim Leers |
Comments
Comment #1
effulgentsia CreditAttribution: effulgentsia commentedComment #2
dawehnerWow, what a heroic effort!
Just observations
I really love how this class collects a bunch of helper methods! Nice name!
I wonder whether we could give a one-liner how the default implementation looks like? Just a quick summary
Typo: ruote, you probably didn't worked enough of routes, yet.
It should also return NULL if there is no matching menu link, right?
This one is not used in this class. This is also nice in terms of separation of concerns, because the tree service should not assume anything about the storage. No, you don't need to inject a service just to use "overrides" in a comment ;)
oh nice!
Should be MenuLinkTreeElement instead of interface, right?
<3
Let's merge the two docblocks, this looks odd.
Missing docs, just a note
Just in case someone wants to fix that t() call
... docs
just in case: the new phpunit test "standard" recommends to not add @group Drupal anymore
I love those kind of comments, really helpful!
OH I see the start of the Hundred Years' War
Comment #3
YesCT CreditAttribution: YesCT commentedpart 1 is close. starting on this.
this do not test patch is an updated just diff to part 1 that is in #2301239-34: MenuLinkNG part1 (no UI or conversions): plugins (static + MenuLinkContent) + MenuLinkManager + MenuTreeStorage
menu-2256521-MenuLinkTree-review-3-do-not-test.patch is just part 2.
does not include improvements mentioned in #2
Comment #4
dawehnerA bit:
Do we need an interface? The access especially could be potentially needed to be swapped out?
i wonder whether we should rather move this detail into the class. the trail could be also decided on other logic and not go back to the root of the tree.
missing dot
I wonder whether this is the right layer where the preloading is done.
... Needs docs updates. It should also describe the difference between MenuLinkManager::createInstance and self::createInstaces()
it should clarify what the array is. maybe a list of MenuLinkInterface[]?
NULL means that the access has not been determined yet. I guess we should document that.
should be static::load
finds
Should be absolute with the namespace.
Comment #5
dawehnerWe should convert it to use the new annotation based tests.
Don't we use "//" for all inline comments?
remove @group Drupal
is the tree an array of some objects?
no need anymore
doc changes needed
It is odd that we don't set the key 0. Would it be possible to substract 1 to all of them?
This is odd. Should this function maybe return the tree?
remove
remove
Some improvements for the docs would be cool.
no need for this additional parenthesis
needs a one liner
remove
OH I am a bit confused about that method name. Would childCount() make more sense?
remove
Comment #6
dawehnernope, this is wrong. probably a merge error.
why this?
at least some verb would be cool for this methdo name, what about setTopLevelOnly?
Comment #7
kgoel CreditAttribution: kgoel commentedQuestion about getParentSelectOptions - It is marked deprecated in MenuParentFormSelectorinterface.php so i am not sure why are we using deprecated method in the patch.
Comment #8
kgoel CreditAttribution: kgoel commentedI am not sure why are we using @codeCovergaeIgnore to ignore the test coverage on setMaxDepth function.
Comment #9
kgoel CreditAttribution: kgoel commentedI am working on part 2 based on dawehner reviews. Peter is working on rebasing the branch against head so I need to wait for him to finish so I can clone the repo and continue to work. I am going to start work again tomorrow on this issue.
Comment #10
dawehnerA couple of more reviews …
getInfo() and @group Drupal can be removed
The same …
Needs a one-liner.
getINfo and @group Drupal
We should check with ->with() that the expected route name is passed into the loadLinksByRoute method.
On top of that the test could be simplified a bit by using a RouteMatch object instead of a CurrentRouteMatch, so we would not
have to pass along the request stack and the request.
getInfo()
Missing dot
One level too much indentation
Needs @group + removal of getInfo()
Dots
Gets ...
Should use (optional)
I guess we wanted people to better use parentSelectElement instead(). We should write that down here.
(optional)
(optional)
I guess we want rather static::transform() given that this is more how our codestyle looks like, though this could be discussed
and added to PSR-5
This method needs verbs in the one-liner.
Let's use an absolute path, to make xjm's life easier.
I wonder whether it is worth to try out 'static $element' instead. Otherwise the adaptability of this class could be more difficult
We don't really have to check is_callable, ... the controller resolver returns just the callable if it is already one.
Maybe it is worth to mention that loadLinksByRoute() already sorts by depth, weight and ID, so it is
not that simple ...
Comment #11
Wim Leers#2: Glad to see you like 6. and 8. so much :)
#4.1: No: a menu link tree manipulator is just a callback that accepts a menu link tree and returns the manipulated menu link tree. This service just contains the default manipulators. So when you'd want to use a different access check manipulator (which is indeed utterly essential), you'd change
to
See
menu_link.cacheable_access_check_tree_manipulator
in #1805054: Cache localized, access filtered, URL resolved, and rendered menu trees.#4.4: I agree that the preloading doesn't belong here.
#5.7: the numeric keys correspond to
mlid
s, which were the IDs used to load menu links in 7/HEAD, and now still exist in the DB. 0 was and still is the virtual "root" node of the menu link tree. But off the top of my head (still getting back into this), I think it would be fine to convert this to string keys, which is what part1 + part2 (this patch) introduce.#5.15: I think you're confused by the variable names.
count()
counts everything in the given tree, with theMenuLinkTreeElement
object it's invoked on being considered the root. So given a tree of the shapeThen it makes sense.
childCount()
would imply only the children are counted, but this is not the case.#6.2/#8: Because these are straight setters, there's close to no value in writing test coverage for them. If deemed valuable enough, we can add test coverage for that of course.
#6.3: agreed.
#7: Because pwolanin and I hadn't gotten around yet to removing it; it's a low-priority thing in the grand scheme of things. It's an implicit
@todo
, if you will.Comment #12
dawehnerThanks for clarifying! Makes sense
I would be totally fine to not add test coverage here, or at all, but hiding this seems bad.
Comment #13
xjmComment #14
Wim Leers:D
Comment #15
xjmComment #16
pwolanin CreditAttribution: pwolanin commentedHere's the current step2 only patch (do-not-test), and step1 + step2 combined for tests
Comment #17
pwolanin CreditAttribution: pwolanin commentedmissed this typo before:
Should be:
- will have to propagate that to the next steps too.
Comment #18
dawehnerAdded a follow up #2303463: Move route preloading for menu trees out of the MenuLinkTree
These are IDs so using 1 makes a little bit more sense, tbh.
There is no point in changes this.
Comment #19
dawehnerFixed the resettable bit.
Comment #20
Gábor HojtsyNeeds step 2 only patch. Also issue summary is practically missing, makes it hard to review.
Comment #21
pwolanin CreditAttribution: pwolanin commentedHere's a clean step2 patch
Comment #22
tim.plunkettBad merge.
Comment #23
pwolanin CreditAttribution: pwolanin commentedJust a bad patch (rolled against outdated HEAD), the merge is fine.
Here's a patch against the right base.
Comment #24
pwolanin CreditAttribution: pwolanin commentedAnd with a couple more fixes from kgoel
Comment #25
pwolanin CreditAttribution: pwolanin commentedComment #26
pwolanin CreditAttribution: pwolanin commentedRemoving an @deprecated marker that didn't make sense.
Comment #27
dawehnerThis patch has really good test coverage, really nice!
On top of that there is a clear separation of concerns, compared to the earlier versions of the menu patches which had a lot backed into one gigantic class.
Let's burn the karma here, but I really can't find anything anymore.
Comment #28
Wim LeersNote for committers et al: pwolanin wrote
MenuParentFormSelector(Interface)
andMenuLinkTreeTest
, I wrote pretty much everything else. dawehner only fixed his own nitpicks. Hence it's acceptable for dawehner to RTBC this.Comment #29
alexpottImpressive stuff - really well documented and tested - just a couple of minor things I noticed.
This seems a bit terse - lets explain what it provides.
Allegedly there is a followup to convert (at the request of Dries) this to protected - and they are public cause of performance. However I think we should protect them first and look at performance implications later. Especially since the class does not make any use of some of these properties so we are just setting and using them from outside of the class.
According to the docs "If the class is capable of injecting services from the container, it should inject the 'string_translation' service and assign it to $this->stringTranslation."
This at least needs a comment as to why we're doing this. Since other tests do not start with this.
Missing a call to parent setUp
No call to parent::setUp()
Comment #30
Wim Leers#29:
Comment #31
dawehnerI totally agree with wim's comment and changes.
Comment #32
effulgentsia CreditAttribution: effulgentsia commentedA useful thing about adding getters would be that we could NOT add setters, and thereby ensure that once constructed, a MenuLinkTreeElement is immutable.
Comment #33
Wim Leers#32: Except that we need
MenuLinkTreeElement
s to be mutable, because menu link tree manipulators need to be able to manipulate them (to set access check results etc.).Comment #34
pwolanin CreditAttribution: pwolanin commented@effulgentsia - so we can skip most of the setters, but we need to be able to at least manipulate the subtree and access values. I was mistaken when I thought we could avoid that - we'd have to e.g. pass the manipulators into the load step, which would be a substantial refactoring.
Comment #35
alexpottThanks for answering my questions - I can see why the decision to use public properties has been made this way - if we want to change this we can do this is a follow up.
Committed 50ac470 and pushed to 8.x. Thanks!
Comment #37
Wim LeersAwesome, thanks alexpott!
We were already working to address it anyway, to not impact our velocity too much. I've now posted that in a follow-up issue: #2304363: Make MenuLinkTreeElement's properties protected, add getters, add limited setters — in case you or Dries decide you want those properties to be protected after all.
Now we can work on #2301313: MenuLinkNG part3 (no conversions): MenuLinkContent UI! :)
Comment #38
dawehnerAdding the critical regression as follow up
Comment #39
xjmTagging the child issues retroactively.