Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Add API documentation to the MenuLinkParent process plugin.
Proposed resolution
In #15 phenaproxima pointed out the the plugin is out of date and needs 'sprucing up'. That work was done in this patch. Some of the changes (Haven't read the whole issue) include general cleaning up and support for external URIs.
Remaining tasks
Tests. A list was given in #44 of the tests that are needed. When you write a test please strike it off the list here.
The menu link is a root item.The parent ID exists.The parent ID did not exist, but was stubbed.The parent ID did not exist and couldn't be stubbed.The parent ID did not exist, could not be stubbed, and the parent link path/menu name were not passed. (This should result in a MigrateSkipRowException.)The parent ID did not exist, could not be stubbed, and the parent link path is external and could be loaded.The parent ID did not exist, could not be stubbed, and the parent link path is external and could not be loaded. (Should result in a MigrateSkipRowException.)The parent ID did not exist, could not be stubbed, and the parent link path is an internal URI that exists and could be loaded.The parent ID did not exist, could not be stubbed, and the parent link path is an internal URI that doesn't exist. (Should result in a MigrateSkipRowException.)
Create a follow up for this TODO in MuenLinkParent, "Introduce a new exception to be thrown if stubbing fails or is disallowed, and catch that instead"
User interface changes
API changes
Data model changes
Release notes snippet
Comment | File | Size | Author |
---|---|---|---|
#97 | 2845485-97.patch | 14.82 KB | quietone |
#97 | diff-94-97.txt | 598 bytes | quietone |
#94 | 2845485-94.patch | 14.82 KB | quietone |
#94 | interdiff-90-94.txt | 736 bytes | quietone |
#90 | 2845485-90.patch | 14.8 KB | quietone |
Comments
Comment #2
quietone CreditAttribution: quietone as a volunteer commentedComment #3
phenaproximaSelf-assigning for review.
Comment #5
phenaproximaFor people who don't understand that menu links are plugins, this will be extraordinarily confusing. I think we should strike all mentions of plugin IDs. Let's change this, then, to something like "Determines the parent of a menu link."
Ideally, we should also link to documentation that explains how menu links work in D8.
This sentence adds nothing. Let us be rid of it.
These lines exceed 80 characters.
Can we re-word the parent_id description to "The numeric ID of the parent menu link, or 0 if the link is at the top level of its menu"?
In the parent_link_path description, "external path" should be "external URL".
This example needs to be explained.
This should be {@inheritdoc}.
Comment #6
jofitz CreditAttribution: jofitz at ComputerMinds commentedChanges in response to code review.
Comment #8
jofitz CreditAttribution: jofitz at ComputerMinds commentedHere's the correct patch from #6.
Comment #9
gaurav.kapoor CreditAttribution: gaurav.kapoor at OpenSense Labs commentedChecked the patch in #8 and it as per suggestions given in #5.So marking it for review , so that it can be tested.
Comment #10
gaurav.kapoor CreditAttribution: gaurav.kapoor at OpenSense Labs commentedComment #11
phenaproximaI'd like to take another look at this before we jump ahead with RTBC.
Comment #12
phenaproximaThese will need to be outdented to be flush with the first line.
This is a little unclear because it is directly referring to something that is done by the migration plugin, not this one. We should probably include a link, at least, to the migration plugin's documentation.
Also, I notice that the plugin's transform() method throws a MigrateSkipRowException if it falls all the way through. That needs to be documented.
Comment #13
jofitz CreditAttribution: jofitz at ComputerMinds commentedI have addressed #12.1 and documented the MigrateSkipRowException (I hope this is what you meant, @phenaproxima).
As for #12.2 - the example is an adapted version of that in d*_menu_links which does indeed involve the migration plugin, but I would argue that this example does not. I'm struggling to explain this any more clearly than I did the first time, so I am open to any guidance.
Comment #14
prash_98 CreditAttribution: prash_98 commentedThe patch applies well and also the required documentation have been added. So I guess that it can be changed to RTBC.
Comment #15
phenaproximaI took a closer look at the MenuLinkParent plugin and it's pretty far out of date; for example, it tries to catch a MigrateSkipRowException that is no longer thrown. I need the entire plugin needs sprucing up in addition to better documentation, so I think we should expand the scope of this issue and fix it up in here.
Comment #16
jofitz CreditAttribution: jofitz at ComputerMinds commentedWhile removing the MigrateSkipRowException try-catch I discovered that is is still required because Migration::transform() can throw the exception if the 'no_stub' property of the migration destination is set to true (see modules/migrate/src/Plugin/migrate/process/Migration.php:124 which leads to modules/migrate/src/Plugin/Migration.php:400). I hope that makes some sense (happy to discuss in IRC)!
I can't see anything else in the plugin that needs sprucing up, but let me know if you have something specific in mind, @phenaproxima.
Setting back to Needs Review (in hope of RTBC).
Comment #17
phenaproximaSorry -- I had to refactor the plugin a bit. It's out of date and confusing, I couldn't help myself.
I made the following changes:
1) Added a skip_row configuration option to control whether or not the plugin throws MigrateSkipRowException. The decision really shouldn't be up to the plugin at all -- if someone wants to skip the row, they should put a skip_on_empty in the process pipeline. However, to maintain BC, I added this option and defaulted it to TRUE.
2) Got rid of the try-catch block. The migration process plugin does not throw MigrateSkipRowException unless it receives an empty value, which this plugin guarantees will not happen. Therefore the try-catch has no purpose.
3) Various other bits and pieces.
Comment #19
phenaproximaOkay, this should fix the broken tests.
I have streamlined things a little bit by making MenuLinkParent directly extend the Migration process plugin (aliased here as Lookup for clarity). I also restored the try-catch that I removed in #17 -- a path already well-trodden by @Jo Fitzgerald, but one I had to grok for myself -- and added a comment explaining it.
Additionally, I added support for external URIs. At the moment, MenuLinkParent doesn't know what to do if the parent_link_path is an external URI; it'll probably just fail with an InvalidArgumentException, thrown by Url::fromUserInput(). I made it more graceful; it will attempt to look up an existing link with that same external URI before falling through. It's a backwards-compatible change, so I'm not sure it'll need a change record...?
Comment #20
jofitz CreditAttribution: jofitz at ComputerMinds commentedA very minor nit-pick, but perhaps Migration could be aliased as MigrationLookup (rather than just Lookup) because that's what it'll be called once #2845486: Rename Migration process plugin and add documentation is in.
Comment #21
phenaproximaJust realized that we'll need tests of the external URI handling.
Comment #22
heddnMigration process plugin was renamed to migration_lookup. Needs re-roll.
Comment #23
pk188 CreditAttribution: pk188 at OpenSense Labs commentedRe rolled.
Comment #25
pk188 CreditAttribution: pk188 at OpenSense Labs commentedComment #26
jofitz CreditAttribution: jofitz at ComputerMinds commented@pk188 Please can you explain the changes to core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php ?
Comment #27
jofitz CreditAttribution: jofitz at ComputerMinds commentedComment #28
pk188 CreditAttribution: pk188 at OpenSense Labs commentedComment #29
quietone CreditAttribution: quietone as a volunteer commentedWhat? The description says it determines the parent of a menu link, but then one of the source values is the parent link menu. I don't know much about menu links but this is a bit confusing.
In #5.1, phenaproxima suggested adding a link to documentation that explains how menu links work in D8. Maybe I missed it, but I don't see such a link.
Comment #31
masipila CreditAttribution: masipila as a volunteer commentedI'll have a look at this in the near future.
Comment #32
masipila CreditAttribution: masipila as a volunteer commentedHere's a patch with suggested improvements to the API documentation.
A couple of questions to @phenaproxima:
1. Is your idea that this TODO item should be addressed under this same issue or as a follow-up?
2. And the same question for this
Cheers,
Markus
Comment #33
masipila CreditAttribution: masipila as a volunteer commentedApparently I forgot to attach the files to the previous comment...
Comment #34
masipila CreditAttribution: masipila as a volunteer commentedComment #35
phenaproximaI think we should probably address both in this issue. We're already refactoring the hell out of MenuLinkParent, so I see no reason not to attack those TODOs now.
Comment #36
masipila CreditAttribution: masipila as a volunteer commentedSelf assigning.
Comment #37
masipila CreditAttribution: masipila as a volunteer commentedHere's a new version trying to address #32.2.
For the #32.1
Cheers,
Markus
Edit: formatting
Comment #38
quietone CreditAttribution: quietone as a volunteer commentedDecided to run the tests. Had a read through and everything seems done except one item, about a new Exception. It is the second item in #37, where there is a question directed to phenaproxima.
Comment #40
joelpittet[error] The internal path component 'https://example.com/publications.html' is external. You are not allowed to specify an external URL together with internal:/.''
Which is coming from
MenuLinkParent
because of the assumption that the parent link path is routeable through$url = Url::fromUserInput("/$parent_link_path");
The patch doesn't resolve this but does touch this class and line so I thought I'd mention it and hopefully I can resolve in another issue. Just and FYI
Comment #41
giorgio79 CreditAttribution: giorgio79 commentedWild idea: why not treat Menu Link Parents via the content system and use an entity reference field? Similar to taxonomy parent table removal at #2543726: Make $term->parent behave like any other entity reference field, to fix REST and Migrate support and de-customize its Views integration given menus were already converted to entities to use fieldability? #916388: Convert menu links into entities
Comment #42
joelpittetI moved my issue to it's own thing with a patch to avoid mudding up this one.
#2968170: MenuLinkParent breaks migration when Parent URI is external
Comment #43
phenaproximaComment #44
phenaproximaThe documentation here is excellent. Really nice and clear. It's also easy to follow the logic of the plugin -- these are significant improvements.
Don't we need to prefix the URL with
internal:/
?Other than that, this needs dedicated tests of each possible path through the plugin:
Comment #45
jofitz CreditAttribution: jofitz at ComputerMinds commentedHere's the beginning of the tests. I don't have time to finish this now, but maybe someone else can take up the baton?
Comment #47
jofitz CreditAttribution: jofitz at ComputerMinds commentedCorrected the mis-named data provider. Still requires plenty more tests.
Comment #48
quietone CreditAttribution: quietone as a volunteer commented@Jo Fitzgerald, go go go! I would love to see this finished.
Comment #49
jofitz CreditAttribution: jofitz at ComputerMinds commentedPatch from #47 no longer applies. Re-rolled.
Comment #50
jofitz CreditAttribution: jofitz at ComputerMinds commentedFailed to incorporate test file in #49 patch. This is a re-roll of the patch in #47.
Comment #51
jofitz CreditAttribution: jofitz at ComputerMinds commentedNW for remaining tests.
Comment #53
quietone CreditAttribution: quietone as a volunteer commentedThis is the the only issue that didn't get finished in the push to get all the process plugins docuemented. In the hopes of making progress I've added a test case and some comments. Not sure the test is correct since I don't know this area very well.
Comment #54
quietone CreditAttribution: quietone as a volunteer commentedfix formatting in the IS
Comment #55
heddnDid we update the list of tests in the IS that are now covered or is that still needed?
These phrases could be combined into a more simple single sentence.
This TODO either needs to be removed (my preference) or an issue opened.
Comment #56
heddnCleaning up tags and bumping back to NW.
Comment #57
quietone CreditAttribution: quietone as a volunteer commentedNeeds a reroll.
Comment #58
vacho CreditAttribution: vacho at Skilld commentedOnly patch reroll by now.
Comment #59
Ghost of Drupal PastI think extending a plugin instead of calling to it diminishes the value of process plugin being plugins -- one could replace the migration_lookup plugin class with their own for their own needs and the callers would be oblivious to it. By extension a tight coupling is introduced which doesn't seem necessary to me.
Comment #60
vacho CreditAttribution: vacho at Skilld commentedComment #62
quietone CreditAttribution: quietone as a volunteer commentedWorking on a reroll.
Comment #64
quietone CreditAttribution: quietone as a volunteer commentedThe process plugin needs to implement ContainerFactoryPluginInterface.
Comment #65
quietone CreditAttribution: quietone as a volunteer commentedA few tweaks for testing.
Comment #66
dwwMostly this looks great, thanks! Definitely agree all this could use some clean-up and help. :)
Mostly nit picks, but this includes a few things of substance, so setting NW...
Originally, we call the menu name "Administration". Then in the example code, we have just 'admin', which we (sort of) explain. It's a bit of a confusing example, since the menu link path also starts with 'admin', and folks might think that's what's going on (especially if they skim or don't read the fine print).
Could we use an example from a 'Main navigation' ('main') menu, so that there's no overlap between the menu machine name and the link path?
Ooof, I know there's talk of restructuring d.o doc links to remove the 8 vs. 9 part of these paths, since the 9 vs. 8 handbooks are going to be so overlapping. I wonder how many @see links we already have like this. :/ I wonder what's the alternative.
I haven't read all the comments in the thread, but I don't see this line being added back elsewhere...
extra spaces around 'and' here.
Otherwise, LOVE how thorough and helpful this comment is!
Should this be a formal @todo? Is there already an open issue about this? If not, can we file it and include a link to it with this comment?
Wants a comma after "ID" before "so".
If this is a string or array of strings,
@param string|string[]
would be better. We can almost always do better thanarray
as a @param type.Looks like
$source_value
is always treated as an array of strings...so the above should probably just be
@param string[] $source_value
.On first glance, not clear why we're converting this back into an array manually. Why not just:
$plugin->transform($source_value, ...)
?That's not the test this provides data for.
A) In all cases, "The parent ID did not exist, could not be stubbed". Why repeat that every time? Can't we comment that once at the start and say it holds for all the examples?
Once we do that, the part that's different for each case could be listed as the array key, so we wouldn't need comments at all. E.g.:
(or something).
Looks like only the menu name isn't passed. Not sure why this is talking about "the parent link path/" in the comment. Maybe we don't need comments at all (see above), but if we keep them, can we simplify this to only mention the menu name?
As above. This should be
@param string[] $source_value
.Looking at the provider, this is always a string. If it handles an array, it's not clear how. wouldn't
transform()
always return a single string, not an array? If it does take an array, it should bestring[]
.These keys are self-documenting. Not sure we also need to replicate them as comments.
Thanks again!
-Derek
Comment #67
quietone CreditAttribution: quietone as a volunteer commentedThanks for the timely review!
Addressing the low hanging fruit from #66. Fixes for 4, 5, 6, 7, 10, 13, 14, 15
todo: 1, 2, 3, 9, 11, 12
Comment #68
quietone CreditAttribution: quietone as a volunteer commented1. Used menu_name 'navigation' since that is the name of the menu in the Drupal7 fixture for link_path 'admin/structure'.
2. There doesn't seem to be anything to do here for this?
3. This was removed #17 when phenaproxima did some refactoring because the plugin was out of date.
9, 11 and 12 Fixed.
Hopefully, that will tidy this up a bit and pass tests. Still to do is make that all the test cases in the IS are covered.
Comment #70
dwwFantastic. Thanks for opening #3131567: Introduce a new exception if stubbing fails or is disallowed
One very tiny remaining nit:
From what I've seen, the core convention for these is something like this:
I'm composing this in dreditor, not emacs, so I'm not sure that's wrapped correctly, but hopefully you get the idea. ;) Key points:
a) Start with "In [link]"
b) Subsequent lines for the same @todo should be indented 2 spaces
Otherwise, this seems RTBC to me. Thanks again!
Comment #71
quietone CreditAttribution: quietone as a volunteer commented@dww, thanks for the vote of confidence but I think the tests still need work. All the cases in the IS are not covered.
For #70 I fixed the spacing but left the text as is. I did that because the @todo: To Do notes section in the standard does not specify that format and what is here is similar to the example given on that page.
Comment #72
quietone CreditAttribution: quietone as a volunteer commentedUploading the patch will help.
Comment #73
quietone CreditAttribution: quietone as a volunteer commentedAnd now a version for 9.1.x. I redid the test a bit to make it clearer what is happening (at least for me). I retained testTransformExternal but added a data provider to it. There is one test for external links, testTransformExternal, and on for internal links, testMenuLinkParent, and a helper added to do the common setup and run the final assertion.
Comment #74
quietone CreditAttribution: quietone as a volunteer commentedThere is one path in menu_link_parent that is not tested, which is;
And that is because the url is always not routed and thus fails this test. How to test that?
Comment #75
quietone CreditAttribution: quietone as a volunteer commentedComment #76
mikelutz#74 Seems like a bug, or at least a code smell. Url::fromUserInput() will always return an unrouted internal:// url. I don't see why we need/have that code path, as I don't believe it can be executed.
Comment #77
quietone CreditAttribution: quietone as a volunteer commented@mikelutz, thanks. This is an area I know little about. This patch removes that block of code from the source plugin.
Comment #79
mikelutzHmm, interesting. I guess I need to dig into it a little further.
Comment #80
quietone CreditAttribution: quietone as a volunteer commentedOK, this restores that block of code. And I figured out what needs to be done to test it. Yea! This patch does that and does some cleanup as well.
Comment #81
quietone CreditAttribution: quietone as a volunteer commentedAdd strikethrough to the relevant test in the list in the IS.
Comment #82
quietone CreditAttribution: quietone as a volunteer commentedThe MenuLinkParent process plugin is now using the migrate.lookup service not the migration_lookup process plugin it was when this issue was created. The service does not create stubs it just does the lookup, therefor all references to stub can be removed.
Comment #83
dwwLooking good. A few final concerns:
Why do we need both of these comments for the same early return?
Core isn't totally consistent, but seems to use () at the end of function names in comments like this.
Seems slightly weird to go through the trouble of a data provider when there's only 1 test case. I guess it's "good plumbing for later" but I wonder about YAGNI.
If we keep it, the comment points to the wrong test function, and we should add ().
I believe all this is dead code. If not, typo in the function name.
Almost RTBC. :)
Thanks!
-Derek
Comment #84
quietone CreditAttribution: quietone as a volunteer commentedThanks for the quick review.
1. Fixed.
2. Fixed.
3. Comment fixed. I made a provider because I wasn't sure if other test cases will be needed. Maybe a review would point out one I missed?
4. Yes, it is dead. It has been removed.
Comment #85
dwwRe: #84: Thanks for the fixes! Looking really close now.
Re: #84.3: I'd feel a lot better RTBC'ing if we added a 2nd case to that provider. Not sure what else makes sense for testing an external menu parent. If we truly can't think of any other cases to test for that, I'd advocate undoing the provider and just let it be a simple test case with a single case. A provider for 1 case seems like a wonky precedent to set for core tests. Of course, what I think doesn't matter as much as what the core committers think. ;) /shrug
Comment #86
quietone CreditAttribution: quietone as a volunteer commentedOk. How about this, I moved that single test into providerMenuLinkParent() and removed testTransformExternal().
Comment #87
dwwYeah, that's much better, thanks! However, with that change:
This comment is no longer true. :/
Sorry,
-Derek
Comment #88
quietone CreditAttribution: quietone as a volunteer commentedOh fudge. At the risk of making another error I changed the summary link of both of the tests. And then I found an unused use statement.
@dww, Thanks for you patience.
Comment #89
dwwThanks for catching that the other test summary was wrong.
If we're going to go this far, we should use proper sentences for these. ;)
"Tests that an ..."?
Or maybe:
"Tests which exception ..."?
Tests the menu ...
Comment #90
quietone CreditAttribution: quietone as a volunteer commentedOK. ... I am reminded of the poor grades I got in English (my first and only language) classes many years ago.
Comment #91
dwwSorry about the reminder. ;)
Nothing left to complain about, RTBC! 🎉
Thanks for your patience and perseverance...
Comment #92
alexpottThis one bit has me a bit confused...
parent_link_path - I think this should be
The Drupal path or external URL the parent of this menu link points to.
Comment #93
alexpottSetting back to needs review for #92 - if I'm wrong this can be set back to rtbc.
Comment #94
quietone CreditAttribution: quietone as a volunteer commentedYea, this is interesting. The process plugin is only provided information about the parent not the child so which link is 'this menu link'? Any way, the change suggested does bring that line into accord with the rest of the documentation.
Comment #95
dwwInterdiff in #94 addresses #92. Sorry I missed that in earlier reviews. Back to RTBC.
Thanks!
-Derek
Comment #96
catchNeeds a re-roll.
Comment #97
quietone CreditAttribution: quietone as a volunteer commentedSimple reroll.
Comment #98
heddnAnd back to RTBC.
Comment #99
alexpottCommitted and pushed 244ccb2863 to 9.1.x. Thanks!
I considered backporting to 9.1.x but since this mixes documentation and code changes I felt that this was unnecessary. I'm pretty sure that the code changes are safe but been caught out in the past so not taking the risk.