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 3b490f0f19..1649700f4c 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 2e61589fb5..f45e95d2cc 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 90803288e4..cf2f4567a8 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 0dd56c9acf..c3e611a4d4 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 c4e7b4981d..732fd3feea 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 9e92619f8e..da9e037328 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 373d1e90b7..8dba3b022a 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 9d184ff86a..3a4cf89f3b 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 45f5b9d239..7a51444109 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 930c13b030..87c3bfe7ac 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 0000000000..3ec65ddece --- /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 ad78bc924d..8225b713f7 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 2b33c858b9..7a9c47907e 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 1579afadc5..ba69b7852c 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 11df8ec243..0c8e9ba705 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 1b43724991..f8a89da1ee 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 74dfd3bcd7..34bed95e08 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 acb9d9cd7e..de55e1337a 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 39f109b697..e7647a1562 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 1023409971..fb3fe7461b 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; @@ -49,6 +51,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. * * @param \Drupal\Core\State\StateInterface $state @@ -59,12 +75,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; } /** @@ -75,7 +97,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 0cbd9ce8bb..ae470954d7 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', '//table[@id="edit-available-module-list-module-list"]//td[text()="' . $available . '"]'); + $session->elementNotExists('xpath', '//table[@id="edit-missing-module-list"]//td[text()="' . $available . '"]'); + } + + // Test the missing migration paths. + $all_missing = $this->getMissingPaths(); + foreach ($all_missing as $missing) { + $session->elementExists('xpath', '//table[@id="edit-missing-module-list"]//td[text()="' . $missing . '"]'); + $session->elementNotExists('xpath', '//table[@id="edit-available-module-list-module-list"]//td[text()="' . $missing . '"]'); + } + $this->drupalPostForm(NULL, [], t('Perform upgrade')); $this->assertText(t('Congratulations, you upgraded Drupal!')); @@ -259,4 +275,20 @@ protected function translatePostValues(array $values) { */ 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 d961faab9e..3717606cd8 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 @@ -80,6 +80,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. */ public function testMigrateUpgrade() { 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 f22a9f7aba..3cfe4bc6d7 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 @@ -84,6 +84,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. */ public function testMigrateUpgrade() { 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 0000000000..b6b5516aa0 --- /dev/null +++ b/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php @@ -0,0 +1,15 @@ +