Problem/Motivation
When migrating entity reference fields from a multilingual D7 site to a multilingual D8 site, I get the following error:
"Value is not a valid entity." line 106 on core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReference.php
This happens because core expects the entity reference value expects either a scalar value(like an ID) or an object typed as EntityInterface and the migration is sending it an array with ID and langcode.
Proposed resolution
I imagine one solution would be to allow sending both ID and langcode as parameters for an entity load, but I'm not sure how that would work exactly. I have a workaround for now that I'll describe in detail on the comments bellow.
Comment | File | Size | Author |
---|---|---|---|
#13 | 2852570-migrate-d7-d8-translated-entity-reference-3.patch | 631 bytes | nightlife2008 |
#2 | 2852570-migrate-d7-d8-translated-entity-reference-2.patch | 963 bytes | jmoreira |
Comments
Comment #2
jmoreira CreditAttribution: jmoreira as a volunteer commentedTask: Migrate multilingual content types A and B from D7 to D8. Content type A has a reference to content type B.
Note: In this scenario, the Content Translation module is being used for D7, so each translation is an individual node.
My current solution/workarounds for this issue:
If there's a better solution/workaround for this, I would be glad to know and document it somewhere. Here are a sample of my migration config files:
File: migrate_plus.migration.node_a.yml
File: migrate_plus.migration.node_a_translations.yml
File: migrate_plus.migration.node_b.yml
File: migrate_plus.migration.node_b_translations.yml
Comment #3
Gábor HojtsyI don't see how comment #2 is related to the original problem where you say entity references should accept other kinds of values.
Yes, so d7_node_translation does not specify the node migration as a dependency (for some reason), but if you look at how its tested (MigrateNodeTest), the node migration is ran before the translation migration. The node migration will migrate the original language.
Comment #4
jmoreira CreditAttribution: jmoreira as a volunteer commented@Gabor, comment #2 was to show the solution/workaround I got so far. For the "main content type" I do the migration using the tnid as the new nid and it works fine. The problem happens when I add the node reference field, because out of the box when I migrate the referenced content and use the migration process to get the referenced nid, the target_id is returned as an array of id and langcode, instead of an int/string with the id.
So, the workaround outlined in #2 was to remove langcode as an ID(with the patch attached) and import each referenced entity with a new nid. Because I thought(wrongly) I would have problems using repeated nid's as target ID.
I did some new tests and it actually works if I migrate all referenced translations to one node entity, so that isn't an issue, I updated the comment my latest solution, sorry about the mix up.
The actual issue now is the error in the description. The patch on #2 makes it work on my case, but I imagine it's a bad idea to just drop the langcode as an destination ID? Maybe we should do this conditionally? Or at the getValue function for the entity reference field use only the first value if an array is given?
Comment #5
Gábor HojtsyI think this may be too much in the weeds of migrate for me to practically help :/ Know multilingual much better than migrate. But if the langcode is dropped, how is the correct translation identified?
Comment #6
jmoreira CreditAttribution: jmoreira as a volunteer commentedThe language is dropped as a destination id but it's still used to create/update the entity. So for an example in D7 where nid 123 is the original en content and 124 is the fr translation, the mapping table would look something like:
And then the entity destination plugin uses the given langcode to decide if it will create/update a node or a translation. I imagine that in this case where in the D7 source translations have different nid's we don't need the langcode as a destinationid2, but maybe it would be useful in a setup where the D7 source has the same nid for all translations, like with Entity Translation, I think.
Comment #7
Gábor HojtsyYeah I would generally say removing meta information that distinguishes an element is not a good idea. Making systems work with that meta information is better :)
Comment #8
jmoreira CreditAttribution: jmoreira as a volunteer commentedThat makes sense, though it looks like that the Entity Reference field doesn't need the language to select the proper translation for the given field, so I'm not sure why we need to send the language as an ID to the destination. Maybe we could just have it as an ID for mapping?(Not sure if such concept exists in the Migrate API)
Comment #9
samirjusic CreditAttribution: samirjusic as a volunteer commentedI am having the exact issue of not being able to import EntityReference fields (with multiple values) that have translations. The default language migration works fine, but running the translation migration either fails OR it produces these new bizarre referenced items with really long titles for every entity it encounters but can't find (I suppose).
Applying the patch outlined in comment #2 does fix the import of translated content items.
I am curious if someone can point out what is the intended migration config that should work without the patch? I do see that the target ID from the sub-migration has both the ID and a language code. So are we supposed to split it with another plugin and then use it to point to the right destination?
Comment #10
samirjusic CreditAttribution: samirjusic as a volunteer commentedOne note, though: It seems that the patch works if its run on *only* the migration scripts that deal with the translation.
The first run of the migration (that goes through the default language migration) is to be run with the existing code untouched (I'm on 8.3.2). Then the patch is to be applied and the upgrade_d7_node_translation_NODE_TYPE.yml is run with that. This way I was able to complete the migration for the migrated content.
However, if I apply the patch and run the first migration as well with it (upgrade_d7_node_NODE_TYPE.yml) then it seems to me that the system generates these weird nodes that it would generate only in the 2nd step when running the _translate_NODE_TYPE.yml (basically the errors I was experiencing when trying to complete the migration for the translated content would happen right away with the first run of the migration script)
Comment #12
nightlife2008 CreditAttribution: nightlife2008 at Randstad Digital commentedThis patch breaks the path migration's node translation lookup process plugin.
It needs the langcode for a translation migration (destid2) to set the correct language for the path alias.
Comment #13
nightlife2008 CreditAttribution: nightlife2008 at Randstad Digital commentedAs a follow-up on my previous comment, I've retested my own bugfix patch and decided to share it with you guys.
I've been using the various plugins and the only one returning a "faulty" value for an EntityReference is the MigrationLookup plugin.
However, the current patch breaks the UrlAlias translation lookup process plugin, because there isn't a langcode column anymore to depend on, to create the D8 Url alias entity.
In my opinion the patch is as easy as changing 1 character, and to "reset" the destination_ids array, even if there are more then 1 items in the array. This returns a single ID everytime, and thus not removes the metadata (langcode) from the DB scheme, but only inside the method that uses the Id lookup.
Feel free to comment on my fix.
Comment #15
quietone CreditAttribution: quietone as a volunteer commentedtagging
Comment #19
quietone CreditAttribution: quietone as a volunteer commented@jmoreira, thanks for filing this issue and creating a patch.
A migration for entity references for translated nodes was created in #2912348: Handle entity_references related to Drupal 6 and 7 node translations with different IDs and committed on Apr 19 2018. That will will have fixed this problem. There hasn't been any activity on this since before that commit which also leads me to believe this has been fixed.
I'm going to close this as outdated. If I am wrong, reopen this issue by setting the status to Active and explain what is not working, what error message you are getting and anything you think is relevant.
Thanks!
Comment #20
Shiraz DindarI realize this is an old issue, so I'm not going to reopen it, but for the benefit of others, I want to comment that I had the same issue as described by the O.P, and the patch #13 resolved it. So I would say the comment in #19 that this issue was fixed with that commit is incorrect. I'm fine with the patch. I just want to let anyone that finds this issue know.