diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index 7621a48..9c814b8 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -459,7 +459,7 @@ public static function moduleHandler() { * * Use the typed data manager service for creating typed data objects. * - * @return \Drupal\Core\TypedData\TypedDataManager + * @return \Drupal\Core\TypedData\TypedDataManagerInterface * The typed data manager. * * @see \Drupal\Core\TypedData\TypedDataManager::create() diff --git a/core/lib/Drupal/Core/Config/Schema/ArrayElement.php b/core/lib/Drupal/Core/Config/Schema/ArrayElement.php index 88914c0..616f2f9 100644 --- a/core/lib/Drupal/Core/Config/Schema/ArrayElement.php +++ b/core/lib/Drupal/Core/Config/Schema/ArrayElement.php @@ -7,27 +7,10 @@ namespace Drupal\Core\Config\Schema; -use Drupal\Core\Config\TypedConfigManagerInterface; -use Drupal\Core\TypedData\TypedData; - /** * Defines a generic configuration element that contains multiple properties. */ -abstract class ArrayElement extends TypedData implements \IteratorAggregate, TypedConfigInterface { - - /** - * The typed config manager. - * - * @var \Drupal\Core\Config\TypedConfigManagerInterface - */ - protected $typedConfig; - - /** - * The configuration value. - * - * @var mixed - */ - protected $value; +abstract class ArrayElement extends Element implements \IteratorAggregate, TypedConfigInterface { /** * Parsed elements. @@ -152,7 +135,7 @@ public function getIterator() { * @return \Drupal\Core\TypedData\TypedDataInterface */ protected function createElement($definition, $value, $key) { - return $this->typedConfig->create($definition, $value, $key, $this); + return $this->getTypedDataManager()->create($definition, $value, $key, $this); } /** @@ -170,20 +153,7 @@ protected function createElement($definition, $value, $key) { * @return \Drupal\Core\TypedData\DataDefinitionInterface */ protected function buildDataDefinition($definition, $value, $key) { - return $this->typedConfig->buildDataDefinition($definition, $value, $key, $this); - } - - - /** - * Sets the typed config manager on the instance. - * - * This must be called immediately after construction to enable - * self::parseElement() and self::buildDataDefinition() to work. - * - * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config - */ - public function setTypedConfig(TypedConfigManagerInterface $typed_config) { - $this->typedConfig = $typed_config; + return $this->getTypedDataManager()->buildDataDefinition($definition, $value, $key, $this); } } diff --git a/core/lib/Drupal/Core/Config/Schema/Element.php b/core/lib/Drupal/Core/Config/Schema/Element.php index 2993f8c..2dc1056 100644 --- a/core/lib/Drupal/Core/Config/Schema/Element.php +++ b/core/lib/Drupal/Core/Config/Schema/Element.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Config\Schema; use Drupal\Core\TypedData\TypedData; +use Drupal\Core\TypedData\TypedDataManagerInterface; /** * Defines a generic configuration element. @@ -21,4 +22,38 @@ */ protected $value; + /** + * Gets the typed configuration manager. + * + * Overrides \Drupal\Core\TypedData\TypedDataTrait::getTypedDataManager() to + * ensure the typed configuration manager is returned. + * + * @return \Drupal\Core\Config\TypedConfigManagerInterface + * The typed configuration manager. + */ + public function getTypedDataManager() { + if (empty($this->typedDataManager)) { + $this->setTypedDataManager(\Drupal::service('config.typed')); + } + + return $this->typedDataManager; + } + + /** + * Sets the typed config manager. + * + * Overrides \Drupal\Core\TypedData\TypedDataTrait::setTypedDataManager() to + * ensure that only typed configuration manager can be used. + * + * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager + * The typed data manager. + * + * @return $this + */ + public function setTypedDataManager(TypedDataManagerInterface $typed_data_manager) { + assert('$typed_data_manager instanceof \Drupal\Core\Config\TypedConfigManagerInterface'); + $this->typedDataManager = $typed_data_manager; + return $this; + } + } diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php index 500fc3c..084f920 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManager.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php @@ -71,13 +71,7 @@ protected function getDiscovery() { /** - * Gets typed configuration data. - * - * @param string $name - * Configuration object name. - * - * @return \Drupal\Core\Config\Schema\TypedConfigInterface - * Typed configuration data. + * {@inheritdoc} */ public function get($name) { $data = $this->configStorage->read($name); @@ -338,17 +332,4 @@ protected function alterDefinitions(&$definitions) { } } - /** - * {@inheritdoc} - */ - public function createInstance($data_type, array $configuration = array()) { - $instance = parent::createInstance($data_type, $configuration); - // Enable elements to construct their own definitions using the typed config - // manager. - if ($instance instanceof ArrayElement) { - $instance->setTypedConfig($this); - } - return $instance; - } - } diff --git a/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php b/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php index 11c3751..dcd8584 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php @@ -7,9 +7,7 @@ namespace Drupal\Core\Config; -use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface; -use Drupal\Component\Plugin\PluginManagerInterface; -use Drupal\Core\TypedData\DataDefinitionInterface; +use Drupal\Core\TypedData\TypedDataManagerInterface; /** * Defines an interface for managing config schema type plugins. @@ -19,7 +17,7 @@ * @see hook_config_schema_info_alter() * @see https://www.drupal.org/node/1905070 */ -Interface TypedConfigManagerInterface extends PluginManagerInterface, CachedDiscoveryInterface { +Interface TypedConfigManagerInterface extends TypedDataManagerInterface { /** * Gets typed configuration data. @@ -33,48 +31,6 @@ public function get($name); /** - * Instantiates a typed configuration object. - * - * @param string $data_type - * The data type, for which a typed configuration object should be - * instantiated. - * @param array $configuration - * The plugin configuration array, i.e. an array with the following keys: - * - data definition: The data definition object, i.e. an instance of - * \Drupal\Core\TypedData\DataDefinitionInterface. - * - name: (optional) If a property or list item is to be created, the name - * of the property or the delta of the list item. - * - parent: (optional) If a property or list item is to be created, the - * parent typed data object implementing either the ListInterface or the - * ComplexDataInterface. - * - * @return \Drupal\Core\Config\Schema\Element - * The instantiated typed configuration object. - */ - public function createInstance($data_type, array $configuration = array()); - - /** - * Creates a new typed configuration object instance. - * - * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition - * The data definition of the typed data object. - * @param mixed $value - * The data value. If set, it has to match one of the supported - * data type format as documented for the data type classes. - * @param string $name - * (optional) If a property or list item is to be created, the name of the - * property or the delta of the list item. - * @param mixed $parent - * (optional) If a property or list item is to be created, the parent typed - * data object implementing either the ListInterface or the - * ComplexDataInterface. - * - * @return \Drupal\Core\Config\Schema\Element - * The instantiated typed data object. - */ - public function create(DataDefinitionInterface $definition, $value, $name = NULL, $parent = NULL); - - /** * Creates a new data definition object from a type definition array and * actual configuration data. Since type definitions may contain variables * to be replaced, we need the configuration value to create it. diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index ad0002e..4904e95 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -32,7 +32,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\Core\TypedData\TranslatableInterface; -use Drupal\Core\TypedData\TypedDataManager; +use Drupal\Core\TypedData\TypedDataManagerInterface; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -111,7 +111,7 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa /** * The typed data manager. * - * @var \Drupal\Core\TypedData\TypedDataManager + * @var \Drupal\Core\TypedData\TypedDataManagerInterface */ protected $typedDataManager; @@ -193,14 +193,14 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa * The string translationManager. * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver * The class resolver. - * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager + * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager * The typed data manager. * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory * The keyvalue factory. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * The event dispatcher. */ - public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver, TypedDataManager $typed_data_manager, KeyValueFactoryInterface $key_value_factory, EventDispatcherInterface $event_dispatcher) { + public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver, TypedDataManagerInterface $typed_data_manager, KeyValueFactoryInterface $key_value_factory, EventDispatcherInterface $event_dispatcher) { parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\EntityInterface'); $this->setCacheBackend($cache, 'entity_type', array('entity_types')); diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php index 1067ae8..4e775d2 100644 --- a/core/lib/Drupal/Core/Field/FieldItemList.php +++ b/core/lib/Drupal/Core/Field/FieldItemList.php @@ -281,7 +281,7 @@ public function getConstraints() { // widgets. $cardinality = $this->getFieldDefinition()->getFieldStorageDefinition()->getCardinality(); if ($cardinality != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { - $constraints[] = \Drupal::typedDataManager() + $constraints[] = $this->getTypedDataManager() ->getValidationConstraintManager() ->create('Count', array( 'max' => $cardinality, diff --git a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php index 000e3fe..3d896b2 100644 --- a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php +++ b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php @@ -13,7 +13,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\CategorizingPluginManagerTrait; use Drupal\Core\Plugin\DefaultPluginManager; -use Drupal\Core\TypedData\TypedDataManager; +use Drupal\Core\TypedData\TypedDataManagerInterface; /** * Plugin manager for 'field type' plugins. @@ -27,7 +27,7 @@ class FieldTypePluginManager extends DefaultPluginManager implements FieldTypePl /** * The typed data manager. * - * @var \Drupal\Core\TypedData\TypedDataManager + * @var \Drupal\Core\TypedData\TypedDataManagerInterface */ protected $typedDataManager; @@ -41,10 +41,10 @@ class FieldTypePluginManager extends DefaultPluginManager implements FieldTypePl * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface * The module handler. - * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager + * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager * The typed data manager. */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, TypedDataManager $typed_data_manager) { + public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, TypedDataManagerInterface $typed_data_manager) { parent::__construct('Plugin/Field/FieldType', $namespaces, $module_handler, 'Drupal\Core\Field\FieldItemInterface', 'Drupal\Core\Field\Annotation\FieldType'); $this->alterInfo('field_info'); $this->setCacheBackend($cache_backend, 'field_types_plugins'); diff --git a/core/lib/Drupal/Core/TypedData/DataReferenceBase.php b/core/lib/Drupal/Core/TypedData/DataReferenceBase.php index 1b9aaa5..4ad77bd 100644 --- a/core/lib/Drupal/Core/TypedData/DataReferenceBase.php +++ b/core/lib/Drupal/Core/TypedData/DataReferenceBase.php @@ -48,7 +48,7 @@ public function getValue() { * {@inheritdoc} */ public function setValue($value, $notify = TRUE) { - $this->target = \Drupal::typedDataManager()->create($this->definition->getTargetDefinition(), $value); + $this->target = $this->getTypedDataManager()->create($this->definition->getTargetDefinition(), $value); // Notify the parent of any changes. if ($notify && isset($this->parent)) { $this->parent->onChange($this->name); diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php index 2a868db..577bfb4 100644 --- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php @@ -222,7 +222,7 @@ public function appendItem($value = NULL) { * @return \Drupal\Core\TypedData\TypedDataInterface */ protected function createItem($offset = 0, $value = NULL) { - return \Drupal::typedDataManager()->getPropertyInstance($this, $offset, $value); + return $this->getTypedDataManager()->getPropertyInstance($this, $offset, $value); } /** diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php index 7694db5..6c0332b 100644 --- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php @@ -128,7 +128,7 @@ public function get($property_name) { $value = $this->values[$property_name]; } // If the property is unknown, this will throw an exception. - $this->properties[$property_name] = \Drupal::typedDataManager()->getPropertyInstance($this, $property_name, $value); + $this->properties[$property_name] = $this->getTypedDataManager()->getPropertyInstance($this, $property_name, $value); } return $this->properties[$property_name]; } diff --git a/core/lib/Drupal/Core/TypedData/TypedData.php b/core/lib/Drupal/Core/TypedData/TypedData.php index 92c8a89..a266daa 100644 --- a/core/lib/Drupal/Core/TypedData/TypedData.php +++ b/core/lib/Drupal/Core/TypedData/TypedData.php @@ -21,6 +21,7 @@ abstract class TypedData implements TypedDataInterface, PluginInspectionInterface { use StringTranslationTrait; + use TypedDataTrait; /** * The data definition. @@ -85,7 +86,7 @@ public function getPluginId() { * {@inheritdoc} */ public function getPluginDefinition() { - return \Drupal::typedDataManager()->getDefinition($this->definition->getDataType()); + return $this->getTypedDataManager()->getDefinition($this->definition->getDataType()); } /** @@ -124,8 +125,7 @@ public function getString() { * {@inheritdoc} */ public function getConstraints() { - // @todo: Add the typed data manager as proper dependency. - $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager(); + $constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager(); $constraints = array(); foreach ($this->definition->getConstraints() as $name => $options) { $constraints[] = $constraint_manager->create($name, $options); @@ -137,8 +137,7 @@ public function getConstraints() { * {@inheritdoc} */ public function validate() { - // @todo: Add the typed data manager as proper dependency. - return \Drupal::typedDataManager()->getValidator()->validate($this); + return $this->getTypedDataManager()->getValidator()->validate($this); } /** diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index 858d13d..bd9717b 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -23,7 +23,7 @@ /** * Manages data type plugins. */ -class TypedDataManager extends DefaultPluginManager { +class TypedDataManager extends DefaultPluginManager implements TypedDataManagerInterface { use DependencySerializationTrait; /** @@ -76,22 +76,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac } /** - * Instantiates a typed data object. - * - * @param string $data_type - * The data type, for which a typed object should be instantiated. - * @param array $configuration - * The plugin configuration array, i.e. an array with the following keys: - * - data_definition: The data definition object, i.e. an instance of - * \Drupal\Core\TypedData\DataDefinitionInterface. - * - name: (optional) If a property or list item is to be created, the name - * of the property or the delta of the list item. - * - parent: (optional) If a property or list item is to be created, the - * parent typed data object implementing either the ListInterface or the - * ComplexDataInterface. - * - * @return \Drupal\Core\TypedData\TypedDataInterface - * The instantiated typed data object. + * {@inheritdoc} */ public function createInstance($data_type, array $configuration = array()) { $data_definition = $configuration['data_definition']; @@ -108,39 +93,13 @@ public function createInstance($data_type, array $configuration = array()) { if (!isset($class)) { throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $data_type)); } - return $class::createInstance($data_definition, $configuration['name'], $configuration['parent']); + $typed_data = $class::createInstance($data_definition, $configuration['name'], $configuration['parent']); + $typed_data->setTypedDataManager($this); + return $typed_data; } /** - * Creates a new typed data object instance. - * - * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition - * The data definition of the typed data object. For backwards-compatibility - * an array representation of the data definition may be passed also. - * @param mixed $value - * (optional) The data value. If set, it has to match one of the supported - * data type format as documented for the data type classes. - * @param string $name - * (optional) If a property or list item is to be created, the name of the - * property or the delta of the list item. - * @param mixed $parent - * (optional) If a property or list item is to be created, the parent typed - * data object implementing either the ListInterface or the - * ComplexDataInterface. - * - * @return \Drupal\Core\TypedData\TypedDataInterface - * The instantiated typed data object. - * - * @see \Drupal::typedDataManager() - * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() - * @see \Drupal\Core\TypedData\Plugin\DataType\BinaryData - * @see \Drupal\Core\TypedData\Plugin\DataType\BooleanData - * @see \Drupal\Core\TypedData\Plugin\DataType\Date - * @see \Drupal\Core\TypedData\Plugin\DataType\Duration - * @see \Drupal\Core\TypedData\Plugin\DataType\FloatData - * @see \Drupal\Core\TypedData\Plugin\DataType\IntegerData - * @see \Drupal\Core\TypedData\Plugin\DataType\StringData - * @see \Drupal\Core\TypedData\Plugin\DataType\Uri + * {@inheritdoc} */ public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL) { $typed_data = $this->createInstance($definition->getDataType(), array( @@ -155,25 +114,7 @@ public function create(DataDefinitionInterface $definition, $value = NULL, $name } /** - * Creates a new data definition object. - * - * While data definitions objects may be created directly if the definition - * class used by a data type is known, this method allows the creation of data - * definitions for any given data type. - * - * E.g., if a definition for a map is to be created, the following code - * could be used instead of calling this method with the argument 'map': - * @code - * $map_definition = \Drupal\Core\TypedData\MapDataDefinition::create(); - * @endcode - * - * @param string $data_type - * The data type, for which a data definition should be created. - * - * @return \Drupal\Core\TypedData\DataDefinitionInterface - * A data definition for the given data type. - * - * @see \Drupal\Core\TypedData\TypedDataManager::createListDataDefinition() + * {@inheritdoc} */ public function createDataDefinition($data_type) { $type_definition = $this->getDefinition($data_type); @@ -185,15 +126,7 @@ public function createDataDefinition($data_type) { } /** - * Creates a new list data definition for items of the given data type. - * - * @param string $item_type - * The item type, for which a list data definition should be created. - * - * @return \Drupal\Core\TypedData\ListDataDefinitionInterface - * A list definition for items of the given data type. - * - * @see \Drupal\Core\TypedData\TypedDataManager::createDataDefinition() + * {@inheritdoc} */ public function createListDataDefinition($item_type) { $type_definition = $this->getDefinition($item_type); @@ -205,59 +138,14 @@ public function createListDataDefinition($item_type) { } /** - * Implements \Drupal\Component\Plugin\PluginManagerInterface::getInstance(). - * - * @param array $options - * An array of options with the following keys: - * - object: The parent typed data object, implementing the - * TypedDataInterface and either the ListInterface or the - * ComplexDataInterface. - * - property: The name of the property to instantiate, or the delta of the - * the list item to instantiate. - * - value: The value to set. If set, it has to match one of the supported - * data type formats as documented by the data type classes. - * - * @throws \InvalidArgumentException - * If the given property is not known, or the passed object does not - * implement the ListInterface or the ComplexDataInterface. - * - * @return \Drupal\Core\TypedData\TypedDataInterface - * The new property instance. - * - * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() + * {@inheritdoc} */ public function getInstance(array $options) { return $this->getPropertyInstance($options['object'], $options['property'], $options['value']); } /** - * Get a typed data instance for a property of a given typed data object. - * - * This method will use prototyping for fast and efficient instantiation of - * many property objects with the same property path; e.g., - * when multiple comments are used comment_body.0.value needs to be - * instantiated very often. - * Prototyping is done by the root object's data type and the given - * property path, i.e. all property instances having the same property path - * and inheriting from the same data type are prototyped. - * - * @param \Drupal\Core\TypedData\TypedDataInterface $object - * The parent typed data object, implementing the TypedDataInterface and - * either the ListInterface or the ComplexDataInterface. - * @param string $property_name - * The name of the property to instantiate, or the delta of an list item. - * @param mixed $value - * (optional) The data value. If set, it has to match one of the supported - * data type formats as documented by the data type classes. - * - * @throws \InvalidArgumentException - * If the given property is not known, or the passed object does not - * implement the ListInterface or the ComplexDataInterface. - * - * @return \Drupal\Core\TypedData\TypedDataInterface - * The new property instance. - * - * @see \Drupal\Core\TypedData\TypedDataManager::create() + * {@inheritdoc} */ public function getPropertyInstance(TypedDataInterface $object, $property_name, $value = NULL) { // For performance, try to reuse existing prototypes instead of @@ -325,10 +213,7 @@ public function setValidator(ValidatorInterface $validator) { } /** - * Gets the validator for validating typed data. - * - * @return \Symfony\Component\Validator\Validator\ValidatorInterface - * The validator object. + * {@inheritdoc} */ public function getValidator() { if (!isset($this->validator)) { @@ -342,43 +227,21 @@ public function getValidator() { } /** - * Sets the validation constraint manager. - * - * The validation constraint manager is used to instantiate validation - * constraint plugins. - * - * @param \Drupal\Core\Validation\ConstraintManager - * The constraint manager to set. + * {@inheritdoc} */ public function setValidationConstraintManager(ConstraintManager $constraintManager) { $this->constraintManager = $constraintManager; } /** - * Gets the validation constraint manager. - * - * @return \Drupal\Core\Validation\ConstraintManager - * The constraint manager. + * {@inheritdoc} */ public function getValidationConstraintManager() { return $this->constraintManager; } /** - * Gets default constraints for the given data definition. - * - * This generates default constraint definitions based on the data definition; - * e.g. a NotNull constraint is generated if the data is defined as required. - * Besides that any constraints defined for the data type, i.e. below the - * 'constraint' key of the type's plugin definition, are taken into account. - * - * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition - * A data definition. - * - * @return array - * An array of validation constraint definitions, keyed by constraint name. - * Each constraint definition can be used for instantiating - * \Symfony\Component\Validator\Constraint objects. + * {@inheritdoc} */ public function getDefaultConstraints(DataDefinitionInterface $definition) { $constraints = array(); @@ -412,30 +275,7 @@ public function clearCachedDefinitions() { } /** - * Gets the canonical representation of a TypedData object. - * - * The canonical representation is typically used when data is passed on to - * other code components. In many use cases, the TypedData object is mostly - * unified adapter wrapping a primary value (e.g. a string, an entity...) - * which is the canonical representation that consuming code like constraint - * validators are really interested in. For some APIs, though, the domain - * object (e.g. Field API's FieldItem and FieldItemList) directly implements - * TypedDataInterface, and the canonical representation is thus the data - * object itself. - * - * When a TypedData object gets validated, for example, its canonical - * representation is passed on to constraint validators, which thus receive - * an Entity unwrapped, but a FieldItem as is. - * - * Data types specify whether their data objects need unwrapping by using the - * 'unwrap_for_canonical_representation' property in the data definition - * (defaults to TRUE). - * - * @param \Drupal\Core\TypedData\TypedDataInterface $data - * The data. - * - * @return mixed - * The canonical representation of the passed data. + * {@inheritdoc} */ public function getCanonicalRepresentation(TypedDataInterface $data) { $data_definition = $data->getDataDefinition(); diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManagerInterface.php similarity index 50% copy from core/lib/Drupal/Core/TypedData/TypedDataManager.php copy to core/lib/Drupal/Core/TypedData/TypedDataManagerInterface.php index 858d13d..58bba2c 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManagerInterface.php @@ -2,81 +2,23 @@ /** * @file - * Contains \Drupal\Core\TypedData\TypedDataManager. + * Contains \Drupal\Core\TypedData\TypedDataManagerInterface. */ namespace Drupal\Core\TypedData; -use Drupal\Component\Plugin\Exception\PluginException; -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\DependencyInjection\ClassResolverInterface; -use Drupal\Core\DependencyInjection\DependencySerializationTrait; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Plugin\DefaultPluginManager; -use Drupal\Core\TypedData\Validation\ExecutionContextFactory; -use Drupal\Core\TypedData\Validation\RecursiveValidator; +use Drupal\Component\Plugin\PluginManagerInterface; +use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface; use Drupal\Core\Validation\ConstraintManager; -use Drupal\Core\Validation\ConstraintValidatorFactory; -use Drupal\Core\Validation\DrupalTranslator; use Symfony\Component\Validator\Validator\ValidatorInterface; /** - * Manages data type plugins. + * Defines an interface for typed data manager. */ -class TypedDataManager extends DefaultPluginManager { - use DependencySerializationTrait; +Interface TypedDataManagerInterface extends PluginManagerInterface, CachedDiscoveryInterface { /** - * The validator used for validating typed data. - * - * @var \Symfony\Component\Validator\Validator\ValidatorInterface - */ - protected $validator; - - /** - * The validation constraint manager to use for instantiating constraints. - * - * @var \Drupal\Core\Validation\ConstraintManager - */ - protected $constraintManager; - - /** - * An array of typed data property prototypes. - * - * @var array - */ - protected $prototypes = array(); - - /** - * The class resolver. - * - * @var \Drupal\Core\DependencyInjection\ClassResolverInterface - */ - protected $classResolver; - - /** - * Constructs a new TypedDataManager. - * - * @param \Traversable $namespaces - * An object that implements \Traversable which contains the root paths - * keyed by the corresponding namespace to look for plugin implementations. - * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend - * Cache backend instance to use. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. - * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver - * The class resolver. - */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ClassResolverInterface $class_resolver) { - $this->alterInfo('data_type_info'); - $this->setCacheBackend($cache_backend, 'typed_data_types_plugins'); - $this->classResolver = $class_resolver; - - parent::__construct('Plugin/DataType', $namespaces, $module_handler, NULL, 'Drupal\Core\TypedData\Annotation\DataType'); - } - - /** - * Instantiates a typed data object. + * {@inheritdoc} * * @param string $data_type * The data type, for which a typed object should be instantiated. @@ -93,23 +35,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac * @return \Drupal\Core\TypedData\TypedDataInterface * The instantiated typed data object. */ - public function createInstance($data_type, array $configuration = array()) { - $data_definition = $configuration['data_definition']; - $type_definition = $this->getDefinition($data_type); - - if (!isset($type_definition)) { - throw new \InvalidArgumentException("Invalid data type '$data_type' has been given"); - } - - // Allow per-data definition overrides of the used classes, i.e. take over - // classes specified in the type definition. - $class = $data_definition->getClass(); - - if (!isset($class)) { - throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $data_type)); - } - return $class::createInstance($data_definition, $configuration['name'], $configuration['parent']); - } + public function createInstance($data_type, array $configuration = array()); /** * Creates a new typed data object instance. @@ -131,7 +57,6 @@ public function createInstance($data_type, array $configuration = array()) { * @return \Drupal\Core\TypedData\TypedDataInterface * The instantiated typed data object. * - * @see \Drupal::typedDataManager() * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() * @see \Drupal\Core\TypedData\Plugin\DataType\BinaryData * @see \Drupal\Core\TypedData\Plugin\DataType\BooleanData @@ -142,17 +67,7 @@ public function createInstance($data_type, array $configuration = array()) { * @see \Drupal\Core\TypedData\Plugin\DataType\StringData * @see \Drupal\Core\TypedData\Plugin\DataType\Uri */ - public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL) { - $typed_data = $this->createInstance($definition->getDataType(), array( - 'data_definition' => $definition, - 'name' => $name, - 'parent' => $parent, - )); - if (isset($value)) { - $typed_data->setValue($value, FALSE); - } - return $typed_data; - } + public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL); /** * Creates a new data definition object. @@ -175,14 +90,7 @@ public function create(DataDefinitionInterface $definition, $value = NULL, $name * * @see \Drupal\Core\TypedData\TypedDataManager::createListDataDefinition() */ - public function createDataDefinition($data_type) { - $type_definition = $this->getDefinition($data_type); - if (!isset($type_definition)) { - throw new \InvalidArgumentException("Invalid data type '$data_type' has been given"); - } - $class = $type_definition['definition_class']; - return $class::createFromDataType($data_type); - } + public function createDataDefinition($data_type); /** * Creates a new list data definition for items of the given data type. @@ -195,17 +103,10 @@ public function createDataDefinition($data_type) { * * @see \Drupal\Core\TypedData\TypedDataManager::createDataDefinition() */ - public function createListDataDefinition($item_type) { - $type_definition = $this->getDefinition($item_type); - if (!isset($type_definition)) { - throw new \InvalidArgumentException("Invalid data type '$item_type' has been given"); - } - $class = $type_definition['list_definition_class']; - return $class::createFromItemType($item_type); - } + public function createListDataDefinition($item_type); /** - * Implements \Drupal\Component\Plugin\PluginManagerInterface::getInstance(). + * {@inheritdoc} * * @param array $options * An array of options with the following keys: @@ -226,9 +127,7 @@ public function createListDataDefinition($item_type) { * * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() */ - public function getInstance(array $options) { - return $this->getPropertyInstance($options['object'], $options['property'], $options['value']); - } + public function getInstance(array $options); /** * Get a typed data instance for a property of a given typed data object. @@ -259,60 +158,15 @@ public function getInstance(array $options) { * * @see \Drupal\Core\TypedData\TypedDataManager::create() */ - public function getPropertyInstance(TypedDataInterface $object, $property_name, $value = NULL) { - // For performance, try to reuse existing prototypes instead of - // constructing new objects when possible. A prototype is reused when - // creating a data object: - // - for a similar root object (same data type and settings), - // - at the same property path under that root object. - $root_definition = $object->getRoot()->getDataDefinition(); - // If the root object is a list, we want to look at the data type and the - // settings of its item definition. - if ($root_definition instanceof ListDataDefinition) { - $root_definition = $root_definition->getItemDefinition(); - } + public function getPropertyInstance(TypedDataInterface $object, $property_name, $value = NULL); - // Root data type and settings. - $parts[] = $root_definition->getDataType(); - if ($settings = $root_definition->getSettings()) { - // Hash the settings into a string. crc32 is the fastest way to hash - // something for non-cryptographic purposes. - $parts[] = crc32(serialize($settings)); - } - // Property path for the requested data object. When creating a list item, - // use 0 in the key as all items look the same. - $parts[] = $object->getPropertyPath() . '.' . (is_numeric($property_name) ? 0 : $property_name); - $key = implode(':', $parts); - - // Create the prototype if needed. - if (!isset($this->prototypes[$key])) { - // Fetch the data definition for the child object from the parent. - if ($object instanceof ComplexDataInterface) { - $definition = $object->getDataDefinition()->getPropertyDefinition($property_name); - } - elseif ($object instanceof ListInterface) { - $definition = $object->getItemDefinition(); - } - else { - throw new \InvalidArgumentException("The passed object has to either implement the ComplexDataInterface or the ListInterface."); - } - if (!$definition) { - throw new \InvalidArgumentException("Property $property_name is unknown."); - } - // Create the prototype without any value, but with initial parenting - // so that constructors can set up the objects correclty. - $this->prototypes[$key] = $this->create($definition, NULL, $property_name, $object); - } - - // Clone the prototype, update its parenting information, and assign the - // value. - $property = clone $this->prototypes[$key]; - $property->setContext($property_name, $object); - if (isset($value)) { - $property->setValue($value, FALSE); - } - return $property; - } + /** + * Gets the validator for validating typed data. + * + * @return \Symfony\Component\Validator\Validator\ValidatorInterface + * The validator object. + */ + public function getValidator(); /** * Sets the validator for validating typed data. @@ -320,26 +174,15 @@ public function getPropertyInstance(TypedDataInterface $object, $property_name, * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator * The validator object to set. */ - public function setValidator(ValidatorInterface $validator) { - $this->validator = $validator; - } + public function setValidator(ValidatorInterface $validator); /** - * Gets the validator for validating typed data. + * Gets the validation constraint manager. * - * @return \Symfony\Component\Validator\Validator\ValidatorInterface - * The validator object. + * @return \Drupal\Core\Validation\ConstraintManager + * The constraint manager. */ - public function getValidator() { - if (!isset($this->validator)) { - $this->validator = new RecursiveValidator( - new ExecutionContextFactory(new DrupalTranslator()), - new ConstraintValidatorFactory($this->classResolver), - $this - ); - } - return $this->validator; - } + public function getValidationConstraintManager(); /** * Sets the validation constraint manager. @@ -350,19 +193,7 @@ public function getValidator() { * @param \Drupal\Core\Validation\ConstraintManager * The constraint manager to set. */ - public function setValidationConstraintManager(ConstraintManager $constraintManager) { - $this->constraintManager = $constraintManager; - } - - /** - * Gets the validation constraint manager. - * - * @return \Drupal\Core\Validation\ConstraintManager - * The constraint manager. - */ - public function getValidationConstraintManager() { - return $this->constraintManager; - } + public function setValidationConstraintManager(ConstraintManager $constraintManager); /** * Gets default constraints for the given data definition. @@ -380,36 +211,7 @@ public function getValidationConstraintManager() { * Each constraint definition can be used for instantiating * \Symfony\Component\Validator\Constraint objects. */ - public function getDefaultConstraints(DataDefinitionInterface $definition) { - $constraints = array(); - $type_definition = $this->getDefinition($definition->getDataType()); - // Auto-generate a constraint for data types implementing a primitive - // interface. - if (is_subclass_of($type_definition['class'], '\Drupal\Core\TypedData\PrimitiveInterface')) { - $constraints['PrimitiveType'] = array(); - } - // Add in constraints specified by the data type. - if (isset($type_definition['constraints'])) { - $constraints += $type_definition['constraints']; - } - // Add the NotNull constraint for required data. - if ($definition->isRequired()) { - $constraints['NotNull'] = array(); - } - // Check if the class provides allowed values. - if (is_subclass_of($definition->getClass(),'Drupal\Core\TypedData\OptionsProviderInterface')) { - $constraints['AllowedValues'] = array(); - } - return $constraints; - } - - /** - * {@inheritdoc} - */ - public function clearCachedDefinitions() { - parent::clearCachedDefinitions(); - $this->prototypes = array(); - } + public function getDefaultConstraints(DataDefinitionInterface $definition); /** * Gets the canonical representation of a TypedData object. @@ -437,18 +239,6 @@ public function clearCachedDefinitions() { * @return mixed * The canonical representation of the passed data. */ - public function getCanonicalRepresentation(TypedDataInterface $data) { - $data_definition = $data->getDataDefinition(); - // In case a list is passed, respect the 'wrapped' key of its data type. - if ($data_definition instanceof ListDataDefinitionInterface) { - $data_definition = $data_definition->getItemDefinition(); - } - // Get the plugin definition of the used data type. - $type_definition = $this->getDefinition($data_definition->getDataType()); - if (!empty($type_definition['unwrap_for_canonical_representation'])) { - return $data->getValue(); - } - return $data; - } + public function getCanonicalRepresentation(TypedDataInterface $data); } diff --git a/core/lib/Drupal/Core/TypedData/TypedDataTrait.php b/core/lib/Drupal/Core/TypedData/TypedDataTrait.php index 737a86a..b2cde54 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataTrait.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataTrait.php @@ -15,19 +15,19 @@ /** * The typed data manager used for creating the data types. * - * @var \Drupal\Core\TypedData\TypedDataManager + * @var \Drupal\Core\TypedData\TypedDataManagerInterface */ protected $typedDataManager; /** * Sets the typed data manager. * - * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager + * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager * The typed data manager. * * @return $this */ - public function setTypedDataManager(TypedDataManager $typed_data_manager) { + public function setTypedDataManager(TypedDataManagerInterface $typed_data_manager) { $this->typedDataManager = $typed_data_manager; return $this; } @@ -35,7 +35,7 @@ public function setTypedDataManager(TypedDataManager $typed_data_manager) { /** * Gets the typed data manager. * - * @return \Drupal\Core\TypedData\TypedDataManager + * @return \Drupal\Core\TypedData\TypedDataManagerInterface * The typed data manager. */ public function getTypedDataManager() { diff --git a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php index 81b8eeb..05fe0a0 100644 --- a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php +++ b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php @@ -10,7 +10,7 @@ use Drupal\Core\TypedData\ComplexDataInterface; use Drupal\Core\TypedData\ListInterface; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\Core\TypedData\TypedDataManager; +use Drupal\Core\TypedData\TypedDataManagerInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; @@ -64,10 +64,10 @@ class RecursiveContextualValidator implements ContextualValidatorInterface { * The metadata factory. * @param \Symfony\Component\Validator\ConstraintValidatorFactoryInterface $validator_factory * The constraint validator factory. - * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager + * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager * The typed data manager. */ - public function __construct(ExecutionContextInterface $context, MetadataFactoryInterface $metadata_factory, ConstraintValidatorFactoryInterface $validator_factory, TypedDataManager $typed_data_manager) { + public function __construct(ExecutionContextInterface $context, MetadataFactoryInterface $metadata_factory, ConstraintValidatorFactoryInterface $validator_factory, TypedDataManagerInterface $typed_data_manager) { $this->context = $context; $this->metadataFactory = $metadata_factory; $this->constraintValidatorFactory = $validator_factory; diff --git a/core/lib/Drupal/Core/TypedData/Validation/RecursiveValidator.php b/core/lib/Drupal/Core/TypedData/Validation/RecursiveValidator.php index c828cba..e5260f7 100644 --- a/core/lib/Drupal/Core/TypedData/Validation/RecursiveValidator.php +++ b/core/lib/Drupal/Core/TypedData/Validation/RecursiveValidator.php @@ -8,7 +8,7 @@ namespace Drupal\Core\TypedData\Validation; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\Core\TypedData\TypedDataManager; +use Drupal\Core\TypedData\TypedDataManagerInterface; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; use Symfony\Component\Validator\Context\ExecutionContextFactoryInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; @@ -44,10 +44,10 @@ class RecursiveValidator implements ValidatorInterface { * The factory for creating new contexts. * @param \Symfony\Component\Validator\ConstraintValidatorFactoryInterface $validator_factory * The constraint validator factory. - * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager + * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager * The typed data manager. */ - public function __construct(ExecutionContextFactoryInterface $context_factory, ConstraintValidatorFactoryInterface $validator_factory, TypedDataManager $typed_data_manager) { + public function __construct(ExecutionContextFactoryInterface $context_factory, ConstraintValidatorFactoryInterface $validator_factory, TypedDataManagerInterface $typed_data_manager) { $this->contextFactory = $context_factory; $this->constraintValidatorFactory = $validator_factory; $this->typedDataManager = $typed_data_manager;