commit c7beb2344753de06e47afb76fa053640325d1204 Author: fago Date: Mon Dec 30 14:28:41 2013 +0100 Added definition factory. diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index b0b905d..4f12e9b 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -45,6 +45,14 @@ protected $routeProvider; /** + * {@inheritdoc} + */ + public static function createDataDefinition($data_type) { + // @todo: Implement a proper data definition class for entities. + return DataDefinition::create($data_type); + } + + /** * Constructs an Entity object. * * @param array $values diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php index 37ffa55..cec6d6e 100644 --- a/core/lib/Drupal/Core/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Field/FieldItemBase.php @@ -26,6 +26,16 @@ /** * {@inheritdoc} */ + public static function createDataDefinition($data_type) { + // The data type of a field item is in the form of "field_item:$field_type". + $parts = explode(':', $data_type, 2); + $field_definition = FieldDefinition::create($parts[1]); + return $field_definition->getItemDefinition(); + } + + /** + * {@inheritdoc} + */ public static function getMainPropertyName() { return 'value'; } diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php index 1af3254..17c1664 100644 --- a/core/lib/Drupal/Core/Field/FieldItemList.php +++ b/core/lib/Drupal/Core/Field/FieldItemList.php @@ -41,6 +41,15 @@ class FieldItemList extends ItemList implements FieldItemListInterface { /** * {@inheritdoc} */ + public static function createDataDefinition($data_type) { + // The data type of a field item is in the form of "field_item:$field_type". + $parts = explode(':', $data_type, 2); + return FieldDefinition::create($parts[1]); + } + + /** + * {@inheritdoc} + */ public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); // Always initialize one empty item as most times a value for at least one diff --git a/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php b/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php index e026fe8..d5eaf14 100644 --- a/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php +++ b/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php @@ -14,7 +14,13 @@ * For example, a plugin could describe its parameters using data definitions * in order to specify what kind of data is required for it. * + * Definitions that describe lists or complex data have to implement the + * respective interfaces, such that the metadata about contained list items or + * properties can be retrieved from the definition. + * * @see \Drupal\Core\TypedData\DataDefinition + * @see \Drupal\Core\TypedData\ListDefinitionInterface + * @see \Drupal\Core\TypedData\ComplexDataDefinitionInterface */ interface DataDefinitionInterface { diff --git a/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php b/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php index c07d60e..613c1f8 100644 --- a/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php +++ b/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php @@ -12,6 +12,8 @@ * * This interface is present on a data definition if it describes a list. The * actual lists implement the \Drupal\Core\TypedData\ListInterface. + * + * @see \Drupal\Core\TypedData\ListDefinition */ interface ListDefinitionInterface extends DataDefinitionInterface { diff --git a/core/lib/Drupal/Core/TypedData/ListInterface.php b/core/lib/Drupal/Core/TypedData/ListInterface.php index 53f5eac..d60eb64 100644 --- a/core/lib/Drupal/Core/TypedData/ListInterface.php +++ b/core/lib/Drupal/Core/TypedData/ListInterface.php @@ -19,6 +19,17 @@ interface ListInterface extends TypedDataInterface, \ArrayAccess, \Countable, \Traversable { /** + * Creates a new list definition. + * + * @param string $data_type + * The data type of the list items. + * + * @return \Drupal\Core\TypedData\ListDefinitionInterface + * A list definition for the given data type. + */ + public static function createDataDefinition($data_type); + + /** * Determines whether the list contains any non-empty items. * * @return boolean diff --git a/core/lib/Drupal/Core/TypedData/MapDefinition.php b/core/lib/Drupal/Core/TypedData/MapDefinition.php index f3f968b..d848211 100644 --- a/core/lib/Drupal/Core/TypedData/MapDefinition.php +++ b/core/lib/Drupal/Core/TypedData/MapDefinition.php @@ -20,6 +20,20 @@ class MapDefinition extends ComplexDataDefinitionBase { protected $mainPropertyName = NULL; /** + * Creates a new map definition. + * + * @param string $type + * (optional) The data type of the map. Defaults to 'map'. + * + * @return static + * A new MapDefinition object. + */ + public static function create($type = 'map') { + $definition['type'] = $type; + return new static($definition); + } + + /** * {@inheritdoc} */ public function getPropertyDefinitions() { diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php index 2e906d0..91865dd 100644 --- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php @@ -8,6 +8,7 @@ namespace Drupal\Core\TypedData\Plugin\DataType; use Drupal\Core\TypedData\ComplexDataInterface; +use Drupal\Core\TypedData\ListDefinition; use Drupal\Core\TypedData\ListInterface; use Drupal\Core\TypedData\TypedData; use Drupal\Core\TypedData\TypedDataInterface; @@ -35,6 +36,13 @@ class ItemList extends TypedData implements \IteratorAggregate, ListInterface { protected $list = array(); /** + * {@inheritdoc} + */ + public static function createDataDefinition($data_type) { + return ListDefinition::create($data_type); + } + + /** * Overrides \Drupal\Core\TypedData\TypedData::getValue(). */ public function getValue() { diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php index ef5c370..d08f237 100644 --- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php @@ -7,6 +7,7 @@ namespace Drupal\Core\TypedData\Plugin\DataType; +use Drupal\Core\TypedData\MapDefinition; use Drupal\Core\TypedData\TypedData; use Drupal\Core\TypedData\ComplexDataInterface; @@ -51,6 +52,13 @@ class Map extends TypedData implements \IteratorAggregate, ComplexDataInterface /** * {@inheritdoc} */ + public static function createDataDefinition($data_type) { + return MapDefinition::create($data_type); + } + + /** + * {@inheritdoc} + */ public function getPropertyDefinitions() { return $this->definition->getPropertyDefinitions(); } diff --git a/core/lib/Drupal/Core/TypedData/TypedData.php b/core/lib/Drupal/Core/TypedData/TypedData.php index 1597c93..2dda8d2 100644 --- a/core/lib/Drupal/Core/TypedData/TypedData.php +++ b/core/lib/Drupal/Core/TypedData/TypedData.php @@ -39,6 +39,13 @@ protected $parent; /** + * {@inheritdoc} + */ + public static function createDataDefinition($data_type) { + return DataDefinition::create($data_type); + } + + /** * Constructs a TypedData object given its definition and context. * * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition diff --git a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php index 4d7b066..bcd7be9 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php @@ -15,6 +15,17 @@ interface TypedDataInterface { /** + * Creates a new data definition object. + * + * @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. + */ + public static function createDataDefinition($data_type); + + /** * Gets the data definition. * * @return \Drupal\Core\TypedData\DataDefinitionInterface diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index e060cd3..3bd17c7 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -133,6 +133,33 @@ public function create(DataDefinitionInterface $definition, $value = NULL, $name } /** + * Creates a new data definition object. + * + * @param string $data_type + * The data type, for which a data definition should be created. + * @param bool $list + * (optional) Whether to define a single item of the given type (FALSE), or + * a list of items (TRUE). Defaults to FALSE. + * + * @return \Drupal\Core\TypedData\DataDefinitionInterface|\Drupal\Core\TypedData\ListDefinitionInterface + * A data or list definition for the given data type. + */ + public function createDataDefinition($data_type, $list = FALSE) { + $type_definition = $this->getDefinition($data_type); + if (!isset($type_definition)) { + throw new \InvalidArgumentException(format_string('Invalid data type %plugin_id has been given.', array('%plugin_id' => $data_type))); + } + // A single 'list' item is the same as a list of 'any' items. Always handle + // it as the latter, such that the "list" class can always act as a list. + if ($data_type == 'list' && !$list) { + $data_type = 'any'; + $list = TRUE; + } + $class = $list ? $type_definition['list_class'] : $type_definition['class']; + return $class::createDataDefinition($data_type); + } + + /** * Implements \Drupal\Component\Plugin\PluginManagerInterface::getInstance(). * * @param array $options diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php index 0ccda3a..22d81bb 100644 --- a/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php @@ -52,20 +52,25 @@ public function setUp() { /** * Tests deriving metadata about list items. */ - public function testListMetadata() { - // @todo: Add a definition factory to the typed data manager. + public function testLists() { $list = ListDefinition::create('string'); $this->assertTrue($list instanceof ListDefinitionInterface); $item = $list->getItemDefinition(); $this->assertTrue($item instanceof DataDefinitionInterface); $this->assertEqual($item->getDataType(), 'string'); + + // Test using the definition factory. + $list2 = $this->typedDataManager->createDataDefinition('list'); + $this->assertTrue($list2 instanceof ListDefinitionInterface); + $list2->getItemDefinition()->setDataType('string'); + $this->assertEqual($list, $list2); } /** * Tests deriving metadata about maps. */ - public function testTypedDataMaps() { - $map = MapDefinition::create('map') + public function testMaps() { + $map = MapDefinition::create() ->setPropertyDefinition('one', DataDefinition::create('string')) ->setPropertyDefinition('two', DataDefinition::create('string')) ->setPropertyDefinition('three', DataDefinition::create('string')); @@ -77,6 +82,14 @@ public function testTypedDataMaps() { $this->assertEqual($map->getPropertyDefinition('one')->getDataType(), 'string'); $this->assertNull($map->getMainPropertyName()); $this->assertNull($map->getPropertyDefinition('invalid')); + + // Test using the definition factory. + $map2 = $this->typedDataManager->createDataDefinition('map'); + $this->assertTrue($map2 instanceof ComplexDataDefinitionInterface); + $map2->setPropertyDefinition('one', DataDefinition::create('string')) + ->setPropertyDefinition('two', DataDefinition::create('string')) + ->setPropertyDefinition('three', DataDefinition::create('string')); + $this->assertEqual($map, $map2); } /** @@ -104,6 +117,19 @@ public function testFields() { $this->assertEqual($field->getPropertyDefinition('value')->getDataType(), 'integer'); $this->assertEqual($field->getMainPropertyName(), 'value'); $this->assertNull($field->getPropertyDefinition('invalid')); + + // Test using the definition factory for field item lists and field items. + $field_item2 = $this->typedDataManager->createDataDefinition('field_item:integer'); + $this->assertFalse($field_item2 instanceof ListDefinitionInterface); + $this->assertTrue($field_item2 instanceof ComplexDataDefinitionInterface); + // Comparison should ignore the internal static cache, so compare the + // serialized objects instead. + $this->assertEqual(serialize($field_item), serialize($field_item2)); + + $field2 = $this->typedDataManager->createDataDefinition('field_item:integer', TRUE); + $this->assertTrue($field2 instanceof ListDefinitionInterface); + $this->assertFalse($field2 instanceof ComplexDataDefinitionInterface); + $this->assertEqual(serialize($field), serialize($field2)); } /**