Issue #1849752 by effulgentsia, Berdir: Abstract non-Drupal-specific parts of AnnotatedClassDiscovery into a Drupal\Component base class.
parent
d395e8af58
commit
adc8b1e725
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\Core\Annotation\AnnotationInterface.
|
||||
* Contains Drupal\Component\Annotation\AnnotationInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Annotation;
|
||||
namespace Drupal\Component\Annotation;
|
||||
|
||||
/**
|
||||
* Defines a common interface for classed annotations.
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Drupal\Component\Annotation\Plugin.
|
||||
*/
|
||||
|
||||
namespace Drupal\Component\Annotation;
|
||||
|
||||
/**
|
||||
* Defines a Plugin annotation object.
|
||||
*
|
||||
* Annotations in plugin classes can utilize this class in order to pass
|
||||
* various metadata about the plugin through the parser to
|
||||
* DiscoveryInterface::getDefinitions() calls. This allows the metadata
|
||||
* of a class to be located with the class itself, rather than in module-based
|
||||
* info hooks.
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class Plugin implements AnnotationInterface {
|
||||
|
||||
/**
|
||||
* The plugin definiton read from the class annotation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definition;
|
||||
|
||||
/**
|
||||
* Constructs a Plugin object.
|
||||
*
|
||||
* Builds up the plugin definition and invokes the get() method for any
|
||||
* classed annotations that were used.
|
||||
*/
|
||||
public function __construct($values) {
|
||||
$this->definition = $this->parse($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an annotation into its definition.
|
||||
*
|
||||
* @param array $values
|
||||
* The annotation array.
|
||||
*
|
||||
* @return array
|
||||
* The parsed annotation as a definition.
|
||||
*/
|
||||
protected function parse(array $values) {
|
||||
$definitions = array();
|
||||
foreach ($values as $key => $value) {
|
||||
if ($value instanceof AnnotationInterface) {
|
||||
$definitions[$key] = $value->get();
|
||||
}
|
||||
elseif (is_array($value)) {
|
||||
$definitions[$key] = $this->parse($value);
|
||||
}
|
||||
else {
|
||||
$definitions[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Core\Annotation\AnnotationInterface::get().
|
||||
*/
|
||||
public function get() {
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Drupal\Component\Plugin\Discovery\AnnotatedClassDiscovery.
|
||||
*/
|
||||
|
||||
namespace Drupal\Component\Plugin\Discovery;
|
||||
|
||||
use DirectoryIterator;
|
||||
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
|
||||
use Drupal\Component\Reflection\MockFileFinder;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Reflection\StaticReflectionParser;
|
||||
|
||||
/**
|
||||
* Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.
|
||||
*/
|
||||
class AnnotatedClassDiscovery implements DiscoveryInterface {
|
||||
|
||||
/**
|
||||
* The namespaces within which to find plugin classes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pluginNamespaces;
|
||||
|
||||
/**
|
||||
* The namespaces of classes that can be used as annotations.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $annotationNamespaces;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constructs an AnnotatedClassDiscovery object.
|
||||
*/
|
||||
function __construct($plugin_namespaces = array(), $annotation_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') {
|
||||
$this->pluginNamespaces = $plugin_namespaces;
|
||||
$this->annotationNamespaces = $annotation_namespaces;
|
||||
$this->pluginDefinitionAnnotationName = $plugin_definition_annotation_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
|
||||
*/
|
||||
public function getDefinition($plugin_id) {
|
||||
$plugins = $this->getDefinitions();
|
||||
return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
|
||||
*/
|
||||
public function getDefinitions() {
|
||||
$definitions = array();
|
||||
$reader = new AnnotationReader();
|
||||
// Prevent @endlink from being parsed as an annotation.
|
||||
$reader->addGlobalIgnoredName('endlink');
|
||||
|
||||
// Register the namespaces of classes that can be used for annotations.
|
||||
AnnotationRegistry::registerAutoloadNamespaces($this->getAnnotationNamespaces());
|
||||
|
||||
// Search for classes within all PSR-0 namespace locations.
|
||||
foreach ($this->getPluginNamespaces() as $namespace => $dirs) {
|
||||
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');
|
||||
|
||||
// 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(), $this->pluginDefinitionAnnotationName)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of PSR-0 namespaces to search for plugin classes.
|
||||
*/
|
||||
protected function getPluginNamespaces() {
|
||||
return $this->pluginNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of PSR-0 namespaces to search for annotation classes.
|
||||
*/
|
||||
protected function getAnnotationNamespaces() {
|
||||
return $this->annotationNamespaces;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,68 +7,12 @@
|
|||
|
||||
namespace Drupal\Core\Annotation;
|
||||
|
||||
use Drupal\Core\Annotation\AnnotationInterface;
|
||||
use Drupal\Component\Annotation\Plugin as ComponentPlugin;
|
||||
|
||||
/**
|
||||
* Defines a Plugin annotation object.
|
||||
*
|
||||
* Annotations in plugin classes can utilize this class in order to pass
|
||||
* various metadata about the plugin through the parser to
|
||||
* DiscoveryInterface::getDefinitions() calls. This allows the metadata
|
||||
* of a class to be located with the class itself, rather than in module-based
|
||||
* info hooks.
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class Plugin implements AnnotationInterface {
|
||||
|
||||
/**
|
||||
* The plugin definiton read from the class annotation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definition;
|
||||
|
||||
/**
|
||||
* Constructs a Plugin object.
|
||||
*
|
||||
* Builds up the plugin definition and invokes the get() method for any
|
||||
* classed annotations that were used.
|
||||
*/
|
||||
public function __construct($values) {
|
||||
$this->definition = $this->parse($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an annotation into its definition.
|
||||
*
|
||||
* @param array $values
|
||||
* The annotation array.
|
||||
*
|
||||
* @return array
|
||||
* The parsed annotation as a definition.
|
||||
*/
|
||||
protected function parse(array $values) {
|
||||
$definitions = array();
|
||||
foreach ($values as $key => $value) {
|
||||
if ($value instanceof AnnotationInterface) {
|
||||
$definitions[$key] = $value->get();
|
||||
}
|
||||
elseif (is_array($value)) {
|
||||
$definitions[$key] = $this->parse($value);
|
||||
}
|
||||
else {
|
||||
$definitions[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Core\Annotation\AnnotationInterface::get().
|
||||
*/
|
||||
public function get() {
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
class Plugin extends ComponentPlugin {
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\Core\Annotation;
|
||||
|
||||
use Drupal\Core\Annotation\AnnotationInterface;
|
||||
use Drupal\Component\Annotation\AnnotationInterface;
|
||||
|
||||
/**
|
||||
* Defines a translatable annotation object.
|
||||
|
|
|
@ -7,94 +7,41 @@
|
|||
|
||||
namespace Drupal\Core\Plugin\Discovery;
|
||||
|
||||
use DirectoryIterator;
|
||||
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
|
||||
use Drupal\Component\Reflection\MockFileFinder;
|
||||
use Drupal\Core\Annotation\Plugin;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Reflection\StaticReflectionParser;
|
||||
use Drupal\Component\Plugin\Discovery\AnnotatedClassDiscovery as ComponentAnnotatedClassDiscovery;
|
||||
|
||||
/**
|
||||
* Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.
|
||||
*/
|
||||
class AnnotatedClassDiscovery implements DiscoveryInterface {
|
||||
class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery {
|
||||
|
||||
/**
|
||||
* Constructs an AnnotatedClassDiscovery object.
|
||||
*/
|
||||
function __construct($owner, $type) {
|
||||
function __construct($owner, $type, $root_namespaces = NULL) {
|
||||
$this->owner = $owner;
|
||||
$this->type = $type;
|
||||
$this->rootNamespaces = $root_namespaces;
|
||||
$annotation_namespaces = array(
|
||||
'Drupal\Component\Annotation' => DRUPAL_ROOT . '/core/lib',
|
||||
'Drupal\Core\Annotation' => DRUPAL_ROOT . '/core/lib',
|
||||
);
|
||||
parent::__construct(array(), $annotation_namespaces, 'Drupal\Core\Annotation\Plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
|
||||
* Overrides Drupal\Component\Plugin\Discovery\AnnotatedClassDiscovery::getPluginNamespaces().
|
||||
*
|
||||
* This is overridden rather than set in the constructor, because Drupal
|
||||
* modules can be enabled (and therefore, namespaces registered) during the
|
||||
* lifetime of a plugin manager.
|
||||
*/
|
||||
public function getDefinition($plugin_id) {
|
||||
$plugins = $this->getDefinitions();
|
||||
return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
|
||||
*/
|
||||
public function getDefinitions() {
|
||||
$definitions = array();
|
||||
$reader = new AnnotationReader();
|
||||
// Prevent @endlink from being parsed as an annotation.
|
||||
$reader->addGlobalIgnoredName('endlink');
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected function getPluginNamespaces() {
|
||||
$plugin_namespaces = array();
|
||||
$root_namespaces = isset($this->rootNamespaces) ? $this->rootNamespaces : drupal_classloader()->getNamespaces();
|
||||
foreach ($root_namespaces as $namespace => $dirs) {
|
||||
$plugin_namespaces["$namespace\\Plugin\\{$this->owner}\\{$this->type}"] = $dirs;
|
||||
}
|
||||
return $definitions;
|
||||
return $plugin_namespaces;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue