function TypedDataManager::getPropertyInstance

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/TypedData/TypedDataManager.php \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance()
  2. 10 core/lib/Drupal/Core/TypedData/TypedDataManager.php \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance()
  3. 11.x core/lib/Drupal/Core/TypedData/TypedDataManager.php \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance()

Overrides TypedDataManagerInterface::getPropertyInstance

1 call to TypedDataManager::getPropertyInstance()
TypedDataManager::getInstance in core/lib/Drupal/Core/TypedData/TypedDataManager.php

File

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

Class

TypedDataManager
Manages data type plugins.

Namespace

Drupal\Core\TypedData

Code

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;
}

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