function TypedDataManager::getPropertyInstance

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

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.