class AnnotatedClassDiscoveryAutomatedProviders

Same name and namespace in other branches
  1. 9 core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php \Drupal\migrate\Plugin\Discovery\AnnotatedClassDiscoveryAutomatedProviders
  2. 8.9.x core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php \Drupal\migrate\Plugin\Discovery\AnnotatedClassDiscoveryAutomatedProviders
  3. 11.x core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php \Drupal\migrate\Plugin\Discovery\AnnotatedClassDiscoveryAutomatedProviders

Determines providers based on a class's and its parent's namespaces.

@internal This is a temporary solution to the fact that migration source plugins have more than one provider. This functionality will be moved to core in https://www.drupal.org/node/2786355.

Hierarchy

Expanded class hierarchy of AnnotatedClassDiscoveryAutomatedProviders

1 file declares its use of AnnotatedClassDiscoveryAutomatedProviders
MigrateSourcePluginManager.php in core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php

File

core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php, line 21

Namespace

Drupal\migrate\Plugin\Discovery
View source
class AnnotatedClassDiscoveryAutomatedProviders extends AnnotatedClassDiscovery {
  
  /**
   * A utility object that can use active autoloaders to find files for classes.
   *
   * @var \Drupal\Component\ClassFinder\ClassFinderInterface
   */
  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.
   */
  public function __construct($subdir, \Traversable $root_namespaces, $plugin_definition_annotation_name = 'Drupal\\Component\\Annotation\\Plugin', array $annotation_namespaces = []) {
    parent::__construct($subdir, $root_namespaces, $plugin_definition_annotation_name, $annotation_namespaces);
    $this->finder = new ClassFinder();
  }
  
  /**
   * {@inheritdoc}
   */
  protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, ?BaseStaticReflectionParser $parser = NULL) {
    if (!$annotation instanceof MultipleProviderAnnotationInterface) {
      throw new \LogicException('AnnotatedClassDiscoveryAutomatedProviders annotations must implement \\Drupal\\migrate\\Annotation\\MultipleProviderAnnotationInterface');
    }
    $annotation->setClass($class);
    $providers = $annotation->getProviders();
    // Loop through all the parent classes and add their providers (which we
    // infer by parsing their namespaces) to the $providers array.
    do {
      $providers[] = $this->getProviderFromNamespace($parser->getNamespaceName());
    } while ($parser = StaticReflectionParser::getParentParser($parser, $this->finder));
    $providers = array_unique(array_filter($providers, function ($provider) {
      return $provider && $provider !== 'component';
    }));
    $annotation->setProviders($providers);
  }
  
  /**
   * {@inheritdoc}
   */
  public function getDefinitions() {
    $definitions = [];
    $reader = $this->getAnnotationReader();
    // Clear the annotation loaders of any previous annotation classes.
    AnnotationRegistry::reset();
    // Register the namespaces of classes that can be used for annotations.
    AnnotationRegistry::registerLoader('class_exists');
    // Search for classes within all PSR-4 namespace locations.
    foreach ($this->getPluginNamespaces() as $namespace => $dirs) {
      foreach ($dirs as $dir) {
        if (file_exists($dir)) {
          $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS));
          foreach ($iterator as $fileinfo) {
            if ($fileinfo->getExtension() == 'php') {
              if ($cached = $this->fileCache
                ->get($fileinfo->getPathName())) {
                if (isset($cached['id'])) {
                  // Explicitly unserialize this to create a new object instance.
                  $definitions[$cached['id']] = unserialize($cached['content']);
                }
                continue;
              }
              $sub_path = $iterator->getSubIterator()
                ->getSubPath();
              $sub_path = $sub_path ? str_replace(DIRECTORY_SEPARATOR, '\\', $sub_path) . '\\' : '';
              $class = $namespace . '\\' . $sub_path . $fileinfo->getBasename('.php');
              // The filename is already known, so there is no need to find the
              // file. However, StaticReflectionParser needs a finder, so use a
              // mock version.
              $finder = MockFileFinder::create($fileinfo->getPathName());
              $parser = new BaseStaticReflectionParser($class, $finder, FALSE);
              /** @var \Drupal\Component\Annotation\AnnotationInterface $annotation */
              if ($annotation = $reader->getClassAnnotation($parser->getReflectionClass(), $this->pluginDefinitionAnnotationName)) {
                $this->prepareAnnotationDefinition($annotation, $class, $parser);
                $id = $annotation->getId();
                $content = $annotation->get();
                $definitions[$id] = $content;
                // Explicitly serialize this to create a new object instance.
                $this->fileCache
                  ->set($fileinfo->getPathName(), [
                  'id' => $id,
                  'content' => serialize($content),
                ]);
              }
              else {
                // Store a NULL object, so the file is not parsed again.
                $this->fileCache
                  ->set($fileinfo->getPathName(), [
                  NULL,
                ]);
              }
            }
          }
        }
      }
    }
    // Don't let annotation loaders pile up.
    AnnotationRegistry::reset();
    return $definitions;
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
AnnotatedClassDiscovery::$annotationNamespaces protected property Additional namespaces to be scanned for annotation classes.
AnnotatedClassDiscovery::$annotationReader protected property The doctrine annotation reader.
AnnotatedClassDiscovery::$directorySuffix protected property The directory suffix.
AnnotatedClassDiscovery::$fileCache protected property The file cache object.
AnnotatedClassDiscovery::$namespaceSuffix protected property The namespace suffix.
AnnotatedClassDiscovery::$pluginDefinitionAnnotationName protected property The name of the annotation that contains the plugin definition.
AnnotatedClassDiscovery::$pluginNamespaces protected property The namespaces within which to find plugin classes.
AnnotatedClassDiscovery::$rootNamespacesIterator protected property A list of base namespaces with their PSR-4 directories.
AnnotatedClassDiscovery::getAnnotationReader protected function Gets the used doctrine annotation reader. Overrides AnnotatedClassDiscovery::getAnnotationReader
AnnotatedClassDiscovery::getPluginNamespaces protected function Gets an array of PSR-4 namespaces to search for plugin classes. Overrides AnnotatedClassDiscovery::getPluginNamespaces
AnnotatedClassDiscovery::getProviderFromNamespace protected function Extracts the provider name from a Drupal namespace.
AnnotatedClassDiscoveryAutomatedProviders::$finder protected property A utility object that can use active autoloaders to find files for classes.
AnnotatedClassDiscoveryAutomatedProviders::getDefinitions public function Gets the definition of all plugins for this type. Overrides AnnotatedClassDiscovery::getDefinitions
AnnotatedClassDiscoveryAutomatedProviders::prepareAnnotationDefinition protected function Prepares the annotation definition. Overrides AnnotatedClassDiscovery::prepareAnnotationDefinition
AnnotatedClassDiscoveryAutomatedProviders::__construct public function Constructs an AnnotatedClassDiscoveryAutomatedProviders object. Overrides AnnotatedClassDiscovery::__construct
DiscoveryTrait::doGetDefinition protected function Gets a specific plugin definition.
DiscoveryTrait::getDefinition public function 3
DiscoveryTrait::hasDefinition public function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.