Problem/Motivation

https://git.drupalcode.org/project/multiple_selects/-/blob/8.x-1.x/src/P... uses multiple_options_select as the widget plugin ID.

But https://git.drupalcode.org/project/multiple_selects/-/blob/7.x-1.x/multi... uses multiple_selects

This means that migrations from D7 to D8|9 will not automatically pick up this migration.

Steps to reproduce

Proposed resolution

Alter the field configuration migration to do this automatically. #3051252: Upgrade path for Multiupload Filefield Widget and Multiupload Imagefield Widget can serve as an example.

Remaining tasks

Add a migration state file
Manual testing
Review
Commit

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers created an issue. See original summary.

quietone’s picture

Status: Active » Needs review
FileSize
465.72 KB

And here is a patch.

quietone’s picture

Status: Needs review » Needs work
FileSize
2.11 KB
465.79 KB

Rename filed plugin file and fix coding standards. Not testing this patch because the tests are not running with run-tests.sh
FATAL Drupal\Tests\multiple_select\Kernel\Migrate\MigrateFieldTest: test runner returned a non-zero error code (2).

quietone’s picture

Status: Needs work » Needs review
FileSize
3.66 KB
465.77 KB

The migration tests now pass locally now with run-tests.sh. I also discovered that I was working in a module with the name multiple_select not multiple_selects. History shows I did ddev composer require drupal/multiple_select:1.x-dev which does exist but is not this module. What a nuisance to have two similarly named modules. Anyway, all updated now.

quietone’s picture

And I was working on D 9.2.x, so ran the tests with that. And I checked the test log, the tests are running. So all good here.

quietone’s picture

Issue summary: View changes

Oh, I think this should be tested with real world data.

quietone’s picture

Issue summary: View changes

Also, this needs a migration state file.

Wim Leers’s picture

FileSize
693 bytes
465.81 KB

I tested this manually, on a real-world site. This does not work at all? 😅

  1. +++ b/src/Plugin/migrate/field/d7/MultipleSelectField.php
    @@ -0,0 +1,31 @@
    + *   type_map = {
    + *     "list_text" = "list_string",
    + *   },
    

    Why only these two types? It supports much more!

  2. +++ b/src/Plugin/migrate/field/d7/MultipleSelectField.php
    @@ -0,0 +1,31 @@
    +  public function getFieldWidgetType(Row $row) {
    +    return 'options_select';
    +  }
    

    Huh, this Field Widget Type is not even provided by the multiple_selects module?


\Drupal\migrate\Plugin\migrate\destination\ComponentEntityDisplayBase::import() is still calling it with unmodified raw values.

I have a field_course node_reference field. This is its field_config_instance data:

a:7:{s:5:"label";s:5:"Track";s:6:"widget";a:5:{s:6:"weight";s:1:"7";s:4:"type";s:16:"multiple_selects";s:6:"module";s:16:"multiple_selects";s:6:"active";i:1;s:8:"settings";a:0:{}}s:8:"settings";a:1:{s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:6:"inline";s:4:"type";s:22:"node_reference_default";s:6:"weight";s:1:"8";s:8:"settings";a:1:{s:21:"field_formatter_class";s:10:"pull-right";}s:6:"module";s:14:"node_reference";}}s:8:"required";i:0;s:11:"description";s:39:"Select which track this course reflect.";s:13:"default_value";N;}

Why isn't this just modifying process.widget_type_mapped[0].map in d7_field_instance_widget_settings? Wouldn't that solve it more accurately and with far less code?

Basically, the alter hook equivalent of

diff --git a/core/modules/field/migrations/d7_field_instance_widget_settings.yml b/core/modules/field/migrations/d7_field_instance_widget_settings.yml
index f7977757b7..102aae9dd1 100644
--- a/core/modules/field/migrations/d7_field_instance_widget_settings.yml
+++ b/core/modules/field/migrations/d7_field_instance_widget_settings.yml
@@ -63,6 +63,7 @@ process:
         entityreference_autocomplete: entity_reference_autocomplete
         entityreference_autocomplete_tags: entity_reference_autocomplete_tags
         taxonomy_autocomplete: entity_reference_autocomplete
