From 0033bac9938fdc4ea3c8ab26bbf675fdeffd3aac Mon Sep 17 00:00:00 2001 From: Dries Date: Sat, 11 Aug 2012 12:49:44 -0400 Subject: [PATCH] - Patch #1683644 by chx, EclipseGc, tim.plunkett, aspilicious, xjm, dawehner, effulgentsia: use Annotations for plugin discovery. --- .../Component/Reflection/MockFileFinder.php | 50 ++++++++++ .../Core/Annotation/AnnotationInterface.php | 20 ++++ core/lib/Drupal/Core/Annotation/Plugin.php | 56 +++++++++++ .../Drupal/Core/Annotation/Translation.php | 55 +++++++++++ .../Discovery/AnnotatedClassDiscovery.php | 98 +++++++++++++++++++ 5 files changed, 279 insertions(+) create mode 100644 core/lib/Drupal/Component/Reflection/MockFileFinder.php create mode 100644 core/lib/Drupal/Core/Annotation/AnnotationInterface.php create mode 100644 core/lib/Drupal/Core/Annotation/Plugin.php create mode 100644 core/lib/Drupal/Core/Annotation/Translation.php create mode 100644 core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php diff --git a/core/lib/Drupal/Component/Reflection/MockFileFinder.php b/core/lib/Drupal/Component/Reflection/MockFileFinder.php new file mode 100644 index 00000000000..34c6949d780 --- /dev/null +++ b/core/lib/Drupal/Component/Reflection/MockFileFinder.php @@ -0,0 +1,50 @@ +filename; + } + + /** + * Creates new mock file finder objects. + */ + static public function create($filename) { + $object = new static(array()); + $object->filename = $filename; + return $object; + } + +} diff --git a/core/lib/Drupal/Core/Annotation/AnnotationInterface.php b/core/lib/Drupal/Core/Annotation/AnnotationInterface.php new file mode 100644 index 00000000000..3382d4836b6 --- /dev/null +++ b/core/lib/Drupal/Core/Annotation/AnnotationInterface.php @@ -0,0 +1,20 @@ + $value) { + if ($value instanceof AnnotationInterface) { + $this->definition[$key] = $value->get(); + } + else { + $this->definition[$key] = $value; + } + } + } + + /** + * Implements Drupal\Core\Annotation\AnnotationInterface::get(). + */ + public function get() { + return $this->definition; + } + +} diff --git a/core/lib/Drupal/Core/Annotation/Translation.php b/core/lib/Drupal/Core/Annotation/Translation.php new file mode 100644 index 00000000000..1e4ec6da92d --- /dev/null +++ b/core/lib/Drupal/Core/Annotation/Translation.php @@ -0,0 +1,55 @@ + $values['context'], + ); + } + $this->translation = t($string, array(), $options); + } + + /** + * Implements Drupal\Core\Annotation\AnnotationInterface::get(). + */ + public function get() { + return $this->translation; + } + +} diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php new file mode 100644 index 00000000000..a8b16434582 --- /dev/null +++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -0,0 +1,98 @@ +owner = $owner; + $this->type = $type; + } + + /** + * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition(). + */ + public function getDefinition($plugin_id) { + $plugins = $this->getDefinitions(); + return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : array(); + } + + /** + * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions(). + */ + public function getDefinitions() { + $definitions = array(); + $reader = new AnnotationReader(); + + // Register the namespace of classes that can be used for annotations. + AnnotationRegistry::registerAutoloadNamespace('Drupal\Core\Annotation', array(DRUPAL_ROOT . '/core/lib')); + // Get all PSR-0 namespaces. + $namespaces = drupal_classloader()->getNamespaces(); + foreach ($namespaces as $ns => $namespace_dirs) { + + // OS-Safe directory separators. + $ns = str_replace('\\', DIRECTORY_SEPARATOR, $ns); + + foreach ($namespace_dirs as $dir) { + // Check for the pre-determined directory structure to find plugins. + $prefix = implode(DIRECTORY_SEPARATOR, array( + $ns, + 'Plugin', + $this->owner, + $this->type + )); + $dir .= DIRECTORY_SEPARATOR . $prefix; + + // If the directory structure exists, look for classes. + if (file_exists($dir)) { + $directories = new DirectoryIterator($dir); + foreach ($directories as $fileinfo) { + // @todo Once core requires 5.3.6, use $fileinfo->getExtension(). + if (pathinfo($fileinfo->getFilename(), PATHINFO_EXTENSION) == 'php') { + $class = str_replace( + DIRECTORY_SEPARATOR, + '\\', + $prefix . DIRECTORY_SEPARATOR . $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); + + if ($annotation = $reader->getClassAnnotation($parser->getReflectionClass(), 'Drupal\Core\Annotation\Plugin')) { + // AnnotationInterface::get() returns the array definition + // instead of requiring us to work with the annotation object. + $definition = $annotation->get(); + $definition['class'] = $class; + $definitions[$definition['id']] = $definition; + } + } + } + } + } + } + return $definitions; + } + +}