You are here

class AnnotatedClassDiscovery in Service Container 7.2

Same name in this branch
  1. 7.2 lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery
  2. 7.2 modules/providers/service_container_annotation_discovery/src/Plugin/Discovery/AnnotatedClassDiscovery.php \Drupal\service_container_annotation_discovery\Plugin\Discovery\AnnotatedClassDiscovery
Same name and namespace in other branches
  1. 7 modules/providers/service_container_annotation_discovery/src/Plugin/Discovery/AnnotatedClassDiscovery.php \Drupal\service_container_annotation_discovery\Plugin\Discovery\AnnotatedClassDiscovery

TODO

This class cannot be tested as it relies on the existence of procedural code. @codeCoverageIgnore

Hierarchy

Expanded class hierarchy of AnnotatedClassDiscovery

File

modules/providers/service_container_annotation_discovery/src/Plugin/Discovery/AnnotatedClassDiscovery.php, line 23
Contains \Drupal\service_container_annotation_discovery\Plugin\Discovery\AnnotatedClassDiscovery

Namespace

Drupal\service_container_annotation_discovery\Plugin\Discovery
View source
class AnnotatedClassDiscovery implements DiscoveryInterface {

  /**
   * The plugin definition.
   *
   * @var array
   */
  protected $pluginManagerDefinition;

  /**
   * 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;

  /**
   * Constructs a new instance.
   *
   * @param string[] $plugin_manager_definition
   *   (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'.
   */
  function __construct($plugin_manager_definition, $plugin_definition_annotation_name = 'Drupal\\Component\\Annotation\\Plugin') {
    $namespaces = array();
    foreach (module_list() as $module_name) {
      $directory = DRUPAL_ROOT . '/' . drupal_get_path('module', $module_name) . '/src/' . trim($plugin_manager_definition['directory'], DIRECTORY_SEPARATOR);
      $namespaces['Drupal\\' . $module_name] = array(
        $directory,
      );
    }
    $this->pluginNamespaces = new \ArrayObject($namespaces);
    $this->pluginDefinitionAnnotationName = isset($plugin_manager_definition['class']) ? $plugin_manager_definition['class'] : $plugin_definition_annotation_name;
    $this->pluginManagerDefinition = $plugin_manager_definition;
  }

  /**
   * 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);
    }
    return $this->annotationReader;
  }

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

  /**
   * {@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') {
              $sub_path = $iterator
                ->getSubIterator()
                ->getSubPath();
              $sub_path = $sub_path ? str_replace('/', '\\', $sub_path) . '\\' : '';
              $class = $namespace . '\\' . str_replace('/', '\\', $this->pluginManagerDefinition['directory']) . '\\' . $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);
              if ($annotation = $reader
                ->getClassAnnotation($parser
                ->getReflectionClass(), $this->pluginDefinitionAnnotationName)) {
                $this
                  ->prepareAnnotationDefinition($annotation, $class);
                $definitions[$annotation
                  ->getId()] = $annotation
                  ->get();
              }
            }
          }
        }
      }
    }

    // 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($annotation, $class) {
    $annotation
      ->setClass($class);
  }

  /**
   * {@inheritdoc}
   */
  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
    $definitions = $this
      ->getDefinitions();
    $definition = isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : FALSE;
    if (!$definition && $exception_on_invalid) {
      throw new PluginNotFoundException($plugin_id, sprintf('The "%s" plugin does not exist.', $plugin_id));
    }
    return $definition;
  }

  /**
   * {@inheritdoc}
   */
  public function hasDefinition($plugin_id) {
    return (bool) $this
      ->getDefinition($plugin_id, FALSE);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AnnotatedClassDiscovery::$annotationReader protected property The doctrine annotation reader.
AnnotatedClassDiscovery::$pluginDefinitionAnnotationName protected property The name of the annotation that contains the plugin definition.
AnnotatedClassDiscovery::$pluginManagerDefinition protected property 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.
AnnotatedClassDiscovery::getDefinition public function Gets a specific plugin definition. Overrides DiscoveryInterface::getDefinition
AnnotatedClassDiscovery::getDefinitions public function Gets the definition of all plugins for this type. Overrides DiscoveryInterface::getDefinitions
AnnotatedClassDiscovery::getPluginNamespaces protected function Gets an array of PSR-0 namespaces to search for plugin classes.
AnnotatedClassDiscovery::hasDefinition public function Indicates if a specific plugin definition exists. Overrides DiscoveryInterface::hasDefinition
AnnotatedClassDiscovery::prepareAnnotationDefinition protected function Prepares the annotation definition.
AnnotatedClassDiscovery::__construct function Constructs a new instance.