diff -u b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php --- b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php @@ -2,28 +2,26 @@ namespace Drupal\Core\Plugin\Discovery; - use Doctrine\Common\Reflection\StaticReflectionParser; use Drupal\Component\Annotation\AnnotationInterface; +/** + * Adds the namespaces in the plugin class use statements as providers. + */ class AnnotatedClassDiscoveryAutomatedProviders extends AnnotatedClassDiscovery { /** * {@inheritdoc} */ protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, StaticReflectionParser $parser) { - $provider_set = $annotation->getProvider(); parent::prepareAnnotationDefinition($annotation, $class, $parser); - - if (!$provider_set) { - $namespaces[$annotation->getProvider()] = TRUE; - foreach ($parser->getUseStatements() as $class) { - if ($namespace = AnnotatedClassDiscovery::getProviderFromNamespace($class)) { - $namespaces[strtolower($namespace)] = TRUE; - } + $providers = array_flip((array) $annotation->getProvider()); + foreach ($parser->getUseStatements() as $class) { + if ($provider = AnnotatedClassDiscovery::getProviderFromNamespace($class)) { + $providers[strtolower($provider)] = TRUE; } - $annotation->setProvider(array_keys($namespaces)); } + $annotation->setProvider(array_keys($providers)); } } reverted: --- b/core/modules/migrate/src/Plugin/InheritProviderDecorator.php +++ /dev/null @@ -1,52 +0,0 @@ -decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function getDefinitions() { - $source_plugin_manager = \Drupal::service('plugin.manager.migrate.source'); - return array_map(function (array $definition) use ($source_plugin_manager) { - if (!isset($definition['provider'])) { - $source_plugin_definition = $source_plugin_manager->getDefinition($definition['source']['plugin']); - if (isset($source_plugin_definition['provider'])) { - $definition['provider'] = array_merge($definition['provider'], $source_plugin_definition['provider']); - } - } - return $definition; - }, $this->decorated->getDefinitions()); - } - - /** - * Passes through all unknown calls onto the decorated object. - */ - public function __call($method, $args) { - return call_user_func_array(array($this->decorated, $method), $args); - } - -} diff -u b/core/modules/migrate/src/Plugin/MigrationPluginManager.php b/core/modules/migrate/src/Plugin/MigrationPluginManager.php --- b/core/modules/migrate/src/Plugin/MigrationPluginManager.php +++ b/core/modules/migrate/src/Plugin/MigrationPluginManager.php @@ -69,8 +69,14 @@ }, $this->moduleHandler->getModuleDirectories()); $yaml_discovery = new YamlDirectoryDiscovery($directories, 'migrate'); - $inherited_discovery = new InheritProviderDecorator($yaml_discovery); - $filtered_discovery = new ProviderFilterDecorator($inherited_discovery, [$this->moduleHandler, 'moduleExists']); + // This gets rid of migration which try to use a non-existing source + // plugin. The common case for this is the source plugin defining a + // non-existing provider like migrate_drupal. + $only_with_source_discovery = new NoSourcePluginDecorator($yaml_discovery); + // This gets rid of migrations with explicit providers set if one of the + // providers do not exist before we try to use a potentially non-existing + // deriver. This is a rare case. + $filtered_discovery = new ProviderFilterDecorator($only_with_source_discovery, [$this->moduleHandler, 'moduleExists']); $this->discovery = new ContainerDerivativeDiscoveryDecorator($filtered_discovery); } return $this->discovery; only in patch2: unchanged: --- a/core/modules/block_content/migration_templates/block_content_body_field.yml +++ b/core/modules/block_content/migration_templates/block_content_body_field.yml @@ -30,3 +30,6 @@ destination: migration_dependencies: required: - block_content_type +provider: + - block_content + - migrate_drupal only in patch2: unchanged: --- a/core/modules/block_content/migration_templates/block_content_type.yml +++ b/core/modules/block_content/migration_templates/block_content_type.yml @@ -17,3 +17,6 @@ process: label: label destination: plugin: entity:block_content_type +provider: + - block_content + - migrate_drupal only in patch2: unchanged: --- a/core/modules/comment/src/Plugin/migrate/source/d6/CommentVariablePerCommentType.php +++ b/core/modules/comment/src/Plugin/migrate/source/d6/CommentVariablePerCommentType.php @@ -4,7 +4,8 @@ /** * @MigrateSource( - * id = "d6_comment_variable_per_comment_type" + * id = "d6_comment_variable_per_comment_type", + * provider = "migrate_drupal", * ) */ class CommentVariablePerCommentType extends CommentVariable { only in patch2: unchanged: --- a/core/modules/field/src/Plugin/migrate/source/d6/FieldInstancePerViewMode.php +++ b/core/modules/field/src/Plugin/migrate/source/d6/FieldInstancePerViewMode.php @@ -9,7 +9,8 @@ * * @MigrateSource( * id = "d6_field_instance_per_view_mode", - * source_provider = "content" + * source_provider = "content", + * provider = "migrate_drupal", * ) */ class FieldInstancePerViewMode extends ViewModeBase { only in patch2: unchanged: --- /dev/null +++ b/core/modules/migrate/src/Plugin/NoSourcePluginDecorator.php @@ -0,0 +1,47 @@ +decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function getDefinitions() { + /** @var \Drupal\Component\Plugin\PluginManagerInterface $source_plugin_manager */ + $source_plugin_manager = \Drupal::service('plugin.manager.migrate.source'); + return array_filter($this->decorated->getDefinitions(), function (array $definition) use ($source_plugin_manager) { + return $source_plugin_manager->hasDefinition($definition['source']['plugin']); + }); + } + + /** + * Passes through all unknown calls onto the decorated object. + */ + public function __call($method, $args) { + return call_user_func_array(array($this->decorated, $method), $args); + } + +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php @@ -0,0 +1,108 @@ +container->get('plugin.manager.migration')->getDefinitions(); + // All the plugins provided by core depend on migrate_drupal. + $this->assertEmpty($migration_plugins); + + // Enable a module that provides migrations that do not depend on + // migrate_drupal. + $this->enableModules(['migrate_external_translated_test']); + $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); + // All the plugins provided by migrate_external_translated_test do depend + // not on migrate_drupal. + $this::assertArrayHasKey('external_translated_test_node', $migration_plugins); + $this::assertArrayHasKey('external_translated_test_node_translation', $migration_plugins); + + // Disable the test module and the list should be empty again. + $this->disableModules(['migrate_external_translated_test']); + $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); + // All the plugins provided by core depend on migrate_drupal. + $this->assertEmpty($migration_plugins); + + // Enable migrate_drupal to test that the plugins can now be discovered. + $this->enableModules(['migrate_drupal']); + // Set up a migrate database connection so that plugin disocovery works. + // Clone the current connection and replace the current prefix. + $connection_info = Database::getConnectionInfo('migrate'); + if ($connection_info) { + Database::renameConnection('migrate', 'simpletest_original_migrate'); + } + $connection_info = Database::getConnectionInfo('default'); + foreach ($connection_info as $target => $value) { + $prefix = is_array($value['prefix']) ? $value['prefix']['default'] : $value['prefix']; + // Simpletest uses 7 character prefixes at most so this can't cause + // collisions. + $connection_info[$target]['prefix']['default'] = $prefix . '0'; + + // Add the original simpletest prefix so SQLite can attach its database. + // @see \Drupal\Core\Database\Driver\sqlite\Connection::init() + $connection_info[$target]['prefix'][$value['prefix']['default']] = $value['prefix']['default']; + } + Database::addConnectionInfo('migrate', 'default', $connection_info['default']); + + $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); + // All the plugins provided by core depend on migrate_drupal. + $this->assertNotEmpty($migration_plugins); + } + +} only in patch2: unchanged: --- a/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php +++ b/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php @@ -7,7 +7,8 @@ * Drupal 6 node revision source from database. * * @MigrateSource( - * id = "d6_node_revision" + * id = "d6_node_revision", + * provider = "migrate_drupal", * ) */ class NodeRevision extends Node { only in patch2: unchanged: --- a/core/modules/node/src/Plugin/migrate/source/d6/ViewMode.php +++ b/core/modules/node/src/Plugin/migrate/source/d6/ViewMode.php @@ -7,7 +7,8 @@ * * @MigrateSource( * id = "d6_view_mode", - * source_provider = "content" + * source_provider = "content", + * provider = "migrate_drupal", * ) */ class ViewMode extends ViewModeBase { only in patch2: unchanged: --- a/core/modules/node/src/Plugin/migrate/source/d7/NodeRevision.php +++ b/core/modules/node/src/Plugin/migrate/source/d7/NodeRevision.php @@ -7,7 +7,8 @@ * * @MigrateSource( * id = "d7_node_revision", - * source_provider = "node" + * source_provider = "node", + * provider = "migrate_drupal", * ) */ class NodeRevision extends Node { only in patch2: unchanged: --- a/core/modules/path/src/Plugin/migrate/source/d6/UrlAlias.php +++ b/core/modules/path/src/Plugin/migrate/source/d6/UrlAlias.php @@ -9,7 +9,8 @@ * * @MigrateSource( * id = "d6_url_alias", - * source_provider = "path" + * source_provider = "path", + * provider = "migrate_drupal", * ) */ class UrlAlias extends UrlAliasBase { only in patch2: unchanged: --- a/core/modules/path/src/Plugin/migrate/source/d7/UrlAlias.php +++ b/core/modules/path/src/Plugin/migrate/source/d7/UrlAlias.php @@ -9,7 +9,8 @@ * * @MigrateSource( * id = "d7_url_alias", - * source_provider = "path" + * source_provider = "path", + * provider = "migrate_drupal", * ) */ class UrlAlias extends UrlAliasBase { only in patch2: unchanged: --- a/core/modules/taxonomy/src/Plugin/migrate/source/d6/TermNodeRevision.php +++ b/core/modules/taxonomy/src/Plugin/migrate/source/d6/TermNodeRevision.php @@ -6,7 +6,8 @@ * Source returning tids from the term_node table for the non-current revision. * * @MigrateSource( - * id = "d6_term_node_revision" + * id = "d6_term_node_revision", + * provider = "migrate_drupal", * ) */ class TermNodeRevision extends TermNode { only in patch2: unchanged: --- a/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php +++ b/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php @@ -7,7 +7,8 @@ * * @MigrateSource( * id = "d6_taxonomy_vocabulary_per_type", - * source_provider = "taxonomy" + * source_provider = "taxonomy", + * provider = "migrate_drupal", * ) */ class VocabularyPerType extends Vocabulary { only in patch2: unchanged: --- a/core/modules/taxonomy/tests/modules/taxonomy_term_stub_test/migrations/taxonomy_term_stub_test.yml +++ b/core/modules/taxonomy/tests/modules/taxonomy_term_stub_test/migrations/taxonomy_term_stub_test.yml @@ -27,3 +27,6 @@ destination: migration_dependencies: required: - vocabularies +provider: + - migrate_drupal + - taxonomy