diff --git a/core/lib/Drupal/Component/Annotation/AnnotationInterface.php b/core/lib/Drupal/Component/Annotation/AnnotationInterface.php index 6b40aee..bbb86cd 100644 --- a/core/lib/Drupal/Component/Annotation/AnnotationInterface.php +++ b/core/lib/Drupal/Component/Annotation/AnnotationInterface.php @@ -13,18 +13,16 @@ public function get(); /** - * Gets the name(s) of the provider(s) of the annotated class. + * Gets the name of the provider of the annotated class. * - * @return string|array - * Can be str4ing or array because of backwards compatibility reasons. + * @return string */ public function getProvider(); /** - * Sets the name(s) of the provider(s) of the annotated class. + * Sets the name of the provider(s) of the annotated class. * - * @param string|array $provider - * Can be str4ing or array because of backwards compatibility reasons. + * @param array|string $provider */ public function setProvider($provider); diff --git a/core/lib/Drupal/Component/Annotation/Plugin.php b/core/lib/Drupal/Component/Annotation/Plugin.php index 29f3675..d1f7e46 100644 --- a/core/lib/Drupal/Component/Annotation/Plugin.php +++ b/core/lib/Drupal/Component/Annotation/Plugin.php @@ -78,7 +78,9 @@ public function get() { * {@inheritdoc} */ public function getProvider() { - return isset($this->definition['provider']) ? $this->definition['provider'] : FALSE; + if (isset($this->definition['provider'])) { + return is_array(isset($this->definition['provider'])) ? reset($this->definition['provider']) : $this->definition['provider']; + } } /** diff --git a/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php index 77ebb23..a35b22c 100644 --- a/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php +++ b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -19,7 +19,7 @@ class AnnotatedClassDiscovery implements DiscoveryInterface { use DiscoveryTrait; /** - * Whether the parser should return only wants class annotations. + * Whether the parser should return only class annotations. */ const CLASS_ANNOTATION_OPTIMIZE = TRUE; diff --git a/core/lib/Drupal/Component/Plugin/Discovery/StaticReflectionParser.php b/core/lib/Drupal/Component/Plugin/Discovery/StaticReflectionParser.php index 3789544..0744f1a 100644 --- a/core/lib/Drupal/Component/Plugin/Discovery/StaticReflectionParser.php +++ b/core/lib/Drupal/Component/Plugin/Discovery/StaticReflectionParser.php @@ -1,6 +1,6 @@ processDefinition($definition, $plugin_id); } $this->alterDefinitions($definitions); - return ProviderFilterDecorator::filterDefinitions($definitions, function ($provider) { return $this->providerExists($provider); }); + return ProviderFilterDecorator::filterDefinitions($definitions, function ($provider) { + return $this->providerExists($provider); + }); } /** diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php index 0d11a9f..5e6a3c6 100644 --- a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php @@ -2,8 +2,10 @@ namespace Drupal\Core\Plugin\Discovery; +use Composer\Autoload\ClassLoader; use Doctrine\Common\Reflection\StaticReflectionParser as BaseStaticReflectionParser; use Drupal\Component\Annotation\AnnotationInterface; +use Drupal\Component\Plugin\Discovery\StaticReflectionParser; /** * Adds the namespaces in the plugin class use statements as providers. @@ -16,16 +18,44 @@ class AnnotatedClassDiscoveryAutomatedProviders extends AnnotatedClassDiscovery const CLASS_ANNOTATION_OPTIMIZE = FALSE; /** + * @var \Composer\Autoload\ClassLoader + */ + protected $finder; + + /** + * Constructs an AnnotatedClassDiscoveryAutomatedProviders object. + * + * @param string $subdir + * Either the plugin's subdirectory, for example 'Plugin/views/filter', or + * empty string if plugins are located at the top level of the namespace. + * @param \Traversable $root_namespaces + * An object that implements \Traversable which contains the root paths + * keyed by the corresponding namespace to look for plugin implementations. + * If $subdir is not an empty string, it will be appended to each namespace. + * @param string $plugin_definition_annotation_name + * The name of the annotation that contains the plugin definition. + * Defaults to 'Drupal\Component\Annotation\Plugin'. + * @param string[] $annotation_namespaces + * Additional namespaces to scan for annotation definitions. + * @param \Composer\Autoload\ClassLoader $finder + * The class loader already know where to find the classes so it is reused + * as the class finder. + */ + public function __construct($subdir, \Traversable $root_namespaces, $plugin_definition_annotation_name, $annotation_namespaces, ClassLoader $finder) { + parent::__construct($subdir, $root_namespaces, $plugin_definition_annotation_name, $annotation_namespaces); + $this->finder = $finder; + } + + /** * {@inheritdoc} */ protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, BaseStaticReflectionParser $parser) { parent::prepareAnnotationDefinition($annotation, $class, $parser); - $finder = \Drupal::service('class_loader'); $providers = (array) $annotation->getProvider(); do { $new_providers = array_map([$this, 'getProviderFromNamespace'], $parser->getUseStatements()); $providers = array_merge($providers, $new_providers); - } while ($parser = StaticReflectionParser::getParentParser($parser, $finder)); + } while ($parser = StaticReflectionParser::getParentParser($parser, $this->finder)); $annotation->setProvider(array_unique(array_filter($providers))); } diff --git a/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php index 26ecb40..24cde50 100644 --- a/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php @@ -4,7 +4,6 @@ use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Component\Plugin\Discovery\DiscoveryTrait; -use Drupal\Core\Extension\ModuleHandlerInterface; /** * Remove plugin definitions with non-existing providers. @@ -59,7 +58,10 @@ public static function filterDefinitions(array $definitions, callable $provider_ return in_array($provider, ['core', 'component']) || $provider_exists($provider); }; return array_filter($definitions, function ($definition) use ($provider_exists) { + // Plugin definitions can be objects (for example, Typed Data) those will + // become empty array here and cause no problems. $definition = (array) $definition + ['provider' => []]; + // There can be one or many providers, handle them as multiple always. $providers = (array) $definition['provider']; return count($providers) == count(array_filter($providers, $provider_exists)); }); diff --git a/core/modules/migrate/migrate.services.yml b/core/modules/migrate/migrate.services.yml index 254de2a..c9a6457 100644 --- a/core/modules/migrate/migrate.services.yml +++ b/core/modules/migrate/migrate.services.yml @@ -7,7 +7,7 @@ services: arguments: [migrate] plugin.manager.migrate.source: class: Drupal\migrate\Plugin\MigrateSourcePluginManager - arguments: [source, '@container.namespaces', '@cache.discovery', '@module_handler', 'Drupal\migrate\Annotation\MigrateSource'] + arguments: [source, '@container.namespaces', '@cache.discovery', '@module_handler', '@class_loader'] plugin.manager.migrate.process: class: Drupal\migrate\Plugin\MigratePluginManager arguments: [process, '@container.namespaces', '@cache.discovery', '@module_handler', 'Drupal\migrate\Annotation\MigrateProcessPlugin'] diff --git a/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php b/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php index b5112c9..bd8bd26 100644 --- a/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php +++ b/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php @@ -2,6 +2,9 @@ namespace Drupal\migrate\Plugin; +use Composer\Autoload\ClassLoader; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscoveryAutomatedProviders; use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; @@ -18,11 +21,38 @@ class MigrateSourcePluginManager extends MigratePluginManager { /** + * @var \Composer\Autoload\ClassLoader + */ + protected $classLoader; + + /** + * MigrateSourcePluginManager constructor. + * + * @param string $type + * The type of the plugin: row, source, process, destination, entity_field, + * id_map. + * @param \Traversable $namespaces + * An object that implements \Traversable which contains the root paths + * keyed by the corresponding namespace to look for plugin implementations. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend + * Cache backend instance to use. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler to invoke the alter hook with. + * @param \Composer\Autoload\ClassLoader $class_loader + * Guess what a ClassLoader object could be. Perhaps the class loader? + */ + public function __construct($type, \Traversable $namespaces, \Drupal\Core\Cache\CacheBackendInterface $cache_backend, \Drupal\Core\Extension\ModuleHandlerInterface $module_handler, ClassLoader $class_loader) { + parent::__construct($type, $namespaces, $cache_backend, $module_handler, 'Drupal\migrate\Annotation\MigrateSource'); + $this->classLoader = $class_loader; + + } + + /** * {@inheritdoc} */ protected function getDiscovery() { if (!$this->discovery) { - $discovery = new AnnotatedClassDiscoveryAutomatedProviders($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces); + $discovery = new AnnotatedClassDiscoveryAutomatedProviders($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces, $this->classLoader); $this->discovery = new ContainerDerivativeDiscoveryDecorator($discovery); } return $this->discovery;