diff --git a/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php index bdf1eba..50bbd18 100644 --- a/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php +++ b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -43,6 +43,13 @@ class AnnotatedClassDiscovery implements DiscoveryInterface { protected $annotationReader; /** + * The maximum level of depth for recursion under the top discovery directory. + * + * @var int + */ + protected $maxDepth; + + /** * Constructs an AnnotatedClassDiscovery object. * * @param array $plugin_namespaces @@ -51,10 +58,15 @@ class AnnotatedClassDiscovery implements DiscoveryInterface { * @param string $plugin_definition_annotation_name * (optional) The name of the annotation that contains the plugin definition. * Defaults to 'Drupal\Component\Annotation\Plugin'. + * @param int $max_depth + * (optional) The maximum level of depth for recursion under the top + * discovery directory. Setting this value to -1 will make the discovery + * descend to all levels. Defaults to 0 (no recursion). */ - function __construct($plugin_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { + function __construct($plugin_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin', $max_depth = 0) { $this->pluginNamespaces = $plugin_namespaces; $this->pluginDefinitionAnnotationName = $plugin_definition_annotation_name; + $this->maxDepth = $max_depth; } /** @@ -100,10 +112,15 @@ public function getDefinitions() { foreach ($dirs as $dir) { $dir .= DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $namespace); if (file_exists($dir)) { - foreach (new \DirectoryIterator($dir) as $fileinfo) { - // @todo Once core requires 5.3.6, use $fileinfo->getExtension(). - if (pathinfo($fileinfo->getFilename(), PATHINFO_EXTENSION) == 'php') { - $class = $namespace . '\\' . $fileinfo->getBasename('.php'); + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS) + ); + $iterator->setMaxDepth($this->maxDepth); + foreach ($iterator as $fileinfo) { + if ($fileinfo->getExtension() == 'php') { + $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 diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php index 92bc3f0..58d934e 100644 --- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php +++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php @@ -99,10 +99,14 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt * @param string $plugin_definition_annotation_name * (optional) The name of the annotation that contains the plugin definition. * Defaults to 'Drupal\Component\Annotation\Plugin'. + * @param int $max_depth + * (optional) The maximum level of depth for recursion under the top + * discovery directory. Setting this value to -1 will make the discovery + * descend to all levels. Defaults to 0 (no recursion). */ - public function __construct($subdir, \Traversable $namespaces, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { + public function __construct($subdir, \Traversable $namespaces, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin', $max_depth = 0) { $this->subdir = $subdir; - $this->discovery = new AnnotatedClassDiscovery($subdir, $namespaces, $plugin_definition_annotation_name); + $this->discovery = new AnnotatedClassDiscovery($subdir, $namespaces, $plugin_definition_annotation_name, $max_depth); $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); $this->factory = new ContainerFactory($this); } diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php index ffafdf6..b2e962b 100644 --- a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -44,14 +44,18 @@ class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery { * @param string $plugin_definition_annotation_name * (optional) The name of the annotation that contains the plugin definition. * Defaults to 'Drupal\Component\Annotation\Plugin'. + * @param int $max_depth + * (optional) The maximum level of depth for recursion under the top + * discovery directory. Setting this value to -1 will make the discovery + * descend to all levels. Defaults to 0 (no recursion). */ - function __construct($subdir, \Traversable $root_namespaces, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { + function __construct($subdir, \Traversable $root_namespaces, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin', $max_depth = 0) { if ($subdir) { $this->subdir = str_replace('/', '\\', $subdir); } $this->rootNamespacesIterator = $root_namespaces; $plugin_namespaces = array(); - parent::__construct($plugin_namespaces, $plugin_definition_annotation_name); + parent::__construct($plugin_namespaces, $plugin_definition_annotation_name, $max_depth); } /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php index d2fba9b..6dbcece 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php @@ -56,10 +56,23 @@ public function setUp() { 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Orange', 'provider' => 'plugin_test', ), + 'depth1' => array( + 'id' => 'depth1', + 'label' => 'Depth 1', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\depth1\Depth1', + 'provider' => 'plugin_test', + ), + 'depth2' => array( + 'id' => 'depth2', + 'label' => 'Depth 2', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\depth1\depth2\Depth2', + 'provider' => 'plugin_test', + ), + ); $namespaces = new \ArrayObject(array('Drupal\plugin_test' => DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib')); - $this->discovery = new AnnotatedClassDiscovery('Plugin/plugin_test/fruit', $namespaces); - $this->emptyDiscovery = new AnnotatedClassDiscovery('Plugin/non_existing_module/non_existing_plugin_type', $namespaces); + $this->discovery = new AnnotatedClassDiscovery('Plugin/plugin_test/fruit', $namespaces, 'Drupal\Component\Annotation\Plugin', 2); + $this->emptyDiscovery = new AnnotatedClassDiscovery('Plugin/non_existing_module/non_existing_plugin_type', $namespaces, 'Drupal\Component\Annotation\Plugin', 2); } }