Problem/Motivation
There is no migration for menu links.
Proposed resolution
Write a migration for menu links.
Remaining tasks
Move the path validator resolution into a process plugin.
User interface changes
None.
API changes
In order to generate the route name and parameters, we need to make a call to PathValidator::getUrlIfValid(). But, we need to do it in a way that doesn't depend on user access to the path, so we need to update the PathValidator and PathValidatorInterface to have methods that skip access checking. This very small change is achieved by adding new methods.
Original report by @chx
Menu links are entities so this won't be too hard. The router_path is new but it's calculated by MenuLink::preSave so it's not something we need to bother with. I fully except this to be a 1:1 copy.
Comment | File | Size | Author |
---|---|---|---|
#36 | menu_name_error.txt | 9.74 KB | eliza411 |
#32 | 2178703_32.patch | 33.06 KB | chx |
#32 | interdiff.txt | 2.53 KB | chx |
Comments
Comment #1
penyaskitoComment #2
penyaskitoPartial work.
Migration is done, but untested. Call it a day.
Comment #3
penyaskitoStill WIP, almost done. Works quite well.
Comment #4
penyaskitoAdded tests for the menu links source.
The migration test is still not working because the menu_name is not set to the menu link, or gets unset somewhere.
Comment #5
ultimikeComment #6
jp.stacey CreditAttribution: jp.stacey commentedShould this issue have #2221733: [Meta] Test individual D6 > D8 content migrations as its parent, so all D6->D8 migration development/testing can continue to be marshalled into one checklist?
Comment #7
ultimikeComment #8
joemoraca CreditAttribution: joemoraca commentedI have tried this and get no menu links - do I need to apply one of the above patches (seem really old) or is it just not working yet?
Comment #9
penyaskitoIt won't work, too old and D8 menu_links were buggy at that time. I will try to get to this soonish, but unassigned so noone is stopped to work on this one.
Comment #10
ultimikeI started updating this patch - it's not complete:
-mike
Comment #11
ultimikepenyaskito and I were talking on IRC and think that we probably don't need to migrate all menu links - perhaps just where menu_links.module = 'menu' and menu_links.customized = 1. Thoughts?
I made some more progress on this patch tonight, but still some work to do in mapping fields and updating MigrateLinkSourceTest.
-mike
Comment #12
chx CreditAttribution: chx commentedI think that's a good idea. You have books in there which are migrated separately, you have the generated links there etc.
Comment #13
ultimikeOk - making steady progress now. Updated patch and interdiff attached.
At this point, the functional test is mostly there, I still haven't started updating the unit test.
According to a previous version of the patch, the route_name and route_parameters should be calculated on preSave() - but I don't see a preSave() method for menu_link_content...
I'm also not sure if we need to do anything with the p1...p9 D6 fields.
-mike
Comment #14
ultimikeI just updated the unit test. Interdiff and patch attached.
@chx - I think you gave me a hint a couple of weeks ago on how to proceed on the route_name, route_parameters, and p1-p9 fields, but I don't remember what it was (sorry!) Can you point me in the right direction on what I need to do to finish this up?
Thanks,
-mike
Comment #15
ultimikechx gave me some guidance on how to move forward with this patch, I've made some progress, but I've hit a wall.
chx and I talked about using
$pathValidator->getUrlIfValid()
in Drupal\migrate_drupal\Plugin\migrate\source\d6\MenuLink::prepareRow() to set the route_name and route_parameters values for each link.Unfortunately, when testing this, regardless of the path that I set up to migrate in MigrateMenuLinkTest,
$pathValidator->getUrlIfValid()
always returns false ($pathValidator->getPathAttributes()
is actually what returns false). What am I missing?Also - should I inject the $pathValidator into Drupal\migrate_drupal\Plugin\migrate\source\d6\MenuLink? I looked into doing this, but didn't see any other source classes that were using dependency injection, so I didn't have anything to model the code on.
I went ahead and added another groups of tests for an external URL.
-mike
Comment #16
chx CreditAttribution: chx commented@ultimike what URLs did you try to feed to $pathValidator->getUrlIfValid() ? Could you try
drush ev 'var_dump(Drupal::service("path.validator")->getUrlIfValid("something");'
?Comment #17
ultimike@chx,
The URLs I tried passing to
$pathValidator->getUrlIfValid()
are the ones in the Drupal6MenuLink dump (the "link_path" field):Running
drush ev 'var_dump(Drupal::service("path.validator")->getUrlIfValid("admin");'
(or "admin/modules" or "https://drupal.org") returns nothing. Nada. Zip. Zilch. http://note.io/1tffturWhen I step through MigrateMenuLinkTest with my debugger,
$pathValidator->getUrlIfValid()
(in MenuLink::prepareRow()) returns false for the internal paths and a $url object for the external path.Any ideas?
-mike
Comment #18
ultimikeComment #19
ultimikeI chatted with chx about this, and he suggested that we add an access_check boolean to PathValidator and PathValidatorInterface that will allow us to check paths without also checking access to those paths (via #2346189: Denormalizing paths into route names/parameters is brittle / broken).
The attached patch incorporates these changes.
-mike
Comment #21
chx CreditAttribution: chx commentedAlthough the path validator code in #19 is mine after a discussion with dawehner it's now clear that it's not a nice and secure experience. Let's add some new methods instead. However the test still fails, and with good reason. Stay tuned.
Comment #23
chx CreditAttribution: chx commentedComment #24
ultimikeBased on a conversation with chx, we decided to:
Updated patch and interdiff attached.
-mike
Comment #25
chx CreditAttribution: chx commentedPlugins have ContainerFactoryPluginInterface so that you can implement
create()
and inject the path validator instead. See how theMigration
process plugin does it.Please rename the plugin to Route (hopefully you have PHPstorm, that makes PSR-compatible renames easy) and set $value to
['route_name' => $route_name, 'route_parameters' => $route_parameters']
. Then the YAML can be this:Noone particularly cares you will end with a "route" property set that is not saved by the destination anyways...
Comment #26
chx CreditAttribution: chx commentedI was wrong: the Route plugin must always return an array of not two but four elements: url where the value is NULL for internal paths and the url for externals and then route_name (NULL), router_parameters ([]) and options ([]) which are empty for external, set for internal. You can find the code in
MenuLinkContentForm::extractFormValues
(what does that code do in a form? don't ask) just replace the getUrlIfValid with a getUrlIfValidWithoutAccessCheck.Comment #27
ultimikechx showed me the way on IRC on this one. Changes include:
Patch and interdiff attached.
-mike
Comment #28
benjy CreditAttribution: benjy commentedThis patch looks great, nice work guys. Few super tiny nitpicks below related to comments. I also think we might need some unit tests for the new path validator methods?
Nice approach :)
Missing comment.
Wrong comment.
Wrong comment.
Comment #29
chx CreditAttribution: chx commentedComment #30
benjy CreditAttribution: benjy commentedLooks great!
Comment #31
alexpottWhy are we adding this? I guess for parity with the IfValid() methods but the only usecase is in a test. Seems superfluous.
Do we need to document the security concerns with using this method? Like we should only be using this if the path is not going to be presented to a user - right?
Comment #32
chx CreditAttribution: chx commentedThanks for reviewing this so quickly and for pointing out the missing doxygen. However, the superfluous argument is the classic case of bikeshed when Drupal 8 contains so many atomic plants. Regardless, I removed it.
Comment #33
benjy CreditAttribution: benjy commentedAll points in #31 have been addressed.
Comment #34
alexpottThis issue is a unfrozen change (migrate) as per https://www.drupal.org/core/beta-changes and it's benefits outweigh any disruption. Committed 92c2514 and pushed to 8.0.x. Thanks!
Comment #36
eliza411 CreditAttribution: eliza411 commentedI just ran a migration from a fairly simple legacy D6 site to a clean 8.0.x site and I'm getting the following error. The full stack trace is attached.
Comment #37
benjy CreditAttribution: benjy commentedHmm, that's interesting menu_name is a look-up from the menu migration. Did that run first without any errors?
Relevant yaml:
We could add a process to skip the row on null menus but i'm more interested in how the menu_name ended up null in the first place.
Comment #38
chx CreditAttribution: chx commentedFollowup at #2372837: menu link stubbing fails because fields are NOT NULL