diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index 7c68f0a..709ba90 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -601,7 +601,7 @@ public function onChange($name) { /** * {@inheritdoc} * - * @return \Drupal\Core\Entity\EntityInterface + * @return \Drupal\Core\Entity\ContentEntityInterface */ public function getTranslation($langcode) { // Ensure we always use the default language code when dealing with the diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 178fe51..2dffe2a 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/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php index 882d086..51b6338 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Field/FieldDefinition.php @@ -8,7 +8,6 @@ namespace Drupal\Core\Field; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\ListDefinition; /** @@ -17,6 +16,22 @@ class FieldDefinition extends ListDefinition implements FieldDefinitionInterface { /** + * The field type. + * + * @var string + */ + protected $type; + + /** + * An array of field property definitions. + * + * @var \Drupal\Core\TypedData\DataDefinitionInterface[] + * + * @see \Drupal\Core\TypedData\ComplexDataDefinitionInterface::getPropertyDefinitions() + */ + protected $propertyDefinitions; + + /** * Creates a new field definition. * * @param string $type @@ -26,7 +41,10 @@ class FieldDefinition extends ListDefinition implements FieldDefinitionInterface * A new field definition object. */ public static function create($type) { - return new static(array(), DataDefinition::create('field_item:' . $type)); + $field_definition = new static(array()); + $field_definition->type = $type; + $field_definition->itemDefinition = FieldItemDefinition::create($field_definition); + return $field_definition; } /** @@ -54,10 +72,7 @@ public function setName($name) { * {@inheritdoc} */ public function getType() { - $data_type = $this->getItemDefinition()->getDataType(); - // Cut of the leading field_item: prefix from 'field_item:FIELD_TYPE'. - $parts = explode(':', $data_type); - return $parts[1]; + return $this->type; } /** @@ -107,13 +122,6 @@ public function setSetting($setting_name, $value) { /** * {@inheritdoc} */ - public function getPropertyNames() { - return array_keys(\Drupal::typedDataManager()->create($this->getItemDefinition())->getPropertyDefinitions()); - } - - /** - * {@inheritdoc} - */ public function isTranslatable() { return !empty($this->definition['translatable']); } @@ -201,4 +209,69 @@ public function getDefaultValue(EntityInterface $entity) { return $this->getSetting('default_value'); } + /** + * {@inheritdoc} + */ + public function getPropertyDefinition($name) { + if (!isset($this->propertyDefinitions)) { + $this->getPropertyDefinitions(); + } + if (isset($this->propertyDefinitions[$name])) { + return $this->propertyDefinitions[$name]; + } + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions() { + if (!isset($this->propertyDefinitions)) { + $class = $this->getFieldItemClass(); + $this->propertyDefinitions = $class::propertyDefinitions($this); + } + return $this->propertyDefinitions; + } + + /** + * {@inheritdoc} + */ + public function getPropertyNames() { + return array_keys($this->getPropertyDefinitions()); + } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + $class = $this->getFieldItemClass(); + return $class::getMainPropertyName(); + } + + /** + * Helper to retrieve the field item class. + * + * @todo: Remove once getClass() adds in defaults. See + * https://drupal.org/node/2116341. + */ + protected function getFieldItemClass() { + if ($class = $this->itemDefinition->getClass()) { + return $class; + } + else { + $type_definition = \Drupal::typedDataManager() + ->getDefinition($this->itemDefinition->getDataType()); + return $type_definition['class']; + } + } + + /** + * {@inheritdoc} + */ + public function __sleep() { + // Do not serialize the statically cached property definitions. + $vars = get_object_vars($this); + unset($vars['propertyDefinitions']); + return array_keys($vars); + } + } diff --git a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php index 76f0ef9..4e95165 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php @@ -209,4 +209,36 @@ public function isMultiple(); */ public function getDefaultValue(EntityInterface $entity); + /** + * Gets the definition of a contained property. + * + * @param string $name + * The name of property. + * + * @return \Drupal\Core\TypedData\DataDefinitionInterface|null + * The definition of the property or NULL if the property does not exist. + */ + public function getPropertyDefinition($name); + + /** + * Gets an array of property definitions of contained properties. + * + * @return \Drupal\Core\TypedData\DataDefinitionInterface[] + * An array of property definitions of contained properties, keyed by + * property name. + */ + public function getPropertyDefinitions(); + + /** + * Returns the name of the main property, if any. + * + * Some field items consist mainly of one main property, e.g. the value of a + * text field or the @code target_id @endcode of an entity reference. If the + * field item has no main property, the method returns NULL. + * + * @return string|null + * The name of the value property, or NULL if there is none. + */ + public function getMainPropertyName(); + } diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php index b5b0f3f..cec6d6e 100644 --- a/core/lib/Drupal/Core/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Field/FieldItemBase.php @@ -26,6 +26,23 @@ /** * {@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'; + } + + /** + * {@inheritdoc} + */ public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); // Initialize computed properties by default, such that they get cloned @@ -211,11 +228,4 @@ public function delete() { } */ public function deleteRevision() { } - /** - * {@inheritdoc} - */ - public function getMainPropertyName() { - return 'value'; - } - } diff --git a/core/lib/Drupal/Core/Field/FieldItemDefinition.php b/core/lib/Drupal/Core/Field/FieldItemDefinition.php new file mode 100644 index 0000000..28a2337 --- /dev/null +++ b/core/lib/Drupal/Core/Field/FieldItemDefinition.php @@ -0,0 +1,62 @@ +getType(); + $item_definition = new static($definition); + $item_definition->fieldDefinition = $field_definition; + return $item_definition; + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinition($name) { + return $this->fieldDefinition->getPropertyDefinition($name); + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions() { + return $this->fieldDefinition->getPropertyDefinitions(); + } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + return $this->fieldDefinition->getMainPropertyName(); + } + +} diff --git a/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php index 2cdd0c3..ee5c06a 100644 --- a/core/lib/Drupal/Core/Field/FieldItemInterface.php +++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php @@ -24,6 +24,31 @@ interface FieldItemInterface extends ComplexDataInterface { /** + * Defines field item properties. + * + * @return \Drupal\Core\TypedData\DataDefinitionInterface[] + * An array of property definitions of contained properties, keyed by + * property name. + * + * @see \Drupal\Core\Field\FieldDefinition + */ + public static function propertyDefinitions(FieldDefinitionInterface $field_definition); + + /** + * Returns the name of the main property, if any. + * + * Some field items consist mainly of one main property, e.g. the value of a + * text field or the @code target_id @endcode of an entity reference. If the + * field item has no main property, the method returns NULL. + * + * @return string|null + * The name of the value property, or NULL if there is none. + * + * @see \Drupal\Core\Field\FieldDefinition + */ + public static function getMainPropertyName(); + + /** * Gets the entity that field belongs to. * * @return \Drupal\Core\Entity\EntityInterface @@ -136,20 +161,4 @@ public function delete(); */ public function deleteRevision(); - /** - * Returns the name of the main property, if any. - * - * Some field items consist mainly of one main property, e.g. the value of a - * text field or the @code target_id @endcode of an entity reference. If the - * field item has no main property, the method returns NULL. - * - * @return string|null - * The name of the value property, or NULL if there is none. - * - * @todo: Move this to ComplexDataInterface once we improved Typed data to do - * not enforce having all methods on the data objects. - * https://drupal.org/node/2002134 - */ - public function getMainPropertyName(); - } 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/Field/Plugin/Field/FieldType/BooleanItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php index 994957c..5a83b98 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,23 +24,13 @@ class BooleanItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see BooleanItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('boolean') + ->setLabel(t('Boolean value')); - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('boolean') - ->setLabel(t('Boolean value')); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php index 59984c8..0652582 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; /** @@ -22,25 +23,14 @@ class DateItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see DateItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = array( + 'type' => 'date', + 'label' => t('Date value'), + ); - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = array( - 'type' => 'date', - 'label' => t('Date value'), - ); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php index 5a2c107..09aea19 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,24 +24,13 @@ class EmailItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see EmailItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** - * Implements ComplexDataInterface::getPropertyDefinitions(). + * {@inheritdoc} */ - public function getPropertyDefinitions() { + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('email') + ->setLabel(t('E-mail value')); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('email') - ->setLabel(t('E-mail value')); - } - return static::$propertyDefinitions; + return $properties; } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php index 40f7a3a..f3b1cd6 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -30,56 +31,49 @@ class EntityReferenceItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see EntityReferenceItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). + * {@inheritdoc} */ - public function getPropertyDefinitions() { - $settings = $this->definition->getSettings(); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $settings = $field_definition->getSettings(); $target_type = $settings['target_type']; - // Definitions vary by entity type and bundle, so key them accordingly. - $key = $target_type . ':'; - $key .= isset($settings['target_bundle']) ? $settings['target_bundle'] : ''; - - if (!isset(static::$propertyDefinitions[$key])) { - $target_type_info = \Drupal::entityManager()->getDefinition($target_type); - if ($target_type_info->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) { - // @todo: Lookup the entity type's ID data type and use it here. - // https://drupal.org/node/2107249 - static::$propertyDefinitions[$key]['target_id'] = DataDefinition::create('integer') - ->setLabel(t('Entity ID')) - ->setConstraints(array( - 'Range' => array('min' => 0), - )); - } - else { - static::$propertyDefinitions[$key]['target_id'] = DataDefinition::create('string') - ->setLabel(t('Entity ID')); - } - - static::$propertyDefinitions[$key]['entity'] = DataDefinition::create('entity_reference') - ->setLabel(t('Entity')) - ->setDescription(t('The referenced entity')) - // The entity object is computed out of the entity ID. - ->setComputed(TRUE) - ->setReadOnly(FALSE) + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + if ($target_type_info->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) { + // @todo: Lookup the entity type's ID data type and use it here. + // https://drupal.org/node/2107249 + $properties['target_id'] = DataDefinition::create('integer') + ->setLabel(t('Entity ID')) ->setConstraints(array( - 'EntityType' => $settings['target_type'], + 'Range' => array('min' => 0), )); + } + else { + $properties['target_id'] = DataDefinition::create('string') + ->setLabel(t('Entity ID')); + } - if (isset($settings['target_bundle'])) { - static::$propertyDefinitions[$key]['entity']->addConstraint('Bundle', $settings['target_bundle']); - } + $properties['entity'] = DataDefinition::create('entity_reference') + ->setLabel(t('Entity')) + ->setDescription(t('The referenced entity')) + // The entity object is computed out of the entity ID. + ->setComputed(TRUE) + ->setReadOnly(FALSE) + ->setConstraints(array( + 'EntityType' => $settings['target_type'], + )); + + if (isset($settings['target_bundle'])) { + $properties['entity']->addConstraint('Bundle', $settings['target_bundle']); } - return static::$propertyDefinitions[$key]; + + return $properties; + } + + /** + * {@inheritdoc} + */ + public static function getMainPropertyName() { + return 'target_id'; } /** @@ -142,11 +136,4 @@ public function onChange($property_name) { parent::onChange($property_name); } - /** - * {@inheritdoc} - */ - public function getMainPropertyName() { - return 'target_id'; - } - } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php index e489a2f..421acc5 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,23 +24,12 @@ class FloatItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see IntegerItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('float') + ->setLabel(t('Float value')); - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('float') - ->setLabel(t('Float value')); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php index 82f088a..68b5d45 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,23 +24,12 @@ class IntegerItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see IntegerItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('integer') + ->setLabel(t('Integer value')); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('integer') - ->setLabel(t('Integer value')); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php index bd4d877..fee72c2 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Language\Language; use Drupal\Core\TypedData\DataDefinition; @@ -29,30 +30,20 @@ class LanguageItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see LanguageItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). + * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Language code')); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Language code')); - static::$propertyDefinitions['language'] = DataDefinition::create('language_reference') - ->setLabel(t('Language object')) - ->setDescription(t('The referenced language')) + $properties['language'] = DataDefinition::create('language_reference') + ->setLabel(t('Language object')) + ->setDescription(t('The referenced language')) // The language object is retrieved via the language code. - ->setComputed(TRUE) - ->setReadOnly(FALSE); - } - return static::$propertyDefinitions; + ->setComputed(TRUE) + ->setReadOnly(FALSE); + + return $properties; } /** diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php index 957b0e8..23f62bd 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php @@ -8,6 +8,8 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; use Drupal\Core\Field\FieldItemBase; +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\TypedData\DataDefinition; /** * Defines the 'map' entity field type. @@ -15,7 +17,7 @@ * @FieldType( * id = "map", * label = @Translation("Map"), - * description = @Translation("An entity field containing a map value."), + * description = @Translation("An entity field for storing a serialized array of values."), * configurable = FALSE * ) */ @@ -24,6 +26,34 @@ class MapItem extends FieldItemBase { /** * {@inheritdoc} */ + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + // There aren't any properties we can define statically. + return array(); + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions() { + // Come up with some run-time property definitions, such that property + // objects can be used for all map values. + $definitions = parent::getPropertyDefinitions(); + foreach ($this->values as $name => $value) { + $definitions[$name] = DataDefinition::create('any'); + } + return $definitions; + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinition($name) { + return array_key_exists($name, $this->values) ? DataDefinition::create('any') : FALSE; + } + + /** + * {@inheritdoc} + */ public function setValue($values, $notify = TRUE) { $this->values = array(); if (!isset($values)) { diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php index 9c63b33..7c653f7 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,23 +24,12 @@ class StringItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see StringItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Text value')); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Text value')); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php index c1be221..ebb8e2f 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,23 +24,13 @@ class UriItem extends FieldItemBase { /** - * Field definitions of the contained properties. - * - * @see self::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('uri') + ->setLabel(t('URI value')); - /** - * Implements ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - if (!isset(self::$propertyDefinitions)) { - self::$propertyDefinitions['value'] = DataDefinition::create('uri') - ->setLabel(t('URI value')); - } - return self::$propertyDefinitions; + return $properties; } } diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionBase.php b/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionBase.php new file mode 100644 index 0000000..9be93e2 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionBase.php @@ -0,0 +1,48 @@ +propertyDefinitions)) { + $this->getPropertyDefinitions(); + } + if (isset($this->propertyDefinitions[$name])) { + return $this->propertyDefinitions[$name]; + } + } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + return NULL; + } + + /** + * {@inheritdoc} + */ + abstract public function getPropertyDefinitions(); + +} diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionInterface.php new file mode 100644 index 0000000..dbdad24 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionInterface.php @@ -0,0 +1,47 @@ +getDefinition()->getPropertyDefinition() instead). + * See \Drupal\Core\TypedData\ComplexDataDefinitionInterface. */ public function getPropertyDefinition($name); @@ -108,6 +112,10 @@ public function getPropertyDefinition($name); * @return \Drupal\Core\TypedData\DataDefinitionInterface[] * An array of property definitions of contained properties, keyed by * property name. + * + * @deprecated + * Use $this->getDefinition()->getPropertyDefinitions() instead). + * See \Drupal\Core\TypedData\ComplexDataDefinitionInterface. */ public function getPropertyDefinitions(); 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/ListDefinition.php b/core/lib/Drupal/Core/TypedData/ListDefinition.php index 4963107..820603c 100644 --- a/core/lib/Drupal/Core/TypedData/ListDefinition.php +++ b/core/lib/Drupal/Core/TypedData/ListDefinition.php @@ -34,12 +34,10 @@ public static function create($item_type) { /** * {@inheritdoc} - * - * @param */ public function __construct(array $definition = array(), DataDefinitionInterface $item_definition = NULL) { - parent::__construct($definition); - $this->itemDefinition = isset($item_definition) ? $item_definition : DataDefinition::create('any'); + $this->definition = $definition; + $this->itemDefinition = $item_definition; } /** 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 new file mode 100644 index 0000000..d848211 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/MapDefinition.php @@ -0,0 +1,88 @@ +propertyDefinitions)) { + $this->propertyDefinitions = array(); + } + return $this->propertyDefinitions; + } + + /** + * Sets the definition of a map property. + * + * @param string $name + * The name of the property to define. + * @param \Drupal\Core\TypedData\DataDefinitionInterface|null $definition + * (optional) The property definition to set, or NULL to unset it. + * + * @return static + * The object itself for chaining. + */ + public function setPropertyDefinition($name, DataDefinitionInterface $definition = NULL) { + if (isset($definition)) { + $this->propertyDefinitions[$name] = $definition; + } + else { + unset($this->propertyDefinitions[$name]); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + return $this->mainPropertyName; + } + + /** + * Sets the main property name. + * + * @param string|null $name + * The name of the main property, or NULL if there is none. + * + * @return static + * The object itself for chaining. + */ + public function setMainPropertyName($name) { + $this->mainPropertyName = $name; + return $this; + } + +} 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 ab66442..d08f237 100644 --- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php @@ -7,7 +7,7 @@ namespace Drupal\Core\TypedData\Plugin\DataType; -use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\TypedData\MapDefinition; use Drupal\Core\TypedData\TypedData; use Drupal\Core\TypedData\ComplexDataInterface; @@ -29,6 +29,13 @@ class Map extends TypedData implements \IteratorAggregate, ComplexDataInterface { /** + * The data definition. + * + * @var \Drupal\Core\TypedData\ComplexDataDefinitionInterface + */ + protected $definition; + + /** * An array of values for the contained properties. * * @var array @@ -36,21 +43,31 @@ class Map extends TypedData implements \IteratorAggregate, ComplexDataInterface protected $values = array(); /** - * The array of properties, each implementing the TypedDataInterface. + * The array of properties. * - * @var array + * @var \Drupal\Core\TypedData\TypedDataInterface[] */ protected $properties = array(); /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). + * {@inheritdoc} + */ + public static function createDataDefinition($data_type) { + return MapDefinition::create($data_type); + } + + /** + * {@inheritdoc} */ public function getPropertyDefinitions() { - $definitions = array(); - foreach ($this->values as $name => $value) { - $definitions[$name] = DataDefinition::create('any'); - } - return $definitions; + return $this->definition->getPropertyDefinitions(); + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinition($name) { + return $this->definition->getPropertyDefinition($name); } /** @@ -128,7 +145,7 @@ public function get($property_name) { * Implements \Drupal\Core\TypedData\ComplexDataInterface::set(). */ public function set($property_name, $value, $notify = TRUE) { - if ($this->getPropertyDefinition($property_name)) { + if ($this->definition->getPropertyDefinition($property_name)) { $this->get($property_name)->setValue($value, $notify); } else { @@ -182,19 +199,6 @@ public function getIterator() { } /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinition(). - */ - public function getPropertyDefinition($name) { - $definitions = $this->getPropertyDefinitions(); - if (isset($definitions[$name])) { - return $definitions[$name]; - } - else { - return FALSE; - } - } - - /** * Implements \Drupal\Core\TypedData\ComplexDataInterface::isEmpty(). */ public function isEmpty() { 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/comment/comment.module b/core/modules/comment/comment.module index ec6a2cc..1434fea 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -883,7 +883,7 @@ function comment_translation_configuration_element_submit($form, &$form_state) { /** * Implements hook_entity_load(). * - * @see \Drupal\comment\Plugin\Field\FieldType\CommentItem::getPropertyDefinitions() + * @see \Drupal\comment\Plugin\Field\FieldType\CommentItem::propertyDefinitions() */ function comment_entity_load($entities, $entity_type) { if (!\Drupal::service('comment.manager')->getFields($entity_type)) { diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldName.php b/core/modules/comment/lib/Drupal/comment/CommentFieldName.php index 7912fcc..75d4498 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFieldName.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFieldName.php @@ -7,6 +7,7 @@ namespace Drupal\comment; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\StringItem; use Drupal\Core\TypedData\DataDefinition; @@ -16,26 +17,15 @@ class CommentFieldName extends StringItem { /** - * Definitions of the contained properties. - * - * @see self::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('String value')) + ->setClass('\Drupal\comment\CommentFieldNameValue') + ->setComputed(TRUE); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('String value')) - ->setClass('\Drupal\comment\CommentFieldNameValue') - ->setComputed(TRUE); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php index a68f8db..df787ad 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php @@ -7,6 +7,7 @@ namespace Drupal\comment\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; use Drupal\Core\Field\ConfigFieldItemBase; @@ -33,39 +34,31 @@ class CommentItem extends ConfigFieldItemBase { /** - * Definitions of the contained properties. - * - * @var array - */ - public static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['status'] = DataDefinition::create('integer') - ->setLabel(t('Comment status value')); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['status'] = DataDefinition::create('integer') + ->setLabel(t('Comment status value')); - static::$propertyDefinitions['cid'] = DataDefinition::create('integer') - ->setLabel(t('Last comment ID')); + $properties['cid'] = DataDefinition::create('integer') + ->setLabel(t('Last comment ID')); - static::$propertyDefinitions['last_comment_timestamp'] = DataDefinition::create('integer') - ->setLabel(t('Last comment timestamp')) - ->setDescription(t('The time that the last comment was created.')); + $properties['last_comment_timestamp'] = DataDefinition::create('integer') + ->setLabel(t('Last comment timestamp')) + ->setDescription(t('The time that the last comment was created.')); - static::$propertyDefinitions['last_comment_name'] = DataDefinition::create('string') - ->setLabel(t('Last comment name')) - ->setDescription(t('The name of the user posting the last comment.')); + $properties['last_comment_name'] = DataDefinition::create('string') + ->setLabel(t('Last comment name')) + ->setDescription(t('The name of the user posting the last comment.')); - static::$propertyDefinitions['last_comment_uid'] = DataDefinition::create('integer') - ->setLabel(t('Last comment user ID')); + $properties['last_comment_uid'] = DataDefinition::create('integer') + ->setLabel(t('Last comment user ID')); - static::$propertyDefinitions['comment_count'] = DataDefinition::create('integer') - ->setLabel(t('Number of comments')) - ->setDescription(t('The number of comments.')); - } - return static::$propertyDefinitions; + $properties['comment_count'] = DataDefinition::create('integer') + ->setLabel(t('Number of comments')) + ->setDescription(t('The number of comments.')); + + return $properties; } /** diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php index dc2c201..2d0a501 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php @@ -8,6 +8,7 @@ namespace Drupal\datetime\Plugin\Field\FieldType; use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\PrepareCacheInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -41,29 +42,20 @@ class DateTimeItem extends ConfigFieldItemBase implements PrepareCacheInterface const DATETIME_TYPE_DATETIME = 'datetime'; /** - * Field definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('datetime_iso8601') - ->setLabel(t('Date value')); - - static::$propertyDefinitions['date'] = DataDefinition::create('datetime_computed') - ->setLabel(t('Computed date')) - ->setDescription(t('The computed DateTime object.')) - ->setComputed(TRUE) - ->setClass('\Drupal\datetime\DateTimeComputed') - ->setSetting('date source', 'value'); - } - - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('datetime_iso8601') + ->setLabel(t('Date value')); + + $properties['date'] = DataDefinition::create('datetime_computed') + ->setLabel(t('Computed date')) + ->setDescription(t('The computed DateTime object.')) + ->setComputed(TRUE) + ->setClass('\Drupal\datetime\DateTimeComputed') + ->setSetting('date source', 'value'); + + return $properties; } /** diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php index 0f708c3..5af3028 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php @@ -7,6 +7,7 @@ namespace Drupal\entity_reference; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; use Drupal\Core\Field\ConfigEntityReferenceItemBase; @@ -27,40 +28,25 @@ class ConfigurableEntityReferenceItem extends ConfigEntityReferenceItemBase implements ConfigFieldItemInterface { /** - * Definitions of the contained properties. - * - * @see ConfigurableEntityReferenceItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - $settings = $this->definition->getSettings(); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $settings = $field_definition->getSettings(); $target_type = $settings['target_type']; - // Definitions vary by entity type and bundle, so key them accordingly. - $key = $target_type . ':'; - $key .= isset($settings['target_bundle']) ? $settings['target_bundle'] : ''; - - if (!isset(static::$propertyDefinitions[$key])) { - // Call the parent to define the target_id and entity properties. - parent::getPropertyDefinitions(); - - // Only add the revision ID property if the target entity type supports - // revisions. - $target_type_info = \Drupal::entityManager()->getDefinition($target_type); - if ($target_type_info->hasKey('revision') && $target_type_info->getRevisionTable()) { - static::$propertyDefinitions[$key]['revision_id'] = DataDefinition::create('integer') - ->setLabel(t('Revision ID')) - ->setConstraints(array('Range' => array('min' => 0))); - } + // Call the parent to define the target_id and entity properties. + $properties = parent::propertyDefinitions($field_definition); + + // Only add the revision ID property if the target entity type supports + // revisions. + $target_type_info = \Drupal::entityManager()->getDefinition($target_type); + if ($target_type_info->hasKey('revision') && $target_type_info->getRevisionTable()) { + $properties['revision_id'] = DataDefinition::create('integer') + ->setLabel(t('Revision ID')) + ->setConstraints(array('Range' => array('min' => 0))); } - return static::$propertyDefinitions[$key]; + return $properties; } /** diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index 098d83f..5689ab5 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -11,7 +11,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; -use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\Field\FieldItemDefinition; use Drupal\field\FieldException; use Drupal\field\FieldInterface; @@ -192,6 +192,15 @@ class Field extends ConfigEntityBase implements FieldInterface { public $original = NULL; /** + * An array of field property definitions. + * + * @var \Drupal\Core\TypedData\DataDefinitionInterface[] + * + * @see \Drupal\Core\TypedData\ComplexDataDefinitionInterface::getPropertyDefinitions() + */ + protected $propertyDefinitions; + + /** * The data definition of a field item. * * @var \Drupal\Core\TypedData\DataDefinition @@ -551,14 +560,6 @@ public function getSetting($setting_name) { /** * {@inheritdoc} */ - public function getPropertyNames() { - $schema = $this->getSchema(); - return array_keys($schema['columns']); - } - - /** - * {@inheritdoc} - */ public function isTranslatable() { return $this->translatable; } @@ -754,10 +755,65 @@ public function getConstraint($constraint_name) { */ public function getItemDefinition() { if (!isset($this->itemDefinition)) { - $this->itemDefinition = DataDefinition::create('field_item:' . $this->type) + $this->itemDefinition = FieldItemDefinition::create($this) ->setSettings($this->getSettings()); } return $this->itemDefinition; } + /** + * {@inheritdoc} + */ + public function getPropertyDefinition($name) { + if (!isset($this->propertyDefinitions)) { + $this->getPropertyDefinitions(); + } + if (isset($this->propertyDefinitions[$name])) { + return $this->propertyDefinitions[$name]; + } + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions() { + if (!isset($this->propertyDefinitions)) { + $class = $this->getFieldItemClass(); + $this->propertyDefinitions = $class::propertyDefinitions($this); + } + return $this->propertyDefinitions; + } + + /** + * {@inheritdoc} + */ + public function getPropertyNames() { + return array_keys($this->getPropertyDefinitions()); + } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + $class = $this->getFieldItemClass(); + return $class::getMainPropertyName(); + } + + /** + * Helper to retrieve the field item class. + * + * @todo: Remove once getClass() adds in defaults. See + * https://drupal.org/node/2116341. + */ + protected function getFieldItemClass() { + if ($class = $this->getItemDefinition()->getClass()) { + return $class; + } + else { + $type_definition = \Drupal::typedDataManager() + ->getDefinition($this->getItemDefinition()->getDataType()); + return $type_definition['class']; + } + } + } diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php index 7c2e381..2fc1ddd 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Field\FieldItemDefinition; use Drupal\field\FieldException; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInstanceInterface; @@ -496,14 +497,6 @@ public function getSetting($setting_name) { /** * {@inheritdoc} */ - public function getPropertyNames() { - $schema = $this->field->getSchema(); - return array_keys($schema['columns']); - } - - /** - * {@inheritdoc} - */ public function isTranslatable() { return $this->field->translatable; } @@ -676,9 +669,37 @@ public function getConstraint($constraint_name) { */ public function getItemDefinition() { if (!isset($this->itemDefinition)) { - $this->itemDefinition = DataDefinition::create('field_item:' . $this->field->type) + $this->itemDefinition = FieldItemDefinition::create($this) ->setSettings($this->getSettings()); } return $this->itemDefinition; } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinition($name) { + return $this->field->getPropertyDefinition($name); + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions() { + return $this->field->getPropertyDefinitions(); + } + + /** + * {@inheritdoc} + */ + public function getPropertyNames() { + return $this->field->getPropertyNames(); + } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + return $this->field->getMainPropertyName(); + } } diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php index d3597fd..700efde 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php @@ -7,8 +7,8 @@ namespace Drupal\field_test\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; -use Drupal\field_test\Plugin\Field\FieldType\TestItem; /** * Defines the 'hidden_test' entity field item. @@ -25,23 +25,13 @@ class HiddenTestItem extends TestItem { /** - * Property definitions of the contained properties. - * - * @see TestItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('integer') + ->setLabel(t('Test integer value')); - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('integer') - ->setLabel(t('Test integer value')); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php index fedd03c..f20940e 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php @@ -7,6 +7,7 @@ namespace Drupal\field_test\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; use Drupal\Core\Field\ConfigFieldItemBase; @@ -28,26 +29,16 @@ class ShapeItem extends ConfigFieldItemBase { /** - * Property definitions of the contained properties. - * - * @see ShapeItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['shape'] = DataDefinition::create('string') - ->setLabel(t('Shape')); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['shape'] = DataDefinition::create('string') + ->setLabel(t('Shape')); - static::$propertyDefinitions['color'] = DataDefinition::create('string') - ->setLabel(t('Color')); - } - return static::$propertyDefinitions; + $properties['color'] = DataDefinition::create('string') + ->setLabel(t('Color')); + + return $properties; } /** diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php index ed8f38a..80b70be 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php @@ -7,6 +7,7 @@ namespace Drupal\field_test\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\PrepareCacheInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -35,23 +36,13 @@ class TestItem extends ConfigFieldItemBase implements PrepareCacheInterface { /** - * Property definitions of the contained properties. - * - * @see TestItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('integer') - ->setLabel(t('Test integer value')); - } - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('integer') + ->setLabel(t('Test integer value')); + + return $properties; } /** diff --git a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php index 188ae85..3167780 100644 --- a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php +++ b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php @@ -7,6 +7,7 @@ namespace Drupal\file\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -20,6 +21,7 @@ * label = @Translation("File"), * description = @Translation("This field stores the ID of a file as an integer value."), * settings = { + * "target_type" = "file", * "display_field" = "0", * "display_default" = "0", * "uri_scheme" = "" @@ -38,15 +40,6 @@ class FileItem extends EntityReferenceItem implements ConfigFieldItemInterface { /** - * Property definitions of the contained properties. - * - * @see FileItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ public static function schema(FieldInterface $field) { @@ -87,19 +80,16 @@ public static function schema(FieldInterface $field) { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - $this->definition->setSetting('target_type', 'file'); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties = parent::propertyDefinitions($field_definition); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions = parent::getPropertyDefinitions(); + $properties['display'] = DataDefinition::create('boolean') + ->setLabel(t('Flag to control whether this file should be displayed when viewing content')); - static::$propertyDefinitions['display'] = DataDefinition::create('boolean') - ->setLabel(t('Flag to control whether this file should be displayed when viewing content')); + $properties['description'] = DataDefinition::create('string') + ->setLabel(t('A description of the file')); - static::$propertyDefinitions['description'] = DataDefinition::create('string') - ->setLabel(t('A description of the file')); - } - return static::$propertyDefinitions; + return $properties; } /** diff --git a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php index 59e464c..c20b268 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php +++ b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php @@ -7,6 +7,7 @@ namespace Drupal\image\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; use Drupal\file\Plugin\Field\FieldType\FileItem; @@ -19,6 +20,7 @@ * label = @Translation("Image"), * description = @Translation("This field stores the ID of an image file as an integer value."), * settings = { + * "target_type" = "file", * "uri_scheme" = "", * "default_image" = { * "fid" = NULL, @@ -117,25 +119,22 @@ public static function schema(FieldInterface $field) { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - $this->definition->setSetting('target_type', 'file'); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties = parent::propertyDefinitions($field_definition); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions = parent::getPropertyDefinitions(); + $properties['alt'] = DataDefinition::create('string') + ->setLabel(t("Alternative image text, for the image's 'alt' attribute.")); - static::$propertyDefinitions['alt'] = DataDefinition::create('string') - ->setLabel(t("Alternative image text, for the image's 'alt' attribute.")); + $properties['title'] = DataDefinition::create('string') + ->setLabel(t("Image title text, for the image's 'title' attribute.")); - static::$propertyDefinitions['title'] = DataDefinition::create('string') - ->setLabel(t("Image title text, for the image's 'title' attribute.")); + $properties['width'] = DataDefinition::create('integer') + ->setLabel(t('The width of the image in pixels.')); - static::$propertyDefinitions['width'] = DataDefinition::create('integer') - ->setLabel(t('The width of the image in pixels.')); + $properties['height'] = DataDefinition::create('integer') + ->setLabel(t('The height of the image in pixels.')); - static::$propertyDefinitions['height'] = DataDefinition::create('integer') - ->setLabel(t('The height of the image in pixels.')); - } - return static::$propertyDefinitions; + return $properties; } /** diff --git a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php index 3c914ae..db5441e 100644 --- a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php +++ b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php @@ -8,7 +8,9 @@ namespace Drupal\link\Plugin\Field\FieldType; use Drupal\Core\Field\ConfigFieldItemBase; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\TypedData\MapDefinition; use Drupal\field\FieldInterface; /** @@ -28,27 +30,19 @@ class LinkItem extends ConfigFieldItemBase { /** - * Definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['url'] = DataDefinition::create('uri') - ->setLabel(t('URL')); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['url'] = DataDefinition::create('uri') + ->setLabel(t('URL')); + + $properties['title'] = DataDefinition::create('string') + ->setLabel(t('Link text')); - static::$propertyDefinitions['title'] = DataDefinition::create('string') - ->setLabel(t('Link text')); + $properties['attributes'] = MapDefinition::create('map') + ->setLabel(t('Attributes')); - static::$propertyDefinitions['attributes'] = DataDefinition::create('map') - ->setLabel(t('Attributes')); - } - return static::$propertyDefinitions; + return $properties; } /** diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php index 16353db..6083706 100644 --- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php +++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php @@ -7,6 +7,7 @@ namespace Drupal\number\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; use Drupal\Component\Utility\MapArray; @@ -37,12 +38,11 @@ class DecimalItem extends NumberItemBase { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Decimal value')); - } - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Decimal value')); + + return $properties; } /** diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php index 88ee07f..ccbe819 100644 --- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php +++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php @@ -7,6 +7,7 @@ namespace Drupal\number\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -32,12 +33,11 @@ class FloatItem extends NumberItemBase { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('float') - ->setLabel(t('Float value')); - } - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('float') + ->setLabel(t('Float value')); + + return $properties; } /** diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php index dfe35f6..a8cf839 100644 --- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php +++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php @@ -7,6 +7,7 @@ namespace Drupal\number\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -32,12 +33,11 @@ class IntegerItem extends NumberItemBase { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('integer') - ->setLabel(t('Integer value')); - } - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('integer') + ->setLabel(t('Integer value')); + + return $properties; } /** diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/NumberItemBase.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/NumberItemBase.php index e8630be..c8d8ac1 100644 --- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/NumberItemBase.php +++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/NumberItemBase.php @@ -15,13 +15,6 @@ abstract class NumberItemBase extends ConfigFieldItemBase { /** - * Definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ public function instanceSettingsForm(array $form, array &$form_state) { diff --git a/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php b/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php index 6b18833..12d0c85 100644 --- a/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php +++ b/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php @@ -7,6 +7,7 @@ namespace Drupal\options\Type; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\LegacyConfigFieldItem; use Drupal\Core\TypedData\DataDefinition; @@ -16,23 +17,13 @@ class ListFloatItem extends LegacyConfigFieldItem { /** - * Definitions of the contained properties. - * - * @see FloatItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('float') + ->setLabel(t('Float value')); - /** - * Implements ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('float') - ->setLabel(t('Float value')); - } - return static::$propertyDefinitions; + return $properties; } + } diff --git a/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php b/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php index 72ed788..cd9bc81 100644 --- a/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php +++ b/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php @@ -7,6 +7,7 @@ namespace Drupal\options\Type; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\LegacyConfigFieldItem; use Drupal\Core\TypedData\DataDefinition; @@ -16,23 +17,13 @@ class ListIntegerItem extends LegacyConfigFieldItem { /** - * Definitions of the contained properties. - * - * @see IntegerItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('integer') + ->setLabel(t('Integer value')); - /** - * Implements ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('integer') - ->setLabel(t('Integer value')); - } - return static::$propertyDefinitions; + return $properties; } + } diff --git a/core/modules/options/lib/Drupal/options/Type/ListTextItem.php b/core/modules/options/lib/Drupal/options/Type/ListTextItem.php index b66d355..41ea0db 100644 --- a/core/modules/options/lib/Drupal/options/Type/ListTextItem.php +++ b/core/modules/options/lib/Drupal/options/Type/ListTextItem.php @@ -7,6 +7,7 @@ namespace Drupal\options\Type; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\LegacyConfigFieldItem; use Drupal\Core\TypedData\DataDefinition; @@ -16,24 +17,13 @@ class ListTextItem extends LegacyConfigFieldItem { /** - * Definitions of the contained properties. - * - * @see TextItem::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * Implements ComplexDataInterface::getPropertyDefinitions(). */ - public function getPropertyDefinitions() { + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Text value')); - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Text value')); - } - return static::$propertyDefinitions; + return $properties; } } diff --git a/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php index 601bc0b..c89ea05 100644 --- a/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php +++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php @@ -7,6 +7,7 @@ namespace Drupal\path\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; @@ -23,26 +24,16 @@ class PathItem extends FieldItemBase { /** - * Definitions of the contained properties. - * - * @see PathItem::getPropertyDefinitions() - * - * @var array + * {@inheritdoc} */ - static $propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['alias'] = DataDefinition::create('string') + ->setLabel(t('Path alias')); - /** - * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['alias'] = DataDefinition::create('string') - ->setLabel(t('Path alias')); - - static::$propertyDefinitions['pid'] = DataDefinition::create('string') - ->setLabel(t('Path id')); - } - return static::$propertyDefinitions; + $properties['pid'] = DataDefinition::create('string') + ->setLabel(t('Path id')); + + return $properties; } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPath.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPath.php index 885d304..6e235e5 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPath.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPath.php @@ -7,6 +7,7 @@ namespace Drupal\shortcut; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\StringItem; use Drupal\Core\TypedData\DataDefinition; @@ -16,25 +17,14 @@ class ShortcutPath extends StringItem { /** - * Definitions of the contained properties. - * - * @see self::getPropertyDefinitions() - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('String value')) - ->setComputed(TRUE) - ->setClass('\Drupal\shortcut\ShortcutPathValue'); - } - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('String value')) + ->setComputed(TRUE) + ->setClass('\Drupal\shortcut\ShortcutPathValue'); + return $properties; } } diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php new file mode 100644 index 0000000..520c3c3 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/MetadataTest.php @@ -0,0 +1,148 @@ + 'Metadata', + 'description' => 'Tests reading and deriving metadata of core data types.', + 'group' => 'Typed Data API', + ); + } + + public function setUp() { + parent::setup(); + $this->typedDataManager = $this->container->get('typed_data_manager'); + } + + /** + * Tests deriving metadata about list items. + */ + 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('string', TRUE); + $this->assertTrue($list2 instanceof ListDefinitionInterface); + $this->assertEqual($list, $list2); + + // Test creating a single list item, which is the same as a list of any + // items. + $list = $this->typedDataManager->createDataDefinition('list'); + $this->assertTrue($list instanceof ListDefinitionInterface); + $this->assertEqual($list->getDataType(), 'list'); + $this->assertEqual($list->getItemDefinition()->getDataType(), 'any'); + } + + /** + * Tests deriving metadata about maps. + */ + public function testMaps() { + $map = MapDefinition::create() + ->setPropertyDefinition('one', DataDefinition::create('string')) + ->setPropertyDefinition('two', DataDefinition::create('string')) + ->setPropertyDefinition('three', DataDefinition::create('string')); + + $this->assertTrue($map instanceof ComplexDataDefinitionInterface); + + // Test retrieving metadata about contained properties. + $this->assertEqual(array_keys($map->getPropertyDefinitions()), array('one', 'two', 'three')); + $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); + } + + /** + * Tests deriving metadata about fields. + */ + public function testFields() { + $field = FieldDefinition::create('integer'); + // Fields are lists of complex data. + $this->assertTrue($field instanceof ListDefinitionInterface); + $this->assertFalse($field instanceof ComplexDataDefinitionInterface); + $field_item = $field->getItemDefinition(); + $this->assertFalse($field_item instanceof ListDefinitionInterface); + $this->assertTrue($field_item instanceof ComplexDataDefinitionInterface); + + // Derive metadata about field item properties. + $this->assertEqual(array_keys($field_item->getPropertyDefinitions()), array('value')); + $this->assertEqual($field_item->getPropertyDefinition('value')->getDataType(), 'integer'); + $this->assertEqual($field_item->getMainPropertyName(), 'value'); + $this->assertNull($field_item->getPropertyDefinition('invalid')); + + // To ease access of field item property metadata, field definitions make + // metadata about field item properties on the field level as well. + $this->assertTrue($field instanceof FieldDefinitionInterface); + $this->assertEqual(array_keys($field->getPropertyDefinitions()), array('value')); + $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)); + } + + /** + * Tests deriving metadata about entities. + */ + public function testEntities() { + // @todo: Implement. + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php index eeb6bb5..985f401 100644 --- a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php @@ -10,6 +10,8 @@ use Drupal\Core\Field\FieldDefinition; use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\ListDefinition; +use Drupal\Core\TypedData\MapDefinition; +use Drupal\Core\TypedData\Plugin\DataType\Map; use Drupal\simpletest\DrupalUnitTestBase; use Drupal\Core\Datetime\DrupalDateTime; @@ -410,9 +412,12 @@ public function testTypedDataMaps() { 'two' => 'zwei', 'three' => 'drei', ); - $typed_data = $this->createTypedData(array( - 'type' => 'map', - ), $value); + $definition = MapDefinition::create('map') + ->setPropertyDefinition('one', DataDefinition::create('string')) + ->setPropertyDefinition('two', DataDefinition::create('string')) + ->setPropertyDefinition('three', DataDefinition::create('string')); + + $typed_data = $this->createTypedData($definition, $value); // Test iterating. $count = 0; @@ -424,9 +429,9 @@ public function testTypedDataMaps() { // Test retrieving metadata. $this->assertEqual(array_keys($typed_data->getPropertyDefinitions()), array_keys($value)); - $definition = $typed_data->getPropertyDefinition('one'); - $this->assertEqual($definition->getDataType(), 'any'); - $this->assertFalse($typed_data->getPropertyDefinition('invalid')); + $definition = $typed_data->getDefinition()->getPropertyDefinition('one'); + $this->assertEqual($definition->getDataType(), 'string'); + $this->assertNull($typed_data->getDefinition()->getPropertyDefinition('invalid')); // Test getting and setting properties. $this->assertEqual($typed_data->get('one')->getValue(), 'eins'); @@ -450,8 +455,11 @@ public function testTypedDataMaps() { $this->assertEqual($typed_data->get('two')->getValue(), 'zwei'); $this->assertEqual($typed_data->get('three')->getValue(), 'drei'); + // Test setting a not defined property. It shouldn't show up in the + // properties, but be kept in the values. $typed_data->setValue(array('foo' => 'bar')); - $this->assertEqual(array_keys($typed_data->getProperties()), array('foo')); + $this->assertEqual(array_keys($typed_data->getProperties()), array('one', 'two', 'three')); + $this->assertEqual(array_keys($typed_data->getValue()), array('foo', 'one', 'two', 'three')); // Test getting the string representation. $typed_data->setValue(array('one' => 'eins', 'two' => '', 'three' => 'drei')); @@ -492,10 +500,11 @@ public function testTypedDataMaps() { $this->pass('Exception thrown:' . $e->getMessage()); } - // Test adding a new entry to the map. + // Test adding a new property to the map. + $typed_data->getDefinition()->setPropertyDefinition('zero', DataDefinition::create('any')); $typed_data->set('zero', 'null'); $this->assertEqual($typed_data->get('zero')->getValue(), 'null'); - $definition = $typed_data->getPropertyDefinition('zero'); + $definition = $typed_data->get('zero')->getDefinition(); $this->assertEqual($definition->getDataType(), 'any', 'Definition for a new map entry returned.'); } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php index 13025de..f637c98 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php @@ -21,6 +21,7 @@ * label = @Translation("Term Reference"), * description = @Translation("This field stores a reference to a taxonomy term."), * settings = { + * "target_type" = "taxonomy_term", * "options_list_callback" = NULL, * "allowed_values" = { * { @@ -89,14 +90,6 @@ public function getSettableOptions(AccountInterface $account = NULL) { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - $this->definition['settings']['target_type'] = 'taxonomy_term'; - return parent::getPropertyDefinitions(); - } - - /** - * {@inheritdoc} - */ public static function schema(FieldInterface $field) { return array( 'columns' => array( diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php index e55fd52..dd23ca3 100644 --- a/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php +++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php @@ -8,6 +8,7 @@ namespace Drupal\telephone\Plugin\Field\FieldType; use Drupal\Core\Field\ConfigFieldItemBase; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -25,13 +26,6 @@ class TelephoneItem extends ConfigFieldItemBase { /** - * Definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ public static function schema(FieldInterface $field) { @@ -49,12 +43,11 @@ public static function schema(FieldInterface $field) { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Telephone number')); - } - return static::$propertyDefinitions; + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Telephone number')); + + return $properties; } /** diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php index 90d86c2..643b5b7 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php +++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php @@ -8,6 +8,7 @@ namespace Drupal\text\Plugin\Field\FieldType; use Drupal\Core\Field\ConfigFieldItemBase; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\PrepareCacheInterface; use Drupal\Core\TypedData\DataDefinition; @@ -17,31 +18,23 @@ abstract class TextItemBase extends ConfigFieldItemBase implements PrepareCacheInterface { /** - * Definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Text value')); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Text value')); - static::$propertyDefinitions['format'] = DataDefinition::create('filter_format') - ->setLabel(t('Text format')); + $properties['format'] = DataDefinition::create('filter_format') + ->setLabel(t('Text format')); - static::$propertyDefinitions['processed'] = DataDefinition::create('string') - ->setLabel(t('Processed text')) - ->setDescription(t('The text value with the text format applied.')) - ->setComputed(TRUE) - ->setClass('\Drupal\text\TextProcessed') - ->setSetting('text source', 'value'); - } - return static::$propertyDefinitions; + $properties['processed'] = DataDefinition::create('string') + ->setLabel(t('Processed text')) + ->setDescription(t('The text value with the text format applied.')) + ->setComputed(TRUE) + ->setClass('\Drupal\text\TextProcessed') + ->setSetting('text source', 'value'); + + return $properties; } /** diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php index 1efad43..1e0b7c7 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php +++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php @@ -7,6 +7,7 @@ namespace Drupal\text\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInterface; @@ -28,30 +29,22 @@ class TextWithSummaryItem extends TextItemBase { /** - * Definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - - /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions = parent::getPropertyDefinitions(); + public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { + $properties = parent::propertyDefinitions($field_definition); + + $properties['summary'] = DataDefinition::create('string') + ->setLabel(t('Summary text value')); - static::$propertyDefinitions['summary'] = DataDefinition::create('string') - ->setLabel(t('Summary text value')); + $properties['summary_processed'] = DataDefinition::create('string') + ->setLabel(t('Processed summary text')) + ->setDescription(t('The summary text value with the text format applied.')) + ->setComputed(TRUE) + ->setClass('\Drupal\text\TextProcessed') + ->setSetting('text source', 'summary'); - static::$propertyDefinitions['summary_processed'] = DataDefinition::create('string') - ->setLabel(t('Processed summary text')) - ->setDescription(t('The summary text value with the text format applied.')) - ->setComputed(TRUE) - ->setClass('\Drupal\text\TextProcessed') - ->setSetting('text source', 'summary'); - } - return static::$propertyDefinitions; + return $properties; } /** diff --git a/core/tests/Drupal/Tests/Core/Entity/FieldDefinitionTest.php b/core/tests/Drupal/Tests/Core/Entity/FieldDefinitionTest.php index 2982685..2854045 100644 --- a/core/tests/Drupal/Tests/Core/Entity/FieldDefinitionTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/FieldDefinitionTest.php @@ -57,7 +57,7 @@ protected function setUp() { * Tests field name methods. */ public function testFieldName() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $field_name = $this->randomName(); $definition->setName($field_name); $this->assertEquals($field_name, $definition->getName()); @@ -67,7 +67,7 @@ public function testFieldName() { * Tests field label methods. */ public function testFieldLabel() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $label = $this->randomName(); $definition->setLabel($label); $this->assertEquals($label, $definition->getLabel()); @@ -77,7 +77,7 @@ public function testFieldLabel() { * Tests field description methods. */ public function testFieldDescription() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $description = $this->randomName(); $definition->setDescription($description); $this->assertEquals($description, $definition->getDescription()); @@ -96,7 +96,7 @@ public function testFieldType() { * Tests field settings methods. */ public function testFieldSettings() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $setting = $this->randomName(); $value = $this->randomName(); $definition->setSetting($setting, $value); @@ -108,7 +108,7 @@ public function testFieldSettings() { * Tests field default value. */ public function testFieldDefaultValue() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $setting = 'default_value'; $value = $this->randomName(); $definition->setSetting($setting, $value); @@ -122,7 +122,7 @@ public function testFieldDefaultValue() { * Tests field translatable methods. */ public function testFieldTranslatable() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $this->assertFalse($definition->isTranslatable()); $definition->setTranslatable(TRUE); $this->assertTrue($definition->isTranslatable()); @@ -134,7 +134,7 @@ public function testFieldTranslatable() { * Tests field cardinality. */ public function testFieldCardinality() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $this->assertEquals(1, $definition->getCardinality()); // @todo: Add more tests when this can be controlled. } @@ -143,7 +143,7 @@ public function testFieldCardinality() { * Tests required. */ public function testFieldRequired() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $this->assertFalse($definition->isRequired()); $definition->setRequired(TRUE); $this->assertTrue($definition->isRequired()); @@ -155,7 +155,7 @@ public function testFieldRequired() { * Tests configurable. */ public function testFieldConfigurable() { - $definition = new FieldDefinition(); + $definition = FieldDefinition::create('integer'); $this->assertFalse($definition->isConfigurable()); }