Problem/Motivation
Drupal core provides an "underlying API" with field migration plugins to specify a D6 / D7 → D9 formatter and widget plugin ID mapping. The problem is that this feature is accessible only with a field migration plugin (and that is field type specific):
If a module has only formatters or widgets (but these are extending a field type which is not provided by the module), then for these modules, it is nearly impossible to tell Drupal's migration system that a specific Drupal 7 field formatter ID should be mapped to something else for Drupal 9.
For example, the Multiple Selects module would have a trivial migration path, but due to the issue described above, this is currently impossible to automate.
See #3188284: [PP-3] Migration support.
Proposed resolution
Create a new plugin ID mapper process plugin, move the related mapping logic into this plugin, and provide a hook for contribs to specify their plugin ID mapping.
Related 'logic':
- MigrateFieldInterface::alterFieldInstanceMigration()
- MigrateFieldInterface::getFieldFormatterType()
- MigrateFieldInterface::getFieldFormatterMap()
- MigrateFieldInterface::alterFieldWidgetMigration()
- MigrateFieldInterface::getFieldWidgetType()
- MigrateFieldInterface::getFieldWidgetMap()
Remaining tasks
- Add #3204212: Convert remaining widget and formatter type migrations to MigrateField plugins to core.
Patch with the new plugin.Use the new plugin in field migrations: assert that the changes are BC-safe. (This depends on #3204212: Convert remaining widget and formatter type migrations to MigrateField plugins – but it works for me).Add additional test coverage.- Document the new hooks (where?..).
Create a change record.— see https://www.drupal.org/node/3208917
User interface changes
Post-migration, my D7 content type that was migrated will now have the enhanced UX (with the appropriate widgets) that I'm used to as a site owner:
- Before

- After

API changes
Two new hooks:
hook_field_migration_field_formatter_info()hook_field_migration_field_widget_info()
Comments
Comment #2
huzookaWith this patch, contribs are able to map D7 widgets and plugins to their D9 equivalents.
For
multiple_selects:Comment #3
wim leers#2: is the top-level field type key truly necessary? Why can't we just map widget plugin IDs and formatter IDs?
How does this patch relate to #3108302: [PP-2] Field formatter & widget settings: fall back to default if missing plugin?
Comment #4
huzookaThis patch requires #3204212: Convert remaining widget and formatter type migrations to MigrateField plugins .
I don't have any clue why I had to fix
\Drupal\file\Plugin\migrate\process\d6\FieldFile– maybe it just suddenly began to work?..Comment #5
wim leers😅🔥
Comment #6
huzookaComment #7
huzookaComment #8
huzookaComment #9
wim leersThis is blocked on #3204212: Convert remaining widget and formatter type migrations to MigrateField plugins .
Comment #10
wim leersThe example in #2 is wrong. It's not
hook_field_migration_widget_plugin_id_info(), buthook_field_migration_field_widget_info().Note that there is zero pre-existing documentation about the field migration infrastructure (
\Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase()and friends), so it is very unclear where to document this. This explains @huzooka's remaining task in the issue summary:… so I went ahead and created a change record: https://www.drupal.org/node/3208917
Comment #11
wim leersAdding a concrete example of the impact to the issue summary.
Comment #12
wim leers🤔 AFAICT this is how we retain BC?
🤔 When could this ever occur? AFAICT this if-test is safe to remove because the constructor guarantees it exists?
🤔 When can this occur?
This would be an invalid use of this migration plugin.
IMHO this should throw a
InvalidArgumentExceptionor aMigrateException.Superb test coverage! 🤩
Comment #14
quietone commentedIn #9 it is said that this is postponed, so changing status.
Comment #16
huzookaThis patch fixes a very ugly BC problem:
MigrateFieldInterface::alterFieldFormatterMigrationandMigrateFieldInterface::alterFieldWidgetMigrationmethods weren't invoked with patch #8.I've also added test coverage for the above, and addressed the review from #12:
But I missed before that we can specify the provider in the annotation, so since the provider is
migrate_drupal:\Drupal\migrate\Plugin\Discovery\ProviderFilterDecoratorE.g if someone tries to use this process plugin by writing their own migration. From now on, this will throw a
\LogicExceptionwith a meaningful message.\InvalidArgumentExceptionwith a message about the config key's requirements.Comment #18
anybody#16 LGTM! We're using this in several migration projects and it works great!
As this is a "Contributed project blocker" for many contrib issues (all field formatter and widget upgrades), would it perhaps make sense for @Wim Leers (as of #12) or @quietone to already review this for having this RTBC'd as soon as #3204212: Convert remaining widget and formatter type migrations to MigrateField plugins lands?
I think that would help in many many contrib projects and migration projects.
Comment #20
wim leersRerolled on top of #3204212-52: Convert remaining widget and formatter type migrations to MigrateField plugins , due to conflict introduced by #3281427: Update Block and Theme setting migrations to not use Bartik and Seven.
Comment #21
anybody@Wim Leers: Thanks a lot for #20!
As we experienced different behavior (still investigating) from #16 with 9.4.x vs. #20 with 9.5.1 could you perhaps provide an interdiff? I tried, but it didn't work, sorry. :(
And wouldn't it be more transparent to use a MR here to see the changes directly?
Comment #22
grevil commentedUpdate to #21. Patch #20 works great! We just had to regenerate the migration ymls! 🙂👍
Comment #23
grevil commentedUsing patch from #20 for 3 site migrations now and found a little flaw with field widget configurations (and probably also with field formatter settings).
For example, I am migrating any "entityreference_view_widget" field widgets to "entity_browser_entity_reference" for every entityreference field using:
This works as expected, BUT I have no way to tell the new field widget it's settings. In my example, trying to edit a content using the mentioned field widget will result in the following error:
This happens, because the field widget has no entity browser selected. I am yet unsure if the hooks implemented through this issue should implement a way to map these settings (or set them). Or if this is the module's fault, as it should implement fallback options.
Comment #24
grevil commentedFurthermore, if anyone is using this patch together with Media Migration, make sure you implement the mapping for the field type media migration converts it to.
For example, if we have image fields on a few content types, which are using the deprecated "lightbox2" field formatter, and we want to migrate them to the "image" field formatter, we would usually do the following mapping:
But because "media_migration" will convert all image fields to media fields before "hook_field_migration_field_formatter_info()" runs, we have to map "media_image" instead:
Comment #25
anybody@Win Leers: Re #24 should we perhaps allow to pass settings as additional value?
@Grevil: Re #25: Perhaps it would make sense to create an issue over at Media Migration to let them know and perhaps implement a default for that or add it to their documentation? This is important to know, but shouldn't be relevant in this issue.
Comment #26
grevil commented@Anybody already did that a while ago and you already commented that issue! :P
#3317541: [PP-1] Document the use of future implementations "hook_field_migration_field_widget_info()" and "hook_field_migration_field_formatter_info()" with this module
Just thought this information might be relevant here aswell!
Comment #28
grevil commentedPatch from #20 still applies to current 11.x, using latest reroll from https://www.drupal.org/project/drupal/issues/3204212#comment-15475785!
Comment #29
quietone commentedComment #30
marc.bauAny chance that this goes in before D7 goes out of support? Migrating from D7 is quite difficult without and I do not like to run D7 in 2026 only because of migration failures.
Comment #31
quietone commented@marc.bau, if you haven't already you can consider seeking support in the #migration channel of Drupal Slack.
The Migrate Drupal Module was approved for removal in #3371229: [Policy] Migrate Drupal and Migrate Drupal UI after Drupal 7 EOL.
This is Postponed. The status is set according to two policies. The Remove a core extension and move it to a contributed project and the Extensions approved for removal policies.
The deprecation work is in #3522602: [meta] Tasks to remove Migrate Drupal module and the removal work in #3522602: [meta] Tasks to remove Migrate Drupal module.
Migrate Drupal will not be moved to a contributed project. It will be removed from core after the Drupal 12.x branch is open.
Comment #32
marc.bauHow should a removal of migration stuff from core fix the defects and allow people to migrate? *shakes head*
Comment #33
quietone commented@marc.bau, sites can continue to use the Migrate Drupal functionality in Drupal 11, which will be supported until 2028. The Migrate API itself will remain Drupal 12. Fixes can still be made to Migrate Drupal but that will not include feature requests.
Comment #35
quietone commentedOops, forgot this comment.
The Migrate Drupal and Migrate Drupal UI modules are deprecated and will be removed from Drupal 12. Since these are deprecated feature requests and some tasks will not be fixed.
Thanks to all for working on this!