diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php index 3b490f0f19d741dbe723c7a25ae482add4a19985..1649700f4cd632047f253529daab66d769bbcaaa 100644 --- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php +++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php @@ -11,7 +11,9 @@ * core = {6,7}, * type_map = { * "email" = "email" - * } + * }, + * source_module = "email", + * destination_module = "core" * ) */ class Email extends FieldPluginBase { diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php index 2e61589fb5ef014fa7bb4c660f3d3ded99ff313d..f45e95d2ccb39e126fa36db24432c1bd2c493bcb 100644 --- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php +++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php @@ -10,7 +10,9 @@ * type_map = { * "entityreference" = "entity_reference", * }, - * core = {7} + * core = {7}, + * source_module = "entityreference", + * destination_module = "core" * ) */ class EntityReference extends FieldPluginBase {} diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php index 90803288e47eefc33d15f64e6bdd69f33588f9cb..cf2f4567a80d9098ecf7398a65c2be33093ac6ef 100644 --- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php +++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php @@ -12,7 +12,9 @@ * "number_decimal" = "decimal", * "number_float" = "float", * }, - * core = {7} + * core = {7}, + * source_module = "number", + * destination_module = "core" * ) */ class NumberField extends FieldPluginBase {} diff --git a/core/modules/datetime/src/Plugin/migrate/field/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/DateField.php index 0dd56c9acf2975cabae9abd1262b90c769303902..c3e611a4d4751ce5632f7a51bbe09f0723a94d21 100644 --- a/core/modules/datetime/src/Plugin/migrate/field/DateField.php +++ b/core/modules/datetime/src/Plugin/migrate/field/DateField.php @@ -14,7 +14,9 @@ * "datestamp" = "timestamp", * "datetime" = "datetime", * }, - * core = {6,7} + * core = {6,7}, + * source_module = "date", + * destination_module = "datetime" * ) */ class DateField extends FieldPluginBase { diff --git a/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php index c4e7b4981d3d0d6f6b184ffb4914d1dfffbb706b..732fd3feea98d0433753a257a5bcefcc2810760e 100644 --- a/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php +++ b/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php @@ -16,7 +16,9 @@ * "datestamp" = "timestamp", * "datetime" = "datetime", * }, - * core = {6} + * core = {6}, + * source_module = "date", + * destination_module = "datetime" * ) * * @deprecated in Drupal 8.4.x, to be removed before Drupal 9.0.x. Use diff --git a/core/modules/field/src/Plugin/migrate/source/d7/Field.php b/core/modules/field/src/Plugin/migrate/source/d7/Field.php index 9e92619f8e7819c9f7678821b159481405e8d24f..da9e0373281ce6472d3c5a4fff4a60ac9954a1cd 100644 --- a/core/modules/field/src/Plugin/migrate/source/d7/Field.php +++ b/core/modules/field/src/Plugin/migrate/source/d7/Field.php @@ -15,7 +15,7 @@ * * @MigrateSource( * id = "d7_field", - * source_module = "field" + * source_module = "field_sql_storage" * ) */ class Field extends DrupalSqlBase { diff --git a/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php b/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php index 373d1e90b78a3bae0ba073827eafe3a25506e40d..8dba3b022a62b89e82dca7459de9767e187ffbdd 100644 --- a/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php +++ b/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php @@ -11,7 +11,9 @@ /** * @MigrateCckField( * id = "filefield", - * core = {6} + * core = {6}, + * source_module = "filefield", + * destination_module = "file" * ) * * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use diff --git a/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php b/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php index 9d184ff86a7dd5aed96d83cb746bbf89656fa195..3a4cf89f3bd94c0496698e1a01b03c34a466d0b9 100644 --- a/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php +++ b/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php @@ -11,7 +11,9 @@ /** * @MigrateCckField( * id = "file", - * core = {7} + * core = {7}, + * source_module = "file", + * destination_module = "file" * ) * * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use diff --git a/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php b/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php index 45f5b9d23933f295af1a92d8e9eb45f97cb7f71f..7a5144410940562c564e291a6696a622884537e8 100644 --- a/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php +++ b/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php @@ -10,7 +10,9 @@ /** * @MigrateCckField( * id = "image", - * core = {7} + * core = {7}, + * source_module = "image", + * destination_module = "file" * ) * * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use diff --git a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php b/core/modules/file/src/Plugin/migrate/field/d6/FileField.php index 930c13b030020ca6005cd27a42ff915e4a812c40..87c3bfe7acb249502dafdd5995f9d963df10d960 100644 --- a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php +++ b/core/modules/file/src/Plugin/migrate/field/d6/FileField.php @@ -9,7 +9,9 @@ /** * @MigrateField( * id = "filefield", - * core = {6} + * core = {6}, + * source_module = "filefield", + * destination_module = "file" * ) */ class FileField extends FieldPluginBase { diff --git a/core/modules/file/src/Plugin/migrate/field/d6/ImageField.php b/core/modules/file/src/Plugin/migrate/field/d6/ImageField.php new file mode 100644 index 0000000000000000000000000000000000000000..3ec65ddece3f14b236d45443281bb0ef62ee1bcd --- /dev/null +++ b/core/modules/file/src/Plugin/migrate/field/d6/ImageField.php @@ -0,0 +1,13 @@ +container->get('plugin.manager.migration'); - // Get all the migrations + // Get all the migrations. $migrations = $plugin_manager->createInstances(array_keys($plugin_manager->getDefinitions())); // Ensure the test module was enabled. $this->assertTrue(array_key_exists('migration_provider_test', $migrations)); @@ -55,10 +57,190 @@ public function testProvidersExist() { $this->assertTrue($source_module, new FormattableMarkup('Source module found for @migration_id.', ['@migration_id' => $migration_id])); $this->assertTrue($destination_module, new FormattableMarkup('Destination module found for @migration_id.', ['@migration_id' => $migration_id])); } - // Destination module can't be migrate or migrate_drupal or migrate_drupal_ui + // Destination module can't be migrate or migrate_drupal or + // migrate_drupal_ui. $invalid_destinations = ['migrate', 'migrate_drupal', 'migrate_drupal_ui']; $this->assertNotContains($destination_module, $invalid_destinations, new FormattableMarkup('Invalid destination for @migration_id.', ['@migration_id' => $migration_id])); } } + /** + * Tests that modules exist for all field plugins. + */ + public function testFieldProvidersExist() { + $expected_mappings = [ + 'userreference' => [ + 'source_module' => 'user_reference', + 'destination_module' => 'core', + ], + 'nodereference' => [ + 'source_module' => 'node_reference', + 'destination_module' => 'core', + ], + 'optionwidgets' => [ + 'source_module' => 'optionwidgets', + 'destination_module' => 'options', + ], + 'list' => [ + 'source_module' => 'list', + 'destination_module' => 'options', + ], + 'options' => [ + 'source_module' => 'options', + 'destination_module' => 'options', + ], + 'filefield' => [ + 'source_module' => 'filefield', + 'destination_module' => 'file', + ], + 'imagefield' => [ + 'source_module' => 'imagefield', + 'destination_module' => 'file', + ], + 'file' => [ + 'source_module' => 'file', + 'destination_module' => 'file', + ], + 'image' => [ + 'source_module' => 'image', + 'destination_module' => 'file', + ], + 'phone' => [ + 'source_module' => 'phone', + 'destination_module' => 'telephone', + ], + 'link' => [ + 'source_module' => 'link', + 'destination_module' => 'link', + ], + 'link_field' => [ + 'source_module' => 'link', + 'destination_module' => 'link', + ], + 'd6_text' => [ + 'source_module' => 'text', + 'destination_module' => 'text', + ], + 'd7_text' => [ + 'source_module' => 'text', + 'destination_module' => 'text', + ], + 'taxonomy_term_reference' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'core', + ], + 'date' => [ + 'source_module' => 'date', + 'destination_module' => 'datetime', + ], + 'datetime' => [ + 'source_module' => 'date', + 'destination_module' => 'datetime', + ], + 'email' => [ + 'source_module' => 'email', + 'destination_module' => 'core', + ], + 'number_default' => [ + 'source_module' => 'number', + 'destination_module' => 'core', + ], + 'entityreference' => [ + 'source_module' => 'entityreference', + 'destination_module' => 'core', + ], + ]; + // Install all available modules. + $module_handler = $this->container->get('module_handler'); + $modules = $this->coreModuleListDataProvider(); + $modules_enabled = $module_handler->getModuleList(); + $modules_to_enable = array_keys(array_diff_key($modules, $modules_enabled)); + $this->enableModules($modules_to_enable); + + /** @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager $plugin_manager */ + $plugin_manager = $this->container->get('plugin.manager.migrate.field'); + $definitions = $plugin_manager->getDefinitions(); + foreach ($definitions as $key => $definition) { + $this->assertArrayHasKey($key, $expected_mappings); + $this->assertEquals($expected_mappings[$key]['source_module'], $definition['source_module']); + $this->assertEquals($expected_mappings[$key]['destination_module'], $definition['destination_module']); + } + } + + /** + * Test a missing required definition. + * + * @param array $definitions + * A field plugin definition. + * @param string $missing_property + * The name of the property missing from the definition. + * + * @dataProvider fieldPluginDefinitionsProvider + */ + public function testFieldProviderMissingRequiredProperty(array $definitions, $missing_property) { + $discovery = $this->getMockBuilder(MigrateFieldPluginManager::class) + ->disableOriginalConstructor() + ->setMethods(['getDefinitions']) + ->getMock(); + $discovery->method('getDefinitions') + ->willReturn($definitions); + + $plugin_manager = $this->getMockBuilder(MigrateFieldPluginManager::class) + ->disableOriginalConstructor() + ->setMethods(['getDiscovery']) + ->getMock(); + $plugin_manager->method('getDiscovery') + ->willReturn($discovery); + + $this->setExpectedException(BadPluginDefinitionException::class, "The missing_{$missing_property} plugin should define the $missing_property property."); + $plugin_manager->getDefinitions(); + } + + /** + * Data provider for field plugin definitions. + * + * @return array + * Array of plugin definitions. + */ + public function fieldPluginDefinitionsProvider() { + return [ + 'missing_core_scenario' => [ + 'definitions' => [ + 'missing_core' => [ + 'source_module' => 'migrate', + 'destination_module' => 'migrate', + 'id' => 'missing_core', + 'class' => 'foo', + 'provider' => 'foo', + ], + ], + 'missing_property' => 'core', + ], + 'missing_source_scenario' => [ + 'definitions' => [ + 'missing_source_module' => [ + 'core' => [6, 7], + 'destination_module' => 'migrate', + 'id' => 'missing_source_module', + 'class' => 'foo', + 'provider' => 'foo', + ], + ], + 'missing_property' => 'source_module', + ], + 'missing_destination_scenario' => [ + 'definitions' => [ + 'missing_destination_module' => [ + 'core' => [6, 7], + 'source_module' => 'migrate', + 'id' => 'missing_destination_module', + 'class' => 'foo', + 'provider' => 'foo', + ], + ], + 'missing_property' => 'destination_module', + ], + ]; + } + } diff --git a/core/modules/migrate_drupal/src/Annotation/MigrateField.php b/core/modules/migrate_drupal/src/Annotation/MigrateField.php index ad78bc924d5f7220885d6db9d771bf58041fa72c..8225b713f70b0097ea952688df6915378e1ba3da 100644 --- a/core/modules/migrate_drupal/src/Annotation/MigrateField.php +++ b/core/modules/migrate_drupal/src/Annotation/MigrateField.php @@ -49,6 +49,26 @@ public function __construct($values) { * * @var int[] */ - public $core = []; + public $core; + + /** + * Identifies the system providing the data the field plugin will read. + * + * The source_module is expected to be the name of a Drupal module that must + * must be installed in the source database. + * + * @var string + */ + public $source_module; + + /** + * Identifies the system handling the data the destination plugin will write. + * + * The destination_module is expected to be the name of a Drupal module on the + * destination site that must be installed. + * + * @var string + */ + public $destination_module; } diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php index 2b33c858b990c9fa698c600d5211d6b9049b268f..7a9c47907eb77fd66fa79337d45f3082a7bba4f2 100644 --- a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php +++ b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php @@ -3,6 +3,7 @@ namespace Drupal\migrate_drupal\Plugin; use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\migrate\Plugin\Exception\BadPluginDefinitionException; use Drupal\migrate\Plugin\MigratePluginManager; use Drupal\migrate\Plugin\MigrationInterface; @@ -53,4 +54,17 @@ public function getPluginIdFromFieldType($field_type, array $configuration = [], throw new PluginNotFoundException($field_type); } + /** + * {@inheritdoc} + */ + public function processDefinition(&$definition, $plugin_id) { + parent::processDefinition($definition, $plugin_id); + + foreach (['core', 'source_module', 'destination_module'] as $required_property) { + if (empty($definition[$required_property])) { + throw new BadPluginDefinitionException($plugin_id, $required_property); + } + } + } + } diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php index 1579afadc594c792f733d61761b3cebd6c23eba2..ba69b7852c1c0dc3bda89cd7b3ba79ccb0021b75 100644 --- a/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php @@ -11,6 +11,8 @@ * type_map = { * "nodereference" = "entity_reference", * }, + * source_module = "node_reference", + * destination_module = "core", * ) */ class NodeReference extends FieldPluginBase { diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php index 11df8ec243838a2b537bc265cb334187f947b5ec..0c8e9ba705babe16804702a10fbd24456baa07de 100644 --- a/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php +++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php @@ -11,6 +11,8 @@ * type_map = { * "userreference" = "entity_reference", * }, + * source_module = "user_reference", + * destination_module = "core", * ) */ class UserReference extends FieldPluginBase { diff --git a/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6FileField.php b/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6FileField.php index 1b43724991204778f12a685a6673177a474ba150..f8a89da1ee6f514cc8a4b929b8b7bbe8aedf9300 100644 --- a/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6FileField.php +++ b/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6FileField.php @@ -11,7 +11,9 @@ * core = {6}, * type_map = { * "file" = "file" - * } + * }, + * source_module = "foo", + * destination_module = "bar" * ) */ class D6FileField extends CckFieldPluginBase { diff --git a/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6NoCoreVersionSpecified.php b/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6NoCoreVersionSpecified.php index 74dfd3bcd74a759af8b41aabc1deb238007b0c42..34bed95e08f33df0f14741d3d9afa077aaaaac8b 100644 --- a/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6NoCoreVersionSpecified.php +++ b/core/modules/migrate_drupal/tests/modules/migrate_cckfield_plugin_manager_test/src/Plugin/migrate/cckfield/D6NoCoreVersionSpecified.php @@ -7,7 +7,9 @@ /** * @MigrateCckField( - * id = "d6_no_core_version_specified" + * id = "d6_no_core_version_specified", + * source_module = "foo", + * destination_module = "bar", * ) */ class D6NoCoreVersionSpecified extends CckFieldPluginBase { diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php index acb9d9cd7eb7e28a4eaae561738c49fa2fa8f7d1..de55e1337a5146f2c5dfdebe3e0b8366093fe457 100644 --- a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php +++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php @@ -10,7 +10,9 @@ * core = {6}, * type_map = { * "file" = "file" - * } + * }, + * source_module = "foo", + * destination_module = "bar" * ) */ class D6FileField extends FieldPluginBase {} diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php index 39f109b6972c09af7829439bc8fad8cbfb3e1a96..e7647a1562a2de0fe75a8b8790455f0cebc85206 100644 --- a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php +++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php @@ -6,10 +6,9 @@ /** * @MigrateField( - * id = "d6_no_core_version_specified" + * id = "d6_no_core_version_specified", + * source_module = "foo", + * destination_module = "bar", * ) */ -class D6NoCoreVersionSpecified extends FieldPluginBase { - - -} +class D6NoCoreVersionSpecified extends FieldPluginBase {} diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php index eb192afe86d7daced10839565047472869bcea8e..f238504495306d862daaa04fc9ad0faa24e9a220 100644 --- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php @@ -3,12 +3,14 @@ namespace Drupal\migrate_drupal_ui\Form; use Drupal\Core\Datetime\DateFormatterInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\RendererInterface; use Drupal\Core\State\StateInterface; use Drupal\Core\Url; use Drupal\migrate\Plugin\MigrationPluginManagerInterface; +use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface; use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch; use Drupal\migrate_drupal\MigrationConfigurationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -50,6 +52,20 @@ class MigrateUpgradeForm extends ConfirmFormBase { */ protected $pluginManager; + /** + * The field plugin manager. + * + * @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface + */ + protected $fieldPluginManager; + + /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + /** * Constructs the MigrateUpgradeForm. * @@ -61,12 +77,18 @@ class MigrateUpgradeForm extends ConfirmFormBase { * The renderer service. * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $plugin_manager * The migration plugin manager. + * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager + * The field plugin manager. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. */ - public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager) { + public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, ModuleHandlerInterface $module_handler) { $this->state = $state; $this->dateFormatter = $date_formatter; $this->renderer = $renderer; $this->pluginManager = $plugin_manager; + $this->fieldPluginManager = $field_plugin_manager; + $this->moduleHandler = $module_handler; } /** @@ -77,7 +99,9 @@ public static function create(ContainerInterface $container) { $container->get('state'), $container->get('date.formatter'), $container->get('renderer'), - $container->get('plugin.manager.migration') + $container->get('plugin.manager.migration'), + $container->get('plugin.manager.migrate.field'), + $container->get('module_handler') ); } @@ -439,7 +463,12 @@ public function submitCredentialForm(array &$form, FormStateInterface $form_stat } /** - * Confirmation form for missing migrations, etc. + * Confirmation form showing available and missing migration paths. + * + * The confirmation form uses the source_module and destination_module + * properties on the source, destination and field plugins as well as the + * system data from the source to determine if there is a migration path for + * each module in the source. * * @param array $form * An associative array containing the structure of the form. @@ -456,8 +485,9 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) { $form['actions']['submit']['#value'] = $this->t('Perform upgrade'); $version = $form_state->get('version'); - $migrations = $this->getMigrations('migrate_drupal_' . $version, $version); + // Get the source_module and destination_module for each migration. + $migrations = $this->getMigrations('migrate_drupal_' . $version, $version); $table_data = []; foreach ($migrations as $migration) { $migration_id = $migration->getPluginId(); @@ -474,6 +504,15 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) { $table_data[$source_module][$destination_module][$migration_id] = $migration->label(); } } + + // Get the source_module and destination_module from the field plugins. + $definitions = $this->fieldPluginManager->getDefinitions(); + foreach ($definitions as $definition) { + $source_module = $definition['source_module']; + $destination_module = $definition['destination_module']; + $table_data[$source_module][$destination_module][$definition['id']] = $definition['id']; + } + // Sort the table by source module names and within that destination // module names. ksort($table_data); @@ -483,6 +522,11 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) { // Fetch the system data at the first opportunity. $system_data = $form_state->get('system_data'); + // Remove core profiles from the system data. + foreach (['standard', 'minimal'] as $profile) { + unset($system_data['module'][$profile]); + } + $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data); // Missing migrations. diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php index 0b39b2bcc9c0ff388878f475fd0fdb138a62f68c..09dc9691e3fb3f726c6d2853fcd6a1b49b7f06ba 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php @@ -178,6 +178,22 @@ public function testMigrateUpgrade() { $this->assertSession()->pageTextNotContains(t('Destination module not found for migration_provider_test')); // Ensure there are no errors about any other missing migration providers. $this->assertSession()->pageTextNotContains(t('module not found')); + + // Test the available migration paths. + $all_available = $this->getAvailablePaths(); + $session = $this->assertSession(); + foreach ($all_available as $available) { + $session->elementExists('xpath', "//span[contains(@class, 'checked') and text() = '$available']"); + $session->elementNotExists('xpath', "//span[contains(@class, 'warning') and text() = '$available']"); + } + + // Test the missing migration paths. + $all_missing = $this->getMissingPaths(); + foreach ($all_missing as $missing) { + $session->elementExists('xpath', "//span[contains(@class, 'warning') and text() = '$missing']"); + $session->elementNotExists('xpath', "//span[contains(@class, 'checked') and text() = '$missing']"); + } + $this->drupalPostForm(NULL, [], t('Perform upgrade')); $this->assertText(t('Congratulations, you upgraded Drupal!')); @@ -259,4 +275,20 @@ abstract protected function getSourceBasePath(); */ abstract protected function getEntityCounts(); + /** + * Gets the available upgrade paths. + * + * @return string[] + * An array of available upgrade paths. + */ + abstract protected function getAvailablePaths(); + + /** + * Gets the missing upgrade paths. + * + * @return string[] + * An array of missing upgrade paths. + */ + abstract protected function getMissingPaths(); + } diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php index d961faab9ecdfb8c09e1c3aa43d539032a3e1caf..3717606cd846963e0291466bed9f50697e1f7fc2 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php @@ -79,6 +79,72 @@ protected function getEntityCounts() { ]; } + /** + * {@inheritdoc} + */ + protected function getAvailablePaths() { + return [ + 'aggregator', + 'block', + 'book', + 'comment', + 'contact', + 'content', + 'date', + 'dblog', + 'email', + 'entityreference', + 'file', + 'filefield', + 'filter', + 'i18ntaxonomy', + 'image', + 'imagecache', + 'imagefield', + 'link', + 'list', + 'menu', + 'locale', + 'node', + 'node_reference', + 'number', + 'options', + 'optionwidgets', + 'path', + 'phone', + 'profile', + 'search', + 'system', + 'taxonomy', + 'text', + 'translation', + 'upload', + 'user', + 'user_reference', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getMissingPaths() { + return [ + 'date_api', + 'date_timezone', + 'event', + 'i18n', + 'i18nblocks', + 'i18ncck', + 'i18ncontent', + 'i18nmenu', + 'i18nprofile', + 'i18nstrings', + 'imageapi', + 'php', + 'variable_admin', + ]; + } + /** * Executes all steps of migrations upgrade. */ diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php index f22a9f7aba35f4122efa9168ebb10b8ae2537251..3cfe4bc6d711b12a8fab1bd08a88bb7bddde038d 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php @@ -83,6 +83,74 @@ protected function getEntityCounts() { ]; } + /** + * {@inheritdoc} + */ + protected function getAvailablePaths() { + return [ + 'aggregator', + 'block', + 'comment', + 'contact', + 'date', + 'dblog', + 'email', + 'entityreference', + 'field', + 'field_sql_storage', + 'file', + 'filefield', + 'filter', + 'forum', + 'image', + 'imagefield', + 'link', + 'list', + 'locale', + 'menu', + 'node', + 'node_reference', + 'number', + 'options', + 'optionwidgets', + 'path', + 'phone', + 'search', + 'shortcut', + 'statistics', + 'system', + 'taxonomy', + 'text', + 'translation', + 'user', + 'user_reference', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getMissingPaths() { + return [ + 'blog', + 'book', + 'color', + 'contextual', + 'date_api', + 'entity', + 'field_ui', + 'help', + 'php', + 'rdf', + 'simpletest', + 'syslog', + 'toolbar', + 'tracker', + 'trigger', + 'update', + ]; + } + /** * Executes all steps of migrations upgrade. */ diff --git a/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php b/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php new file mode 100644 index 0000000000000000000000000000000000000000..b6b5516aa002c2749818f5cbc421cb0a52119421 --- /dev/null +++ b/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php @@ -0,0 +1,15 @@ +