Commit 62613774 authored by webchick's avatar webchick

Issue #2178795 by tim.plunkett, jlbellido, YesCT, Berdir, Xano: Allow...

Issue #2178795 by tim.plunkett, jlbellido, YesCT, Berdir, Xano: Allow DiscoveryInterface::getDefinition() to throw an exception for an invalid plugin.
parent a0f1611a
......@@ -13,12 +13,15 @@
use Doctrine\Common\Annotations\SimpleAnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Reflection\StaticReflectionParser;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
/**
* Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.
*/
class AnnotatedClassDiscovery implements DiscoveryInterface {
use DiscoveryTrait;
/**
* The namespaces within which to find plugin classes.
*
......@@ -75,14 +78,6 @@ protected function getAnnotationReader() {
return $this->annotationReader;
}
/**
* 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().
*/
......
......@@ -17,6 +17,8 @@
*/
class DerivativeDiscoveryDecorator implements DiscoveryInterface {
use DiscoveryTrait;
protected $derivativeFetchers = array();
protected $decorated;
......@@ -39,10 +41,15 @@ public function __construct(DiscoveryInterface $decorated) {
* Thrown if the 'derivative' class specified in the plugin definition does
* not implement \Drupal\Component\Plugin\Derivative\DerivativeInterface.
*/
public function getDefinition($plugin_id) {
$plugin_definition = $this->decorated->getDefinition($plugin_id);
public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
// This check is only for derivative plugins that have explicitly provided
// an ID. This is not common, and can be expected to fail. Therefore, opt
// out of the thrown exception, which will be handled when checking the
// $base_plugin_id.
$plugin_definition = $this->decorated->getDefinition($plugin_id, FALSE);
list($base_plugin_id, $derivative_id) = $this->decodePluginId($plugin_id);
$base_plugin_definition = $this->decorated->getDefinition($base_plugin_id);
$base_plugin_definition = $this->decorated->getDefinition($base_plugin_id, $exception_on_invalid);
if ($base_plugin_definition) {
$derivative_fetcher = $this->getDerivativeFetcher($base_plugin_id, $base_plugin_definition);
if ($derivative_fetcher) {
......
<?php
/**
* @file
* Contains \Drupal\Component\Plugin\Discovery\DiscoveryCachedTrait.
*/
namespace Drupal\Component\Plugin\Discovery;
trait DiscoveryCachedTrait {
use DiscoveryTrait;
/**
* Cached definitions array.
*
* @var array
*/
protected $definitions;
/**
* {@inheritdoc}
*/
public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
// Fetch definitions if they're not loaded yet.
if (!isset($this->definitions)) {
$this->getDefinitions();
}
return $this->doGetDefinition($this->definitions, $plugin_id, $exception_on_invalid);
}
}
......@@ -18,11 +18,17 @@ interface DiscoveryInterface {
*
* @param string $plugin_id
* A plugin id.
* @param bool $exception_on_invalid
* (optional) If TRUE, an invalid plugin ID will throw an exception.
*
* @return mixed
* A plugin definition, or NULL if no definition was found for $plugin_id.
* A plugin definition, or NULL if the plugin ID is invalid and
* $exception_on_invalid is FALSE.
*
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* Thrown if $plugin_id is invalid and $exception_on_invalid is TRUE.
*/
public function getDefinition($plugin_id);
public function getDefinition($plugin_id, $exception_on_invalid = TRUE);
/**
* Gets the definition of all plugins for this type.
......@@ -33,4 +39,15 @@ public function getDefinition($plugin_id);
*/
public function getDefinitions();
/**
* Indicates if a specific plugin definition exists.
*
* @param string $plugin_id
* A plugin ID.
*
* @return bool
* TRUE if the definition exists, FALSE otherwise.
*/
public function hasDefinition($plugin_id);
}
<?php
/**
* @file
* Contains \Drupal\Component\Plugin\Discovery\DiscoveryTrait.
*/
namespace Drupal\Component\Plugin\Discovery;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
/**
* @see Drupal\Component\Plugin\Discovery\DiscoveryInterface
*/
trait DiscoveryTrait {
/**
* {@inheritdoc}
*/
abstract public function getDefinitions();
/**
* {@inheritdoc}
*/
public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
$definitions = $this->getDefinitions();
return $this->doGetDefinition($definitions, $plugin_id, $exception_on_invalid);
}
/**
* Gets a specific plugin definition.
*
* @param array $definitions
* An array of the available plugin definitions.
* @param string $plugin_id
* A plugin id.
* @param bool $exception_on_invalid
* (optional) If TRUE, an invalid plugin ID will throw an exception.
* Defaults to FALSE.
*
* @return array|null
* A plugin definition, or NULL if the plugin ID is invalid and
* $exception_on_invalid is TRUE.
*
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* Thrown if $plugin_id is invalid and $exception_on_invalid is TRUE.
*/
protected function doGetDefinition(array $definitions, $plugin_id, $exception_on_invalid) {
// Avoid using a ternary that would create a copy of the array.
if (isset($definitions[$plugin_id])) {
return $definitions[$plugin_id];
}
elseif (!$exception_on_invalid) {
return NULL;
}
throw new PluginNotFoundException($plugin_id, sprintf('The "%s" plugin does not exist.', $plugin_id));
}
/**
* {@inheritdoc}
*/
public function hasDefinition($plugin_id) {
return (bool) $this->getDefinition($plugin_id, FALSE);
}
}
......@@ -15,6 +15,8 @@
*/
class ProcessDecorator implements DiscoveryInterface {
use DiscoveryTrait;
/**
* The Discovery object being decorated.
*
......@@ -46,16 +48,6 @@ public function __construct(DiscoveryInterface $decorated, $process_callback) {
$this->processCallback = $process_callback;
}
/**
* Implements \Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinition().
*/
public function getDefinition($plugin_id) {
$definitions = $this->getDefinitions();
if (isset($definitions[$plugin_id])) {
return $definitions[$plugin_id];
}
}
/**
* Implements \Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinitions().
*/
......
......@@ -13,24 +13,15 @@
*/
class StaticDiscovery implements DiscoveryInterface {
/**
* The array of plugin definitions, keyed by plugin id.
*
* @var array
*/
protected $definitions = array();
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
*/
public function getDefinition($base_plugin_id) {
return isset($this->definitions[$base_plugin_id]) ? $this->definitions[$base_plugin_id] : NULL;
}
use DiscoveryCachedTrait;
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
*/
public function getDefinitions() {
if (!$this->definitions) {
$this->definitions = array();
}
return $this->definitions;
}
......
......@@ -41,14 +41,14 @@ public function __construct(DiscoveryInterface $decorated, $registerDefinitions
}
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
* {@inheritdoc}
*/
public function getDefinition($base_plugin_id) {
public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
if (isset($this->registerDefinitions)) {
call_user_func($this->registerDefinitions);
}
$this->definitions += $this->decorated->getDefinitions();
return parent::getDefinition($base_plugin_id);
return parent::getDefinition($base_plugin_id, $exception_on_invalid);
}
/**
......
......@@ -8,12 +8,15 @@
namespace Drupal\Component\Plugin;
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
/**
* Base class for plugin managers.
*/
abstract class PluginManagerBase implements PluginManagerInterface, CachedDiscoveryInterface {
use DiscoveryTrait;
/**
* The object that discovers plugins managed by this manager.
*
......@@ -38,8 +41,8 @@ abstract class PluginManagerBase implements PluginManagerInterface, CachedDiscov
/**
* {@inheritdoc}
*/
public function getDefinition($plugin_id) {
return $this->discovery->getDefinition($plugin_id);
public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
return $this->discovery->getDefinition($plugin_id, $exception_on_invalid);
}
/**
......
......@@ -140,9 +140,9 @@ public function createInstance($plugin_id, array $configuration = array(), $name
}
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
* {@inheritdoc}
*/
public function getDefinition($base_plugin_id) {
public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
$definitions = $this->getDefinitions();
if (isset($definitions[$base_plugin_id])) {
$type = $base_plugin_id;
......@@ -158,7 +158,7 @@ public function getDefinition($base_plugin_id) {
$definition = $definitions[$type];
// Check whether this type is an extension of another one and compile it.
if (isset($definition['type'])) {
$merge = $this->getDefinition($definition['type']);
$merge = $this->getDefinition($definition['type'], $exception_on_invalid);
$definition = NestedArray::mergeDeep($merge, $definition);
// Unset type so we try the merge only once per type.
unset($definition['type']);
......
......@@ -170,8 +170,8 @@ protected function findDefinitions() {
/**
* {@inheritdoc}
*/
public function getDefinition($entity_type_id, $exception_on_invalid = FALSE) {
if (($entity_type = parent::getDefinition($entity_type_id)) && class_exists($entity_type->getClass())) {
public function getDefinition($entity_type_id, $exception_on_invalid = TRUE) {
if (($entity_type = parent::getDefinition($entity_type_id, FALSE)) && class_exists($entity_type->getClass())) {
return $entity_type;
}
elseif (!$exception_on_invalid) {
......@@ -185,7 +185,7 @@ public function getDefinition($entity_type_id, $exception_on_invalid = FALSE) {
* {@inheritdoc}
*/
public function hasController($entity_type, $controller_type) {
if ($definition = $this->getDefinition($entity_type)) {
if ($definition = $this->getDefinition($entity_type, FALSE)) {
return $definition->hasControllerClass($controller_type);
}
return FALSE;
......@@ -260,7 +260,7 @@ public function getAccessController($entity_type) {
*/
public function getController($entity_type, $controller_type, $controller_class_getter = NULL) {
if (!isset($this->controllers[$controller_type][$entity_type])) {
$definition = $this->getDefinition($entity_type, TRUE);
$definition = $this->getDefinition($entity_type);
if ($controller_class_getter) {
$class = $definition->{$controller_class_getter}();
}
......@@ -291,7 +291,7 @@ public function getController($entity_type, $controller_type, $controller_class_
* {@inheritdoc}
*/
public function getAdminRouteInfo($entity_type_id, $bundle) {
if (($entity_type = $this->getDefinition($entity_type_id)) && $admin_form = $entity_type->getLinkTemplate('admin-form')) {
if (($entity_type = $this->getDefinition($entity_type_id, FALSE)) && $admin_form = $entity_type->getLinkTemplate('admin-form')) {
return array(
'route_name' => $admin_form,
'route_parameters' => array(
......
......@@ -274,28 +274,16 @@ public function getExtraFields($entity_type_id, $bundle);
public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array());
/**
* Returns the entity type info for a specific entity type.
*
* @param string $entity_type_id
* The ID of the entity type.
* @param bool $exception_on_invalid
* (optional) If TRUE, an invalid entity type ID will throw an exception.
* Defaults to FALSE.
* {@inheritdoc}
*
* @return \Drupal\Core\Entity\EntityTypeInterface|null
* Returns the entity type object, or NULL if the entity type ID is invalid
* and $exception_on_invalid is TRUE.
*
* @throws \InvalidArgumentException
* Thrown if $entity_type_id is invalid and $exception_on_invalid is TRUE.
*/
public function getDefinition($entity_type_id, $exception_on_invalid = FALSE);
public function getDefinition($entity_type_id, $exception_on_invalid = TRUE);
/**
* Returns an array of entity type info, keyed by entity type name.
* {@inheritdoc}
*
* @return \Drupal\Core\Entity\EntityTypeInterface[]
* An array of entity type objects.
*/
public function getDefinitions();
......
......@@ -51,7 +51,7 @@ public function processDefinition(&$definition, $plugin_id) {
* {@inheritdoc}
*/
public function getDefaultSettings($type) {
$plugin_definition = $this->getDefinition($type);
$plugin_definition = $this->getDefinition($type, FALSE);
if (!empty($plugin_definition['class'])) {
$plugin_class = DefaultFactory::getPluginClass($type, $plugin_definition);
return $plugin_class::defaultSettings();
......@@ -63,7 +63,7 @@ public function getDefaultSettings($type) {
* {@inheritdoc}
*/
public function getDefaultInstanceSettings($type) {
$plugin_definition = $this->getDefinition($type);
$plugin_definition = $this->getDefinition($type, FALSE);
if (!empty($plugin_definition['class'])) {
$plugin_class = DefaultFactory::getPluginClass($type, $plugin_definition);
return $plugin_class::defaultInstanceSettings();
......
......@@ -113,7 +113,7 @@ public function getInstance(array $options) {
// Switch back to default formatter if either:
// - $type_info doesn't exist (the widget type is unknown),
// - the field type is not allowed for the widget.
$definition = $this->getDefinition($configuration['type']);
$definition = $this->getDefinition($configuration['type'], FALSE);
if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
// Grab the default widget for the field type.
$field_type_definition = $this->fieldTypeManager->getDefinition($field_type);
......@@ -201,7 +201,7 @@ public function getOptions($field_type = NULL) {
* definition, or an empty array if type or settings are undefined.
*/
public function getDefaultSettings($type) {
$plugin_definition = $this->getDefinition($type);
$plugin_definition = $this->getDefinition($type, FALSE);
if (!empty($plugin_definition['class'])) {
$plugin_class = DefaultFactory::getPluginClass($type, $plugin_definition);
return $plugin_class::defaultSettings();
......
......@@ -99,7 +99,7 @@ public function getInstance(array $options) {
// Switch back to default widget if either:
// - $type_info doesn't exist (the widget type is unknown),
// - the field type is not allowed for the widget.
$definition = $this->getDefinition($configuration['type']);
$definition = $this->getDefinition($configuration['type'], FALSE);
if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
// Grab the default widget for the field type.
$field_type_definition = $this->fieldTypeManager->getDefinition($field_type);
......@@ -203,7 +203,7 @@ public function getOptions($field_type = NULL) {
* definition, or an empty array if type or settings are undefined.
*/
public function getDefaultSettings($type) {
$plugin_definition = $this->getDefinition($type);
$plugin_definition = $this->getDefinition($type, FALSE);
if (!empty($plugin_definition['class'])) {
$plugin_class = DefaultFactory::getPluginClass($type, $plugin_definition);
return $plugin_class::defaultSettings();
......
......@@ -8,6 +8,8 @@
namespace Drupal\Core\Plugin;
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryCachedTrait;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
use Drupal\Component\Plugin\PluginManagerBase;
use Drupal\Component\Plugin\PluginManagerInterface;
......@@ -25,12 +27,7 @@
*/
class DefaultPluginManager extends PluginManagerBase implements PluginManagerInterface, CachedDiscoveryInterface {
/**
* Cached definitions array.
*
* @var array
*/
protected $definitions;
use DiscoveryCachedTrait;
/**
* Cache backend instance.
......@@ -161,20 +158,6 @@ protected function alterInfo($alter_hook) {
$this->alterHook = $alter_hook;
}
/**
* {@inheritdoc}
*/
public function getDefinition($plugin_id) {
// Fetch definitions if they're not loaded yet.
if (!isset($this->definitions)) {
$this->getDefinitions();
}
// Avoid using a ternary that would create a copy of the array.
if (isset($this->definitions[$plugin_id])) {
return $this->definitions[$plugin_id];
}
}
/**
* {@inheritdoc}
*/
......
......@@ -8,11 +8,15 @@
namespace Drupal\Core\Plugin\Discovery;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
/**
* Enables altering of discovered plugin definitions.
*/
class AlterDecorator implements DiscoveryInterface {
use DiscoveryTrait;
/**
* The name of the alter hook that will be implemented by this discovery instance.
*
......@@ -42,15 +46,6 @@ public function __construct(DiscoveryInterface $decorated, $hook) {
$this->hook = $hook;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
*/
public function getDefinition($plugin_id) {
$definitions = $this->getDefinitions();
return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
*/
......
......@@ -8,6 +8,7 @@
namespace Drupal\Core\Plugin\Discovery;
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryCachedTrait;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Core\Cache\Cache;
......@@ -16,6 +17,8 @@
*/
class CacheDecorator implements CachedDiscoveryInterface {
use DiscoveryCachedTrait;
/**
* The cache key used to store the definition list.
*
......@@ -44,13 +47,6 @@ class CacheDecorator implements CachedDiscoveryInterface {
*/
protected $cacheTags;
/**
* The plugin definitions of the decorated discovery class.
*
* @var array
*/
protected $definitions;
/**
* The Discovery object being decorated.
*
......@@ -83,28 +79,6 @@ public function __construct(DiscoveryInterface $decorated, $cache_key, $cache_bi
$this->cacheTags = $cache_tags;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinition().
*/
public function getDefinition($plugin_id) {
// Optimize for fast access to definitions if they are already in memory.
if (isset($this->definitions)) {
// Avoid using a ternary that would create a copy of the array.
if (isset($this->definitions[$plugin_id])) {
return $this->definitions[$plugin_id];
}
else {
return;
}
}
$definitions = $this->getDefinitions();
// Avoid using a ternary that would create a copy of the array.
if (isset($definitions[$plugin_id])) {
return $definitions[$plugin_id];
}
}
/**
* Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinitions().
*/
......
......@@ -8,6 +8,7 @@
namespace Drupal\Core\Plugin\Discovery;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
use Drupal\Core\Extension\ModuleHandlerInterface;
/**
......@@ -15,6 +16,8 @@
*/
class HookDiscovery implements DiscoveryInterface {
use DiscoveryTrait;
/**
* The name of the hook that will be implemented by this discovery instance.
*
......@@ -43,14 +46,6 @@ function __construct(ModuleHandlerInterface $module_handler, $hook) {
$this->hook = $hook;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinition().
*/
public function getDefinition($plugin_id) {
$plugins = $this->getDefinitions();
return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : NULL;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinitions().
*/
......
......@@ -8,12 +8,15 @@
namespace Drupal\Core\Plugin\Discovery;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
/**
* Allows info hook implementations to enhance discovered plugin definitions.
*/
class InfoHookDecorator implements DiscoveryInterface {
use DiscoveryTrait;
/**
* The Discovery object being decorated.
*
......@@ -41,14 +44,6 @@ public function __construct(DiscoveryInterface $decorated, $hook) {
$this->hook = $hook;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
*/
public function getDefinition($plugin_id) {
$definitions = $this->getDefinitions();
return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
}
/**
* Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
*/
......
......@@ -9,12 +9,15 @@
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Discovery\YamlDiscovery as ComponentYamlDiscovery;
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
/**
* Allows YAML files to define plugin definitions.
*/
class YamlDiscovery implements DiscoveryInterface {
use DiscoveryTrait;
/**
* YAML file discovery and parsing handler.
*
......@@ -35,14 +38,6 @@ function __construct($name, array $directories) {
$this->discovery = new ComponentYamlDiscovery($name, $directories);
}
/**
* {@inheritdoc}
*/
public function getDefinition($plugin_id) {
$definitions = $this->getDefinitions();
return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
}
/**
* {@inheritdoc}
*/
......
......@@ -174,8 +174,7 @@ public function calculateDependencies() {
}
// Create a dependency on the module that provides the formatter or
// widget.
if (isset($component['type'])) {
$definition = $this->pluginManager->getDefinition($component['type']);
if (isset($component['type']) && $definition = $this->pluginManager->getDefinition($component['type'], FALSE)) {
$this->addDependency('module', $definition['provider']);
}
}
......
......@@ -207,7 +207,7 @@ function entity_reference_query_entity_reference_alter(AlterableInterface $query
*/
function entity_reference_create_instance($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = array(), $cardinality = 1) {
// If a field type we know should exist isn't found, clear the field cache.
if (!\Drupal::service('plugin.manager.field.field_type')->getDefinition('entity_reference')) {
if (!\Drupal::service('plugin.manager.field.field_type')->hasDefinition('entity_reference')) {
field_cache_clear();
}
......
......@@ -68,9 +68,7 @@ function field_views_data_alter(&$data) {
*/
function _field_views_is_sql_entity_type(FieldConfigInterface $field) {
$entity_manager = \Drupal::entityManager();
if ($entity_manager->getDefinition($field->entity_type) && $entity_manager->getStorage($field->entity_type) instanceof ContentEntityDatabaseStorage) {
return TRUE;