class TypedDataManager

Same name in other branches
  1. 9 core/lib/Drupal/Core/TypedData/TypedDataManager.php \Drupal\Core\TypedData\TypedDataManager
  2. 8.9.x core/lib/Drupal/Core/TypedData/TypedDataManager.php \Drupal\Core\TypedData\TypedDataManager
  3. 10 core/lib/Drupal/Core/TypedData/TypedDataManager.php \Drupal\Core\TypedData\TypedDataManager

Manages data type plugins.

Hierarchy

Expanded class hierarchy of TypedDataManager

7 files declare their use of TypedDataManager
ContextDefinitionIsSatisfiedTest.php in core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php
ContextHandlerTest.php in core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
EntityContextDefinitionIsSatisfiedTest.php in core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionIsSatisfiedTest.php
FieldDefinitionTest.php in core/tests/Drupal/Tests/Core/Entity/FieldDefinitionTest.php
FieldTypePluginManagerTest.php in core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php

... See full list

File

core/lib/Drupal/Core/TypedData/TypedDataManager.php, line 22

Namespace

Drupal\Core\TypedData
View source
class TypedDataManager extends DefaultPluginManager implements TypedDataManagerInterface {
    use DependencySerializationTrait;
    
    /**
     * 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 = [];
    
    /**
     * 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, DataType::class, 'Drupal\\Core\\TypedData\\Annotation\\DataType');
    }
    
    /**
     * {@inheritdoc}
     */
    public function createInstance($data_type, array $configuration = []) {
        $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));
        }
        $typed_data = $class::createInstance($data_definition, $configuration['name'], $configuration['parent']);
        $typed_data->setTypedDataManager($this);
        return $typed_data;
    }
    
    /**
     * {@inheritdoc}
     */
    public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL) {
        $typed_data = $this->createInstance($definition->getDataType(), [
            'data_definition' => $definition,
            'name' => $name,
            'parent' => $parent,
        ]);
        if (isset($value)) {
            $typed_data->setValue($value, FALSE);
        }
        return $typed_data;
    }
    
    /**
     * {@inheritdoc}
     */
    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'];
        $data_definition = $class::createFromDataType($data_type);
        if (method_exists($data_definition, 'setTypedDataManager')) {
            $data_definition->setTypedDataManager($this);
        }
        return $data_definition;
    }
    
    /**
     * {@inheritdoc}
     */
    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);
    }
    
    /**
     * {@inheritdoc}
     */
    public function getInstance(array $options) {
        return $this->getPropertyInstance($options['object'], $options['property'], $options['value']);
    }
    
    /**
     * {@inheritdoc}
     */
    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();
        }
        // Root data type and settings.
        $parts[] = $root_definition->getDataType();
        if ($settings = $root_definition->getSettings()) {
            // Include the settings serialized as JSON as part of the key. The JSON is
            // a shorter string than the serialized form, so array access is faster.
            $parts[] = json_encode($settings);
        }
        // Property path for the requested data object.
        $parts[] = $object->getPropertyPath();
        // Only property instances of complex data types should be cached by the
        // property name, as they represent different properties. Properties of list
        // data types are the items of the list and the property name represents
        // only the delta in that list and not an unique property, which is why all
        // items should use the same prototype.
        if ($object instanceof ComplexDataInterface) {
            $parts[] = $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 correctly.
            $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;
    }
    
    /**
     * Sets the validator for validating typed data.
     *
     * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator
     *   The validator object to set.
     */
    public function setValidator(ValidatorInterface $validator) {
        $this->validator = $validator;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getValidator() {
        if (!isset($this->validator)) {
            $this->validator = new RecursiveValidator(new ExecutionContextFactory(new DrupalTranslator()), new ConstraintValidatorFactory($this->classResolver), $this);
        }
        return $this->validator;
    }
    
    /**
     * {@inheritdoc}
     */
    public function setValidationConstraintManager(ConstraintManager $constraintManager) {
        $this->constraintManager = $constraintManager;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getValidationConstraintManager() {
        return $this->constraintManager;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getDefaultConstraints(DataDefinitionInterface $definition) {
        $constraints = [];
        $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'] = [];
        }
        // 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'] = [];
        }
        // Check if the class provides allowed values.
        if (is_subclass_of($definition->getClass(), 'Drupal\\Core\\TypedData\\OptionsProviderInterface')) {
            $constraints['AllowedValues'] = [];
        }
        return $constraints;
    }
    
    /**
     * {@inheritdoc}
     */
    public function clearCachedDefinitions() {
        parent::clearCachedDefinitions();
        $this->prototypes = [];
    }
    
    /**
     * {@inheritdoc}
     */
    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;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
DefaultPluginManager::$additionalAnnotationNamespaces protected property Additional annotation namespaces.
DefaultPluginManager::$alterHook protected property Name of the alter hook if one should be invoked.
DefaultPluginManager::$cacheKey protected property The cache key.
DefaultPluginManager::$cacheTags protected property An array of cache tags to use for the cached definitions.
DefaultPluginManager::$defaults protected property A set of defaults to be referenced by $this->processDefinition(). 12
DefaultPluginManager::$moduleExtensionList protected property The module extension list.
DefaultPluginManager::$moduleHandler protected property The module handler to invoke the alter hook. 1
DefaultPluginManager::$namespaces protected property An object of root paths that are traversable.
DefaultPluginManager::$pluginDefinitionAnnotationName protected property The name of the annotation that contains the plugin definition.
DefaultPluginManager::$pluginDefinitionAttributeName protected property The name of the attribute that contains the plugin definition.
DefaultPluginManager::$pluginInterface protected property The interface each plugin should implement. 1
DefaultPluginManager::$subdir protected property The subdirectory within a namespace to look for plugins.
DefaultPluginManager::alterDefinitions protected function Invokes the hook to alter the definitions if the alter hook is set. 5
DefaultPluginManager::alterInfo protected function Sets the alter hook name.
DefaultPluginManager::extractProviderFromDefinition protected function Extracts the provider from a plugin definition.
DefaultPluginManager::findDefinitions protected function Finds plugin definitions. 7
DefaultPluginManager::getCacheContexts public function The cache contexts associated with this object. Overrides CacheableDependencyInterface::getCacheContexts
DefaultPluginManager::getCachedDefinitions protected function Returns the cached plugin definitions of the decorated discovery class.
DefaultPluginManager::getCacheMaxAge public function The maximum age for which this object may be cached. Overrides CacheableDependencyInterface::getCacheMaxAge
DefaultPluginManager::getCacheTags public function The cache tags associated with this object. Overrides CacheableDependencyInterface::getCacheTags
DefaultPluginManager::getDefinitions public function Gets the definition of all plugins for this type. Overrides DiscoveryTrait::getDefinitions 2
DefaultPluginManager::getDiscovery protected function Gets the plugin discovery. Overrides PluginManagerBase::getDiscovery 16
DefaultPluginManager::getFactory protected function Gets the plugin factory. Overrides PluginManagerBase::getFactory
DefaultPluginManager::processDefinition public function Performs extra processing on plugin definitions. 14
DefaultPluginManager::providerExists protected function Determines if the provider of a definition exists. 5
DefaultPluginManager::setCacheBackend public function Initialize the cache backend.
DefaultPluginManager::setCachedDefinitions protected function Sets a cache of plugin definitions for the decorated discovery class.
DefaultPluginManager::useCaches public function Disable the use of caches. Overrides CachedDiscoveryInterface::useCaches 1
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
DiscoveryCachedTrait::$definitions protected property Cached definitions array. 1
DiscoveryCachedTrait::getDefinition public function Overrides DiscoveryTrait::getDefinition 3
DiscoveryTrait::doGetDefinition protected function Gets a specific plugin definition.
DiscoveryTrait::hasDefinition public function
PluginManagerBase::$discovery protected property The object that discovers plugins managed by this manager.
PluginManagerBase::$factory protected property The object that instantiates plugins managed by this manager.
PluginManagerBase::$mapper protected property The object that returns the preconfigured plugin instance appropriate for a particular runtime condition.
PluginManagerBase::getFallbackPluginId protected function Gets a fallback id for a missing plugin. 6
PluginManagerBase::handlePluginNotFound protected function Allows plugin managers to specify custom behavior if a plugin is not found. 1
TypedDataManager::$classResolver protected property The class resolver.
TypedDataManager::$constraintManager protected property The validation constraint manager to use for instantiating constraints.
TypedDataManager::$prototypes protected property An array of typed data property prototypes.
TypedDataManager::$validator protected property The validator used for validating typed data.
TypedDataManager::clearCachedDefinitions public function Clears static and persistent plugin definition caches. Overrides DefaultPluginManager::clearCachedDefinitions 1
TypedDataManager::create public function Creates a new typed data object instance. Overrides TypedDataManagerInterface::create
TypedDataManager::createDataDefinition public function Creates a new data definition object. Overrides TypedDataManagerInterface::createDataDefinition
TypedDataManager::createInstance public function Instantiates a typed data object. Overrides PluginManagerBase::createInstance
TypedDataManager::createListDataDefinition public function Creates a new list data definition for items of the given data type. Overrides TypedDataManagerInterface::createListDataDefinition
TypedDataManager::getCanonicalRepresentation public function Gets the canonical representation of a TypedData object. Overrides TypedDataManagerInterface::getCanonicalRepresentation
TypedDataManager::getDefaultConstraints public function Gets default constraints for the given data definition. Overrides TypedDataManagerInterface::getDefaultConstraints
TypedDataManager::getInstance public function Overrides PluginManagerBase::getInstance
TypedDataManager::getPropertyInstance public function Get a typed data instance for a property of a given typed data object. Overrides TypedDataManagerInterface::getPropertyInstance
TypedDataManager::getValidationConstraintManager public function Gets the validation constraint manager. Overrides TypedDataManagerInterface::getValidationConstraintManager
TypedDataManager::getValidator public function Gets the validator for validating typed data. Overrides TypedDataManagerInterface::getValidator
TypedDataManager::setValidationConstraintManager public function Sets the validation constraint manager. Overrides TypedDataManagerInterface::setValidationConstraintManager
TypedDataManager::setValidator public function Sets the validator for validating typed data. Overrides TypedDataManagerInterface::setValidator
TypedDataManager::__construct public function Constructs a new TypedDataManager. Overrides DefaultPluginManager::__construct 1
UseCacheBackendTrait::$cacheBackend protected property Cache backend instance.
UseCacheBackendTrait::$useCaches protected property Flag whether caches should be used or skipped.
UseCacheBackendTrait::cacheGet protected function Fetches from the cache backend, respecting the use caches flag.
UseCacheBackendTrait::cacheSet protected function Stores data in the persistent cache, respecting the use caches flag.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.