1. 8.3.x core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  2. 8.3.x core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  3. 8.0.x core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  4. 8.0.x core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  5. 8.1.x core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  6. 8.1.x core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  7. 8.2.x core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  8. 8.2.x core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  9. 8.4.x core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery
  10. 8.4.x core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php AnnotatedClassDiscovery

Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.

Hierarchy

Expanded class hierarchy of AnnotatedClassDiscovery

1 file declares its use of AnnotatedClassDiscovery
AnnotatedClassDiscovery.php in core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php

File

core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php, line 17

Namespace

Drupal\Component\Annotation\Plugin\Discovery
View source
class AnnotatedClassDiscovery implements DiscoveryInterface {

  use DiscoveryTrait;

  /**
   * The namespaces within which to find plugin classes.
   *
   * @var string[]
   */
  protected $pluginNamespaces;

  /**
   * The name of the annotation that contains the plugin definition.
   *
   * The class corresponding to this name must implement
   * \Drupal\Component\Annotation\AnnotationInterface.
   *
   * @var string
   */
  protected $pluginDefinitionAnnotationName;

  /**
   * The doctrine annotation reader.
   *
   * @var \Doctrine\Common\Annotations\Reader
   */
  protected $annotationReader;

  /**
   * Additional namespaces to be scanned for annotation classes.
   *
   * @var string[]
   */
  protected $annotationNamespaces = [];

  /**
   * The file cache object.
   *
   * @var \Drupal\Component\FileCache\FileCacheInterface
   */
  protected $fileCache;

  /**
   * Constructs a new instance.
   *
   * @param string[] $plugin_namespaces
   *   (optional) An array of namespace that may contain plugin implementations.
   *   Defaults to an empty array.
   * @param string $plugin_definition_annotation_name
   *   (optional) The name of the annotation that contains the plugin definition.
   *   Defaults to 'Drupal\Component\Annotation\Plugin'.
   * @param string[] $annotation_namespaces
   *   (optional) Additional namespaces to be scanned for annotation classes.
   */
  function __construct($plugin_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin', array $annotation_namespaces = []) {
    $this->pluginNamespaces = $plugin_namespaces;
    $this->pluginDefinitionAnnotationName = $plugin_definition_annotation_name;
    $this->annotationNamespaces = $annotation_namespaces;

    $file_cache_suffix = str_replace('\\', '_', $plugin_definition_annotation_name);
    $file_cache_suffix .= ':' . hash('crc32b', serialize($annotation_namespaces));
    $this->fileCache = FileCacheFactory::get('annotation_discovery:' . $file_cache_suffix);
  }

  /**
   * Gets the used doctrine annotation reader.
   *
   * @return \Doctrine\Common\Annotations\Reader
   *   The annotation reader.
   */
  protected function getAnnotationReader() {
    if (!isset($this->annotationReader)) {
      $this->annotationReader = new SimpleAnnotationReader();

      // Add the namespaces from the main plugin annotation, like @EntityType.
      $namespace = substr($this->pluginDefinitionAnnotationName, 0, strrpos($this->pluginDefinitionAnnotationName, '\\'));
      $this->annotationReader->addNamespace($namespace);

      // Register additional namespaces to be scanned for annotations.
      foreach ($this->annotationNamespaces as $namespace) {
        $this->annotationReader->addNamespace($namespace);
      }
    }
    return $this->annotationReader;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefinitions() {
    $definitions = array();

    $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-0 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 StaticReflectionParser($class, $finder, TRUE);

              /** @var $annotation \Drupal\Component\Annotation\AnnotationInterface */
              if ($annotation = $reader->getClassAnnotation($parser->getReflectionClass(), $this->pluginDefinitionAnnotationName)) {
                $this->prepareAnnotationDefinition($annotation, $class);

                $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 reparsed again.
                $this->fileCache->set($fileinfo->getPathName(), [NULL]);
              }
            }
          }
        }
      }
    }

    // Don't let annotation loaders pile up.
    AnnotationRegistry::reset();

    return $definitions;
  }

  /**
   * Prepares the annotation definition.
   *
   * @param \Drupal\Component\Annotation\AnnotationInterface $annotation
   *   The annotation derived from the plugin.
   * @param string $class
   *   The class used for the plugin.
   */
  protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class) {
    $annotation->setClass($class);
  }

  /**
   * Gets an array of PSR-0 namespaces to search for plugin classes.
   *
   * @return string[]
   */
  protected function getPluginNamespaces() {
    return $this->pluginNamespaces;
  }

}

Members

Contains filters are case sensitive
Namesort descending Modifiers Type Description Overrides
AnnotatedClassDiscovery::$annotationNamespaces protected property Additional namespaces to be scanned for annotation classes.
AnnotatedClassDiscovery::$annotationReader protected property The doctrine annotation reader.
AnnotatedClassDiscovery::$fileCache protected property The file cache object.
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::getAnnotationReader protected function Gets the used doctrine annotation reader. 1
AnnotatedClassDiscovery::getDefinitions public function Gets the definition of all plugins for this type. Overrides DiscoveryTrait::getDefinitions 1
AnnotatedClassDiscovery::getPluginNamespaces protected function Gets an array of PSR-0 namespaces to search for plugin classes. 1
AnnotatedClassDiscovery::prepareAnnotationDefinition protected function Prepares the annotation definition. 2
AnnotatedClassDiscovery::__construct function Constructs a new instance. 2
DiscoveryTrait::doGetDefinition protected function Gets a specific plugin definition. Overrides DiscoveryTrait::doGetDefinition 1
DiscoveryTrait::getDefinition public function Gets a specific plugin definition. Overrides DiscoveryInterface::getDefinition 3
DiscoveryTrait::hasDefinition public function Indicates if a specific plugin definition exists. Overrides DiscoveryTrait::hasDefinition 1