diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 54051a6..392ff27 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -421,40 +421,15 @@ public function getNGEntity() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getType(). - */ - public function getType() { - // @todo: Incorporate the entity type here by making entities proper - // typed data. See http://drupal.org/node/1868004. - return 'entity'; - } - - /** * Implements \Drupal\Core\TypedData\TypedDataInterface::getDefinition(). */ public function getDefinition() { return array( - 'type' => $this->getType() + 'type' => 'entity', ); } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getValue(). - */ - public function getValue() { - // @todo: Implement by making entities proper typed data. See - // http://drupal.org/node/1868004. - } - - /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue(). - */ - public function setValue($value, $notify = TRUE) { - // @todo: Implement by making entities proper typed data. See - // http://drupal.org/node/1868004. - } - - /** * Implements \Drupal\Core\TypedData\TypedDataInterface::getString(). */ public function getString() { @@ -463,7 +438,7 @@ public function getString() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getConstraints(). + * {@inheritdoc} */ public function getConstraints() { // @todo: Implement by making entities proper typed data. See @@ -472,7 +447,7 @@ public function getConstraints() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::validate(). + * {@inheritdoc} */ public function validate() { // @todo: Implement by making entities proper typed data. See diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php index e51f121..44b4b3e 100644 --- a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php +++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php @@ -431,13 +431,6 @@ public function getTranslation($langcode, $strict = TRUE) { /** * Forwards the call to the decorated entity. */ - public function getType() { - return $this->decorated->getType(); - } - - /** - * Forwards the call to the decorated entity. - */ public function getDefinition() { return $this->decorated->getDefinition(); } diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php index 595064e..6f4c9dd 100644 --- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php @@ -21,7 +21,7 @@ * When implementing this interface which extends Traversable, make sure to list * IteratorAggregate or Iterator before this interface in the implements clause. */ -interface ComplexDataInterface extends Traversable, TypedDataInterface { +interface ComplexDataInterface extends Traversable, TypedDataInterface, ContextAwareInterface { /** * Gets a property object. diff --git a/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php b/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php new file mode 100644 index 0000000..2ca7aa8 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/ContextAwareInterface.php @@ -0,0 +1,72 @@ +value = $value; } + + /** + * {@inheritdoc} + */ + public function getString() { + return (string) $this->getValue(); + } } diff --git a/core/lib/Drupal/Core/TypedData/PrimitiveInterface.php b/core/lib/Drupal/Core/TypedData/PrimitiveInterface.php index b2293e2..35f16bd 100644 --- a/core/lib/Drupal/Core/TypedData/PrimitiveInterface.php +++ b/core/lib/Drupal/Core/TypedData/PrimitiveInterface.php @@ -10,7 +10,7 @@ /** * Interface for primitive data. */ -interface PrimitiveInterface { +interface PrimitiveInterface extends StringableInterface { /** * Gets the primitive data value. diff --git a/core/lib/Drupal/Core/TypedData/StringableInterface.php b/core/lib/Drupal/Core/TypedData/StringableInterface.php new file mode 100644 index 0000000..06b9064 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/StringableInterface.php @@ -0,0 +1,22 @@ +definition['type']; - } - - /** * {@inheritdoc} */ public function getPluginId() { @@ -87,32 +80,7 @@ public function getDefinition() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getValue(). - */ - public function getValue() { - return $this->value; - } - - /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue(). - */ - public function setValue($value, $notify = TRUE) { - // Notify the parent of any changes to be made. - if ($notify && isset($this->parent)) { - $this->parent->onChange($this->name); - } - $this->value = $value; - } - - /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getString(). - */ - public function getString() { - return (string) $this->getValue(); - } - - /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getConstraints(). + * {@inheritdoc} */ public function getConstraints() { // @todo: Add the typed data manager as proper dependency. @@ -120,7 +88,7 @@ public function getConstraints() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::validate(). + * {@inheritdoc} */ public function validate() { // @todo: Add the typed data manager as proper dependency. @@ -137,7 +105,7 @@ public function applyDefaultValue($notify = TRUE) { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::setContext(). + * {@inheritdoc} */ public function setContext($name = NULL, TypedDataInterface $parent = NULL) { $this->parent = $parent; @@ -145,14 +113,14 @@ public function setContext($name = NULL, TypedDataInterface $parent = NULL) { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getName(). + * {@inheritdoc} */ public function getName() { return $this->name; } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getRoot(). + * {@inheritdoc} */ public function getRoot() { if (isset($this->parent)) { @@ -163,7 +131,7 @@ public function getRoot() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getPropertyPath(). + * {@inheritdoc} */ public function getPropertyPath() { if (isset($this->parent)) { @@ -181,9 +149,7 @@ public function getPropertyPath() { } /** - * Implements \Drupal\Core\TypedData\TypedDataInterface::getParent(). - * - * @return \Drupal\Core\Entity\Field\FieldInterface + * {@inheritdoc} */ public function getParent() { return $this->parent; diff --git a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php index 96229b6..3f7feaa 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php @@ -7,22 +7,12 @@ namespace Drupal\Core\TypedData; -use Drupal\user; - /** * Interface for typed data objects. */ interface TypedDataInterface { /** - * Gets the data type. - * - * @return string - * The data type of the wrapped data. - */ - public function getType(); - - /** * Gets the data definition. * * @return array @@ -31,54 +21,6 @@ public function getType(); public function getDefinition(); /** - * Gets the data value. - * - * @return mixed - */ - public function getValue(); - - /** - * Sets the data value. - * - * @param mixed|null $value - * The value to set in the format as documented for the data type or NULL to - * unset the data value. - * @param bool $notify - * (optional) Whether to notify the parent object of the change. Defaults to - * TRUE. If a property is updated from a parent object, set it to FALSE to - * avoid being notified again. - * - * @throws \Drupal\Core\TypedData\ReadOnlyException - * If the data is read-only. - */ - public function setValue($value, $notify = TRUE); - - /** - * Returns a string representation of the data. - * - * @return string - */ - public function getString(); - - /** - * Gets a list of validation constraints. - * - * @return array - * Array of constraints, each being an instance of - * \Symfony\Component\Validator\Constraint. - */ - public function getConstraints(); - - /** - * Validates the currently set data value. - * - * @return \Symfony\Component\Validator\ConstraintViolationListInterface - * A list of constraint violations. If the list is empty, validation - * succeeded. - */ - public function validate(); - - /** * Applies the default value. * * @param bool $notify @@ -90,60 +32,4 @@ public function validate(); * Returns itself to allow for chaining. */ public function applyDefaultValue($notify = TRUE); - - /** - * Returns the name of a property or item. - * - * @return string - * If the data is a property of some complex data, the name of the property. - * If the data is an item of a list, the name is the numeric position of the - * item in the list, starting with 0. Otherwise, NULL is returned. - */ - public function getName(); - - /** - * Returns the parent data structure; i.e. either complex data or a list. - * - * @return \Drupal\Core\TypedData\ComplexDataInterface|\Drupal\Core\TypedData\ListInterface - * The parent data structure, either complex data or a list; or NULL if this - * is the root of the typed data tree. - */ - public function getParent(); - - /** - * Returns the root of the typed data tree. - * - * Returns the root data for a tree of typed data objects; e.g. for an entity - * field item the root of the tree is its parent entity object. - * - * @return \Drupal\Core\TypedData\ComplexDataInterface|\Drupal\Core\TypedData\ListInterface - * The root data structure, either complex data or a list. - */ - public function getRoot(); - - /** - * Returns the property path of the data. - * - * The trail of property names relative to the root of the typed data tree, - * separated by dots; e.g. 'field_text.0.format'. - * - * @return string - * The property path relative to the root of the typed tree, or an empty - * string if this is the root. - */ - public function getPropertyPath(); - - /** - * Sets the context of a property or item via a context aware parent. - * - * This method is supposed to be called by the factory only. - * - * @param string $name - * (optional) The name of the property or the delta of the list item, - * or NULL if it is the root of a typed data tree. Defaults to NULL. - * @param \Drupal\Core\TypedData\TypedDataInterface $parent - * (optional) The parent object of the data property, or NULL if it is the - * root of a typed data tree. Defaults to NULL. - */ - public function setContext($name = NULL, TypedDataInterface $parent = NULL); } diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index f0e8034..7721b69 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -14,6 +14,7 @@ use Drupal\Core\Plugin\DefaultPluginManager; use InvalidArgumentException; use Drupal\Core\TypedData\Validation\MetadataFactory; +use Drupal\Core\TypedData\ContextAwareInterface; use Drupal\Core\Validation\ConstraintManager; use Drupal\Core\Validation\DrupalTranslator; use Symfony\Component\Validator\ValidatorInterface; @@ -198,7 +199,7 @@ public function getInstance(array $options) { * 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 + * @param \Drupal\Core\TypedData\ContextAwareInterface $object * The parent typed data object, implementing the TypedDataInterface and * either the ListInterface or the ComplexDataInterface. * @param string $property_name @@ -219,9 +220,11 @@ public function getInstance(array $options) { * @todo: Add type-hinting to $object once entities implement the * TypedDataInterface. */ - public function getPropertyInstance($object, $property_name, $value = NULL) { + public function getPropertyInstance(ContextAwareInterface $object, $property_name, $value = NULL) { if ($root = $object->getRoot()) { - $key = $root->getType() . ':' . $object->getPropertyPath() . '.'; + // @todo: Remove conditional check when #1868004 lands. + $id = $root instanceof \Drupal\Core\Entity\EntityInterface ? 'entity' : $root->getPluginId(); + $key = $id . ':' . $object->getPropertyPath() . '.'; // If we are creating list items, we always use 0 in the key as all list // items look the same. $key .= is_numeric($property_name) ? 0 : $property_name; diff --git a/core/lib/Drupal/Core/TypedData/ValidatableInterface.php b/core/lib/Drupal/Core/TypedData/ValidatableInterface.php new file mode 100644 index 0000000..ac0af19 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/ValidatableInterface.php @@ -0,0 +1,33 @@ +getDefinition(); $this->assertTrue(!empty($definition['type']), format_string('!type data definition was returned.', array('!type' => $definition['type']))); // Assert that the correct type was constructed. - $this->assertEqual($data->getType(), $type, format_string('!type object returned type.', array('!type' => $definition['type']))); + $this->assertEqual($data->getPluginId(), $type, format_string('!type object returned type.', array('!type' => $definition['type']))); return $data; } @@ -413,7 +413,7 @@ public function testTypedDataMaps() { // Test iterating. $count = 0; foreach ($typed_data as $item) { - $this->assertTrue($item instanceof \Drupal\Core\TypedData\TypedDataInterface); + $this->assertTrue($item instanceof \Drupal\Core\TypedData\Plugin\DataType\Any); $count++; } $this->assertEqual($count, 3); @@ -505,6 +505,9 @@ public function testTypedDataValidation() { 'Range' => array('min' => 5), ), ); + $integer = $this->typedData->create($definition, 7); + $this->assertTrue($integer instanceof \Drupal\Core\TypedData\ValidatableInterface); + $violations = $this->typedData->create($definition, 10)->validate(); $this->assertEqual($violations->count(), 0); @@ -614,4 +617,46 @@ public function testTypedDataValidation() { $this->assertEqual($violations[0]->getInvalidValue(), 'string'); $this->assertIdentical($violations[0]->getPropertyPath(), '0.value'); } + + /** + * Tests typed data contexts. + */ + function testTypedDataContext() { + // Test working with a simple map. + $value = array( + 'one' => 'ett', + 'two' => 'två', + 'three' => 'tre', + ); + $typed_data = $this->createTypedData(array( + 'type' => 'map', + ), $value); + + $this->assertTrue($typed_data instanceof \Drupal\Core\TypedData\ContextAwareInterface); + + $item = $typed_data->get('one'); + $this->assertEqual($item->getName(), 'one'); + $this->assertEqual($item->getPropertyPath(), 'one'); + $this->assertTrue($item->getParent() instanceof \Drupal\Core\TypedData\Plugin\DataType\Map); + $this->assertTrue($item->getRoot() instanceof \Drupal\Core\TypedData\Plugin\DataType\Map); + } + + /** + * Tests the typed data manager. + */ + function testTypedDataManager() { + // Test working with a simple map. + $value = array( + 'one' => 'första', + 'two' => 'andra', + 'three' => 'tredje', + ); + $typed_data = $this->createTypedData(array( + 'type' => 'map', + ), $value); + + $item = $this->typedData->getPropertyInstance($typed_data, 'two', 'prototyped value'); + $this->assertTrue($item instanceof \Drupal\Core\TypedData\Plugin\DataType\Any); + $this->assertEqual($item->getValue(), 'prototyped value'); + } }