+        multiple_selects: multiple_options_select
   'options/type':
     -
       plugin: get

… and by stepping through this with a debugger, I ended up with this, which does work for me too:

Wim Leers’s picture

Just discussed with @phenaproxima.

He sort of reached the same conclusion. He wrote:

18:45
WHOA! I see a way past this problem for you. We’d have to change core, but justifiably so
18:45
\Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase::getFieldWidgetMap() — why don’t we just add an alter hook here?
18:46
Or something like that.
18:47
For example:

  public function alterFieldWidgetMigration(MigrationInterface $migration) {
    $process = [];
    $map = $this->getFieldWidgetMap();
    $this->moduleHandler->alter('migrate_field_plugin_widget_map', $map, $this);
    foreach ($this->getFieldWidgetMap() as $source_widget => $destination_widget) {
      $process['type']['map'][$source_widget] = $destination_widget;
    }
    $migration->mergeProcessOfProperty('options/type', $process);
  }

18:47
That’d be entirely BC, and get you out of your predicament.

Wouldn't that make this 100x easier to support?

quietone’s picture

#8 - I only skimmed this and am not surprised by the comments. Migrating the widgets is hard.

#9 - Good idea to talk to phenaproxima! Yes, I agree that would be better. But let's try it locally first just to be sure.

Wim Leers’s picture

Yes, I agree that would be better. But let's try it locally first just to be sure.

👍

quietone’s picture

Took a while to find this issue again. I found a core issue #3033522: Add methods to customize field to MigrateFieldInterface that adds functionality for FieldPluginBase, unfortunately, there isn't a alterFieldWidgetMigration. Once I get that rerolled, which is taking a long time, and back into shape it will be time to consider adding an alterFieldWidgetMigration.

Wim Leers’s picture

Thanks for that super helpful update! 🤩🙏

quietone’s picture

FileSize
29.02 KB
490.46 KB

Now that I've dabbled in the field migration again I am once frustrated that 'type' can mean so many things.

Whatever I was thinking in #10 I am no longer sure. It is already possible to alter the options/type migration for the widget as well as create a custom method to get the widget type (getFieldWidgetType) is that not enough? Or is the problem that the fixture doesn't have real world data? It is probably a good idea to add the fields that failed from the real world site to this fixture.

This patch adds getFieldWidgetType to the Multiple Select migratefield plugin. Maybe that will help with real world data? This also adds two more fields to the fixture, a list_float and an entityreference, both using the multiple_selects widget. Add to complete the range of tests there are now Functional tests.

Wim Leers’s picture

Title: Migration support » [PP-3] Migration support
FileSize
1023 bytes

Per #3202462-2: [PP-1] Provide option for contrib modules to map their D6 / D7 field formatter and widget plugin IDs to the equivalent D9 plugin ID, if #3204212: Convert remaining widget and formatter type migrations to MigrateField plugins and #3202462: [PP-1] Provide option for contrib modules to map their D6 / D7 field formatter and widget plugin IDs to the equivalent D9 plugin ID were to land, then all we'd need is this:

/**
 * Implements hook_field_migration_field_widget_info().
 */
function multiple_selects_field_migration_field_widget_info() {
  return [
    'entityreference' => ['multiple_selects' => 'multiple_options_select'],
    'node_reference' => ['multiple_selects' => 'multiple_options_select'],
    'user_reference' => ['multiple_selects' => 'multiple_options_select'],
    'taxonomy_term_reference' => ['multiple_selects' => 'multiple_options_select'],
    'list_integer' => ['multiple_selects' => 'multiple_options_select'],
    'list_float' => ['multiple_selects' => 'multiple_options_select'],
    'list_text' => ['multiple_selects' => 'multiple_options_select'],
    'list_boolean' => ['multiple_selects' => 'multiple_options_select'],
    'commerce_product_reference' => ['multiple_selects' => 'multiple_options_select'],
  ];
}

… and we would not be putting the burden of writing complex test coverage on the shoulders of every single field formatter/widget contrib module maintainer. Which is good, because it increases the likelihood that they'll actually work on providing a migration path!

Wim Leers’s picture

@huzooka should be credited for #15 btw 🤓