3 namespace Drupal\Core\Plugin\Discovery;
5 use Drupal\Component\Annotation\AnnotationInterface;
6 use Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery as ComponentAnnotatedClassDiscovery;
9 * Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.
11 class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery {
14 * A suffix to append to each PSR-4 directory associated with a base
15 * namespace, to form the directories where plugins are found.
19 protected $directorySuffix = '';
22 * A suffix to append to each base namespace, to obtain the namespaces where
27 protected $namespaceSuffix = '';
30 * A list of base namespaces with their PSR-4 directories.
34 protected $rootNamespacesIterator;
37 * Constructs an AnnotatedClassDiscovery object.
39 * @param string $subdir
40 * Either the plugin's subdirectory, for example 'Plugin/views/filter', or
41 * empty string if plugins are located at the top level of the namespace.
42 * @param \Traversable $root_namespaces
43 * An object that implements \Traversable which contains the root paths
44 * keyed by the corresponding namespace to look for plugin implementations.
45 * If $subdir is not an empty string, it will be appended to each namespace.
46 * @param string $plugin_definition_annotation_name
47 * (optional) The name of the annotation that contains the plugin definition.
48 * Defaults to 'Drupal\Component\Annotation\Plugin'.
49 * @param string[] $annotation_namespaces
50 * (optional) Additional namespaces to scan for annotation definitions.
52 public function __construct($subdir, \Traversable $root_namespaces, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin', array $annotation_namespaces = []) {
54 // Prepend a directory separator to $subdir,
55 // if it does not already have one.
56 if ('/' !== $subdir[0]) {
57 $subdir = '/' . $subdir;
59 $this->directorySuffix = $subdir;
60 $this->namespaceSuffix = str_replace('/', '\\', $subdir);
62 $this->rootNamespacesIterator = $root_namespaces;
63 $plugin_namespaces = [];
64 parent::__construct($plugin_namespaces, $plugin_definition_annotation_name, $annotation_namespaces);
70 protected function getAnnotationReader() {
71 if (!isset($this->annotationReader)) {
72 $reader = parent::getAnnotationReader();
74 // Add the Core annotation classes like @Translation.
75 $reader->addNamespace('Drupal\Core\Annotation');
76 $this->annotationReader = $reader;
78 return $this->annotationReader;
84 protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class) {
85 parent::prepareAnnotationDefinition($annotation, $class);
87 if (!$annotation->getProvider()) {
88 $annotation->setProvider($this->getProviderFromNamespace($class));
93 * Extracts the provider name from a Drupal namespace.
95 * @param string $namespace
96 * The namespace to extract the provider from.
99 * The matching provider name, or NULL otherwise.
101 protected function getProviderFromNamespace($namespace) {
102 preg_match('|^Drupal\\\\(?<provider>[\w]+)\\\\|', $namespace, $matches);
104 if (isset($matches['provider'])) {
105 return mb_strtolower($matches['provider']);
114 protected function getPluginNamespaces() {
115 $plugin_namespaces = [];
116 if ($this->namespaceSuffix) {
117 foreach ($this->rootNamespacesIterator as $namespace => $dirs) {
118 // Append the namespace suffix to the base namespace, to obtain the
119 // plugin namespace; for example, 'Drupal\Views' may become
120 // 'Drupal\Views\Plugin\Block'.
121 $namespace .= $this->namespaceSuffix;
122 foreach ((array) $dirs as $dir) {
123 // Append the directory suffix to the PSR-4 base directory, to obtain
124 // the directory where plugins are found. For example,
125 // DRUPAL_ROOT . '/core/modules/views/src' may become
126 // DRUPAL_ROOT . '/core/modules/views/src/Plugin/Block'.
127 $plugin_namespaces[$namespace][] = $dir . $this->directorySuffix;
132 // Both the namespace suffix and the directory suffix are empty,
133 // so the plugin namespaces and directories are the same as the base
135 foreach ($this->rootNamespacesIterator as $namespace => $dirs) {
136 $plugin_namespaces[$namespace] = (array) $dirs;
140 return $plugin_namespaces;