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.
Taking #2911244: Field collections deriver and base migration as a foundation, I am working on a Multifield to Paragraphs migration where:
1. Fields of type multifield are migrated as Paragraph types.
2. Multifield subfields are migrated as fiels attached to each Paragraph type.
3. Fields that link an entity bundle with a multifield are migrated as entity reference revisions fields that point ot a Paragraph type.
Comment | File | Size | Author |
---|---|---|---|
#48 | paragraphs-multifield_to_paragraphs-2977853-48.patch | 158.23 KB | huzooka |
#44 | paragraphs-multifield_to_paragraphs-2977853-44--complete.patch | 169.71 KB | huzooka |
Comments
Comment #2
juampynr CreditAttribution: juampynr at Lullabot commentedHere is a work in progress patch that implements steps 1 and 2. I am working on step 3 and will post another patch as soon as I make further progress.
Comment #3
juampynr CreditAttribution: juampynr at Lullabot commentedFixed a special case in which a field could belong to a multifield and to a content type. I solved this by making d7_field to create a field base for paragraphs and then a field base for the content type, and then d7_field_instance would attach the fields to each of them.
I also removed the set of changes that belonged to #2911244: Field collections deriver and base migration.
Comment #4
juampynr CreditAttribution: juampynr at Lullabot commentedHere is a patch that converts multifield fields to Entity Reference Revisions ones, which links bundles with Paragraph types.
I found a bug when trying to display an entity reference revisions field at the Manage Form Display section. Once I fix that I will start working on migrating content.
I have also taken the chance to remove #2911244: Field collections deriver and base migration from the patch.
Comment #5
juampynr CreditAttribution: juampynr at Lullabot commentedOops, wrong diff command. Attaching again.
Comment #6
juampynr CreditAttribution: juampynr at Lullabot commentedPlease, slap me with a rainbow trout.
Here is the right one.
Comment #7
KarenS CreditAttribution: KarenS at Lullabot commentedI tried this much out just to see how far it would get. I got the new paragraph types created, with the right fields on them, and each of the content types that had a multifield has an entityreference field linked to the right paragraph type. There is more to do, but it looks like a good start!
Comment #8
juampynr CreditAttribution: juampynr at Lullabot commentedThanks for reviewing, @KarenS! I am still battling with an exception like 'The "hidden" plugin does not exist' when I try to display a paragraph field in a form display. Once I fix that I will start working in the content migration.
Comment #9
juampynr CreditAttribution: juampynr at Lullabot commentedFixed the edge case related with enabling paragraphs in form displays. It was unrelated to Paragraphs module.
Now working on the content migration.
Comment #10
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedThis patch includes content migration and therefore I mark it as ready for review.
I think that the next step would be to add tests to the patch. I will see how migrate's core and contrib modules test migrations and copy their approach.
Comment #11
heddnThere's already some of that in place for field collections inside of paragraphs. But to see how to go about this, review https://www.drupal.org/docs/8/api/migrate-api/generating-database-fixtur...
Comment #12
KarenS CreditAttribution: KarenS at Lullabot commentedEverything but the content migration seems to be working fine. Paragraphs are created with the right fields on them and the content that had multifields now has paragraphs.
I had erratic results on content, some values were correct but others were missing. I examined the results of getSubfields() to see what indexes were being selected and that seems to be where the problem is. It works fine for fields that have a single index, not for those with more than one. For instance I had a link subfield in a multifield and the array returned for that field had no index (and so no content was pulled in). I also had a formatted text field and instead of pulling the 'value' column, it pulled the 'format' column (so again the content was missing). I think you need to find a way to get the primary column if there are multiple values.
This is really complicated stuff, the way multifield stores values does not make this easy, I was looking at this earlier to try to figure out how to pull the right values, and realized how hard that was going to be. I think this is really close, but not quite yet.
Also I tried to do a rollback and re-import and that just wiped everything out. It's possible that just won't work, but if so we should be sure to warn about that.
A very minor nit, I would change the tag from 'Multifield Content' to 'Content', or at least add that as an additional tag, since the current documentation recommends that you can do a migration of all the content using --tag=Content.
Comment #13
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedThanks for the feedback @KarenS!
I have a paragraph where I experienced the bug that you found but I did not have a chance to work on it yet. I will this week.
This scenario happens when there is a field of unlimited cardinality shared by a content type and a multifield. Multifield ignores the field's cardinality as it only supports one value, but since the field's configuration in the database says unlimited (-1), this cardinality gets set at the corresponding field in a paragraph type at the destination database, which is incorrect.
I am leaving the status as needs work as I still need to migrate revisions and fix the issue reported by Karen at #12.
Comment #14
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedHere is a new patch that fixes some warnings when using the static_map plugin to set cardinality to 1 on paragraphs.
Comment #15
KarenS CreditAttribution: KarenS at Lullabot commentedJust to clarify, is this patch now ready for review or is there more coming?
Comment #16
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedThere is more coming, @KarenS. It's just that I did not have a chance to work on the remaining things:
* Fix the issue that you described at #12.
* Migrate content revisions.
* Add tests.
Comment #17
KarenS CreditAttribution: KarenS at Lullabot commentedI have concluded that my problem with the wrong columns being selected is because I have bad values in my D7 database. Even for non-multifield fields, the "index" and "column" values are incorrect in my source data. So I am not going to be able to provide a good test of your code. I can see that the code probably still does not take into account multiple field indexes, instead assuming a single value, so it looks like that still needs to be fixed.
Comment #18
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedThanks for the feedback, @KarenS!
Comment #19
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedHere is another patch where I am skipping migrating field formatters of multifield fields. These will need to be configured manually as I found many discrepancies trying to automate migrating this data.
Comment #20
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedFixing a typo in the above patch.
Comment #21
Vidushi Mehta CreditAttribution: Vidushi Mehta at gai Technologies Pvt Ltd commentedComment #22
heddnReally phenomenal work here. Lots of little things below, nothing super huge. Plus, it would be awful nice to still see some tests.
Nit: whitespace.
We cannot be sure about the name of the id of the migration. Migrate upgrade adds 'upgrade_' as a prefix automatically, but that can be changed/altered with a drush argument at generation time. Or it can be changed manually post generation. It is more safe to check the source plugin id.
We are so close to getting #2951550: Make service for field discovery for use in migrate entity derivers to land in 8.6. Maybe it will so we can start using it here?
This all got improved/made better in #2631698: Fix sub-optimal DX in MigrateFieldInterface. Should we re-work this for 8.6?
Since 8.6 is now alpha and 8.4 no longer has much support, shall we remove this?
Nit: copy/paste title.
This should maybe use/extend migration_lookup instead?
Copy/paste.
Comment length.
Shall we remove this BC logic before we land this?
Comment #23
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedUpdating patch for Drupal 8.6.
I will go through @heddn's feedback at #22 in the next patch.
Comment #24
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedHere I have addressed most of the feedback given at #22. Thanks @heddn!
Comment #25
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedHere is a new patch where I am making the lookup plugin faster by not having to load the referenced entities. I did this initially in order to set the revision at the entity reference revisions field but then I realized that since this is the migration that creates the entities the revision matches the entity's identifier. Loading revision numbers would be needed once we create the migration that migrates revisions, which this patch does not include yet.
Comment #26
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedHere is a new patch where I have improved the logic to find out the value of each subfield within a multifield. I found cases like text fields in sites that have Better Formats module in which the field index is the format instead of the field value. Therefore, I have changed the logic so first it looks for a _value field in the table and, if not found, falls back to the first index defined in the field configuration. See the interdiff for further details.
Comment #27
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedRe-rolling.
Comment #28
juampynr CreditAttribution: juampynr at Lullabot for NBCUniversal commentedI realized that I wasn't taking entity reference revisions into account which led to wrong paragraph associations. Here is an updated patch.
Comment #29
manask CreditAttribution: manask commentedHi, I tried using this patch to migrate multifields to paragraphs. I have a taxonomy subfield in my multifield and it did not migrate the data(term id) to the paragraph type subfield, however, another subfield of type text was correctly migrated.
I think this has something to do with the data type of $field_value. For term/entity references, shouldn't it be of type array?
I changed the code on line 67 when $field_value is empty to the following and tested with migrating taxonomy subfields and it worked but I do not know if there is another or a better way to solve this.
Could you please look into this?
Thanks.
Comment #30
somersoft CreditAttribution: somersoft commentedUpdated the patch in #28 so that there is a test to see if the configuration parameter is present before testing it's value. It removes a PHP warning message.
Comment #31
davedg629 CreditAttribution: davedg629 commentedJust a heads up that this patch has some issues with Drupal >=9.1.4. The patch applies successfully, but I'm getting an error when I run migrate-upgrade:
Since Drupal 9.1.4 was released, additional work has been done on the patch that this patch is based on: https://www.drupal.org/project/paragraphs/issues/2911244. I'm guessing those changes need to be carried over to this patch.
I'm looking into it, but it's all a little over my head. Will report back if I figure anything out.
Comment #32
huzookaComment #33
huzookaNo interdiff - I think I've changed too many things.
This patch needs the following patches:
Improvements compared to #28:
<field value delta> > 0
.I still have to file two feature requests, one for core, and an another for Entity Reference Revisions:
Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity::getFieldValues
– now my patch assumes that the alter tag will bymigrate_field_values
.Comment #34
huzookaCore issue mentioned in #33: #3218294-2: Allow altering field value query performed by FieldableEntity.
Comment #35
huzookaERR patch of #33: #3218312-2: Provide an option to skip (opt-out) forcibly created new revision of the referenced entity (so that migrations won't lead to unnecessary saved revisions).
Comment #36
huzookaUnassigning, but leaving NW because:
Comment #37
huzookaComment #38
huzookaThis new patch makes possible to migrate paragraphs from multifield values selectively, per (host) entity type (and even per bundle): because multifield migration derivative IDs are changed from
multifield:<source_field_name>
tomultifield:<host_entity_type>:<host_bundle>:<source_field_name>
.Comment #39
huzookaFixing typos: mutli* to multi*
Multifield migration IDs used in lookups are updated to the new derivative ID.
Comment #40
huzookaThe FR I created for core adds the tag
migrate_field_value
, while this hook assumesmigrate_field_values
Comment #41
huzookaAddressed #40 and also improved
MultifieldMigrationsTrait
(which will make us able to reuse it in a Migrate UI functional test... or at least I hope so!)Comment #42
Wim LeersHoly crap 🤯
🤔 Should we make this more explicit by adding these to the
paragraphs
module'scomposer.json
in this patch?👍 This is why we need that ERR patch.
🐛 This looks like a typo: it the first parameter needs to be dynamic here.
👏
Übernit: slightly too much indentation here.
Comment #43
huzookaComment #44
huzookaThe patch in #41 tried to migrate deletes multifields as well. That should be fixed.
I also added a new target bundle lookup plugin which will skip those multifield subfield instance migration rows which miss the destination paragraph type.
I also removed every non-crucial changes (see cleanup interdiff).
Re #42:
Comment #45
huzookaPatch addressing most recent releases of Drupal core 9.1+ (see #3190815: Source count caching broken: impossible to enable source count caching for SqlBase-based source plugins (plus, unneeded cache I/O))
Comment #46
Wim Leers👏 Nice reuse of pre-existing (core) source plugins!
Übernit: this could be
static
🤓🤓 s/found/find/
(Also: this does not need to be translatable.)
s/operation/operations/
🤯 Woahh … this is complicated, but once you get it … it is super powerful! Imagine core would've had this years ago… then we'd have many more stable contrib migrations I bet.
🤔 … and this return statement avoids that, right?
But why the assignment and not just
🤓
👏 We should totally add this to Drupal core!!! 🙏
Comment #47
huzookaNew patch on top of #3226658-8: Guarantee the uniqueness of the migrated paragraph types and #3145755-40: Orphaned (nested) paragraphs entities after migration & (invalid) stub paragraph entity leftovers.
Works with any core versions, and also ensures paragraphs type uniqueness.
Comment #48
huzookaRebased on #3145755-43: Orphaned (nested) paragraphs entities after migration & (invalid) stub paragraph entity leftovers.
Comment #49
fjgarlin CreditAttribution: fjgarlin as a volunteer and at Drupal Association commentedI know that I want this patch, but I am struggling to get it to apply with all the other dependencies, maybe it's the order of the patches?
This is what I have in the patches section:
I am using the latest version of paragraphs: 8.x-1.13
Any guidance on this would be greatly appreaciated.