diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index f552c54..e7a9992 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -494,15 +494,17 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) { // Enforce field definitions to be objects. foreach ($this->entityFieldInfo[$entity_type]['definitions'] as $field_name => &$definition) { if (is_array($definition)) { - $definition = FieldDefinition::createFromOldStyleDefinition($definition) - ->setFieldName($field_name); + $definition = FieldDefinition::createFromOldStyleDefinition($definition); } + // Make sure the field name is properly set. + $definition->setFieldName($field_name); } foreach ($this->entityFieldInfo[$entity_type]['optional'] as $field_name => &$definition) { if (is_array($definition)) { - $definition = FieldDefinition::createFromOldStyleDefinition($definition) - ->setFieldName($field_name); + $definition = FieldDefinition::createFromOldStyleDefinition($definition); } + // Make sure the field name is properly set. + $definition->setFieldName($field_name); } $this->cache->set($cid, $this->entityFieldInfo[$entity_type], CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE, 'entity_field_info' => TRUE)); } diff --git a/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php index 226a9ca..e46bc69 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php @@ -17,6 +17,25 @@ class FieldDefinition extends ListDefinition implements FieldDefinitionInterface, \ArrayAccess { /** + * Creates a new entity field definition. + * + * @return \Drupal\Core\Entity\Field\FieldDefinition + */ + public static function create() { + $class = get_called_class(); + return new $class(); + } + + /** + * {@inheritdoc} + */ + public function __construct(array $definition = array()) { + parent::__construct($definition); + // Set a default list type to use. + $this->setDataType('entity_field'); + } + + /** * {@inheritdoc} */ public function getFieldName() { @@ -42,9 +61,18 @@ public function setFieldName($name) { * {@inheritdoc} */ public function getFieldType() { - // Cut of the leading field_item: prefix from 'field_item:FIELD_TYPE'. - $parts = explode(':', $this->getItemDefinition()->getDataType()); - return $parts[1]; + // We have to support 'field_item:FIELD_TYPE' data types as well as + // 'FIELD_TYPE_field' for field types that are not yet implemented as field + // type plugin. + $data_type = $this->getItemDefinition()->getDataType(); + if (strpos($data_type, ':') !== FALSE) { + // Cut of the leading field_item: prefix from 'field_item:FIELD_TYPE'. + $parts = explode(':', $data_type); + return $parts[1]; + } + else { + return str_replace('_field', '', $data_type); + } } /** @@ -57,7 +85,14 @@ public function getFieldType() { * The object itself for chaining. */ public function setFieldType($type) { - $this->getItemDefinition()->setDataType('field_item:' . $type); + // Determine the right data type to use. + if (\Drupal::typedData()->getDefinition('field_item:' . $type)) { + $this->getItemDefinition()->setDataType('field_item:' . $type); + } + else { + // Data type has not been converted to a field type plugin yet. + $this->getItemDefinition()->setDataType($type . '_field'); + } return $this; } @@ -78,7 +113,8 @@ public function getFieldSettings() { * The object itself for chaining. */ public function setFieldSettings(array $settings) { - return $this->getItemDefinition()->setSettings($settings); + $this->getItemDefinition()->setSettings($settings); + return $this; } /** @@ -269,7 +305,9 @@ public static function createFromOldStyleDefinition(array $definition) { } } - // Take care of the item definition. + // Take care of the item definition now. 'required' applies to the list + // definition. + unset($definition['required']); $item_definition = new DataDefinition($definition); if (isset($definition['settings'])) { $item_definition->setSettings($definition['settings']); @@ -302,8 +340,10 @@ public function &offsetGet($offset) { public function offsetSet($offset, $value) { if ($offset == 'type') { // What previously was "type" is now the type of the list item. - $this->itemDefinition['type'] = $value; + $this->itemDefinition->setDataType($value); + } + else { + $this->definition[$offset] = $value; } - $this->definition[$offset] = $value; } } diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemList.php b/core/lib/Drupal/Core/Entity/Field/FieldItemList.php deleted file mode 100644 index a2b308c..0000000 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemList.php +++ /dev/null @@ -1,298 +0,0 @@ -definition['field_name'] = $name; - // Always initialize one empty item as most times a value for at least one - // item will be present. That way prototypes created by - // \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() will - // already have this field item ready for use after cloning. - $this->list[0] = $this->createItem(0); - } - - /** - * {@inheritdoc} - */ - public function getEntity() { - return $this->getParent(); - } - - /** - * {@inheritdoc} - */ - public function setLangcode($langcode) { - $this->langcode = $langcode; - } - - /** - * {@inheritdoc} - */ - public function getLangcode() { - return $this->langcode; - } - - /** - * {@inheritdoc} - */ - public function getFieldDefinition() { - return $this->definition; - } - - /** - * {@inheritdoc} - */ - public function filterEmptyValues() { - if (isset($this->list)) { - $this->list = array_values(array_filter($this->list, function($item) { - return !$item->isEmpty(); - })); - } - } - - /** - * {@inheritdoc} - * @todo Revisit the need when all entity types are converted to NG entities. - */ - public function getValue($include_computed = FALSE) { - if (isset($this->list)) { - $values = array(); - foreach ($this->list as $delta => $item) { - $values[$delta] = $item->getValue($include_computed); - } - return $values; - } - } - - /** - * Overrides \Drupal\Core\TypedData\Plugin\DataType\ItemList::setValue(). - */ - public function setValue($values, $notify = TRUE) { - if (!isset($values) || $values === array()) { - $this->list = $values; - } - else { - // Support passing in only the value of the first item. - if (!is_array($values) || !is_numeric(current(array_keys($values)))) { - $values = array(0 => $values); - } - - // Clear the values of properties for which no value has been passed. - if (isset($this->list)) { - $this->list = array_intersect_key($this->list, $values); - } - - // Set the values. - foreach ($values as $delta => $value) { - if (!is_numeric($delta)) { - throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.'); - } - elseif (!isset($this->list[$delta])) { - $this->list[$delta] = $this->createItem($delta, $value); - } - else { - $this->list[$delta]->setValue($value, FALSE); - } - } - } - // Notify the parent of any changes. - if ($notify && isset($this->parent)) { - $this->parent->onChange($this->name); - } - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::getPropertyDefinition(). - */ - public function getPropertyDefinition($name) { - return $this->offsetGet(0)->getPropertyDefinition($name); - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::getPropertyDefinitions(). - */ - public function getPropertyDefinitions() { - return $this->offsetGet(0)->getPropertyDefinitions(); - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__get(). - */ - public function __get($property_name) { - return $this->offsetGet(0)->__get($property_name); - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::get(). - */ - public function get($property_name) { - return $this->offsetGet(0)->get($property_name); - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__set(). - */ - public function __set($property_name, $value) { - $this->offsetGet(0)->__set($property_name, $value); - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__isset(). - */ - public function __isset($property_name) { - return $this->offsetGet(0)->__isset($property_name); - } - - /** - * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__unset(). - */ - public function __unset($property_name) { - return $this->offsetGet(0)->__unset($property_name); - } - - /** - * {@inheritdoc} - */ - public function access($operation = 'view', AccountInterface $account = NULL) { - $access_controller = \Drupal::entityManager()->getAccessController($this->getParent()->entityType()); - return $access_controller->fieldAccess($operation, $this->getFieldDefinition(), $account, $this); - } - - /** - * {@inheritdoc} - */ - public function defaultAccess($operation = 'view', AccountInterface $account = NULL) { - // Grant access per default. - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function applyDefaultValue($notify = TRUE) { - $value = $this->getFieldDefinition()->getFieldDefaultValue($this->getEntity()); - - // NULL or array() mean "no default value", but 0, '0' and the empty string - // are valid default values. - if (!isset($value) || (is_array($value) && empty($value))) { - // Create one field item and apply defaults. - $this->offsetGet(0)->applyDefaultValue(FALSE); - } - else { - $this->setValue($value, $notify); - } - return $this; - } - - /** - * {@inheritdoc} - */ - public function getConstraints() { - // Constraints usually apply to the field item, but required does make - // sense on the field only. So we special-case it to apply to the field for - // now. - // @todo: Separate list and list item definitions to separate constraints. - $constraints = array(); - if (!empty($this->definition['required'])) { - $constraints[] = \Drupal::typedData()->getValidationConstraintManager()->create('NotNull', array()); - } - return $constraints; - } - - /** - * {@inheritdoc} - */ - public function preSave() { - // Filter out empty items. - $this->filterEmptyValues(); - - $this->delegateMethod('presave'); - } - - /** - * {@inheritdoc} - */ - public function insert() { - $this->delegateMethod('insert'); - } - - /** - * {@inheritdoc} - */ - public function update() { - $this->delegateMethod('update'); - } - - /** - * {@inheritdoc} - */ - public function delete() { - $this->delegateMethod('delete'); - } - - /** - * {@inheritdoc} - */ - public function deleteRevision() { - $this->delegateMethod('deleteRevision'); - } - - /** - * Calls a method on each FieldItem. - * - * @param string $method - * The name of the method. - */ - protected function delegateMethod($method) { - if (isset($this->list)) { - foreach ($this->list as $item) { - $item->{$method}(); - } - } - } - -} diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/BooleanItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/BooleanItem.php index 31e3ec8..d1357be 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/BooleanItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/BooleanItem.php @@ -18,7 +18,7 @@ * id = "boolean_field", * label = @Translation("Boolean field item"), * description = @Translation("An entity field containing a boolean value."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class BooleanItem extends FieldItemBase { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/DateItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/DateItem.php index e6f462f..a23233e 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/DateItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/DateItem.php @@ -18,7 +18,7 @@ * id = "date_field", * label = @Translation("Date field item"), * description = @Translation("An entity field containing a date value."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class DateItem extends FieldItemBase { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/EmailItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/EmailItem.php index 6d1dba6..d736529 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/EmailItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/EmailItem.php @@ -19,7 +19,7 @@ * id = "email_field", * label = @Translation("E-mail field item"), * description = @Translation("An entity field containing an e-mail value."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class EmailItem extends LegacyConfigFieldItem { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php index 5654747..e8b2980 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php @@ -25,7 +25,7 @@ * id = "entity_reference_field", * label = @Translation("Entity reference field item"), * description = @Translation("An entity field containing an entity reference."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList", + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList", * constraints = {"ValidReference" = TRUE} * ) */ diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItem.php index b630fc7..c338151 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItem.php @@ -19,7 +19,7 @@ * @DataType( * id = "field_item", * label = @Translation("Field item"), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList", + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList", * derivative = "Drupal\Core\Entity\Plugin\DataType\Deriver\FieldItemDeriver" * ) */ diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php index b3ce264..561aa1d 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php @@ -7,14 +7,21 @@ namespace Drupal\Core\Entity\Plugin\DataType; +use Drupal\Core\Entity\Field\FieldItemListInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\TypedData\TypedDataInterface; +use Drupal\Core\TypedData\Plugin\DataType\ItemList; +use Drupal\Core\Language\Language; use Drupal\Core\TypedData\Annotation\DataType; use Drupal\Core\Annotation\Translation; -use Drupal\Core\Entity\Field\FieldItemList as ExistingFieldItemList; /** * Defines a data type plugin for entity fields, i.e. the list of field items. * - * @todo: Move the whole implementation to this place. + * An entity field is a list of field items, containing various field item + * properties. Note that even single-valued entity fields are represented as + * list of field items, however for easy access to the contained item the entity + * field delegates __get() and __set() calls directly to the first item. * * @DataType( * id = "entity_field", @@ -22,6 +29,259 @@ * class = "\Drupal\Core\Entity\Field\Field" * ) */ -class FieldItemList extends ExistingFieldItemList { +class FieldItemList extends ItemList implements FieldItemListInterface { + + /** + * Numerically indexed array of field items, implementing the + * FieldItemInterface. + * + * @var array + */ + protected $list = array(); + + /** + * The langcode of the field values held in the object. + * + * @var string + */ + protected $langcode = Language::LANGCODE_DEFAULT; + + /** + * Overrides TypedData::__construct(). + */ + public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { + parent::__construct($definition, $name, $parent); + $this->definition['field_name'] = $name; + // Always initialize one empty item as most times a value for at least one + // item will be present. That way prototypes created by + // \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() will + // already have this field item ready for use after cloning. + $this->list[0] = $this->createItem(0); + } + + /** + * {@inheritdoc} + */ + public function getEntity() { + return $this->getParent(); + } + + /** + * {@inheritdoc} + */ + public function setLangcode($langcode) { + $this->langcode = $langcode; + } + + /** + * {@inheritdoc} + */ + public function getLangcode() { + return $this->langcode; + } + + /** + * {@inheritdoc} + */ + public function getFieldDefinition() { + return $this->definition; + } + + /** + * {@inheritdoc} + */ + public function filterEmptyValues() { + if (isset($this->list)) { + $this->list = array_values(array_filter($this->list, function($item) { + return !$item->isEmpty(); + })); + } + } + + /** + * {@inheritdoc} + * @todo Revisit the need when all entity types are converted to NG entities. + */ + public function getValue($include_computed = FALSE) { + if (isset($this->list)) { + $values = array(); + foreach ($this->list as $delta => $item) { + $values[$delta] = $item->getValue($include_computed); + } + return $values; + } + } + + /** + * Overrides \Drupal\Core\TypedData\Plugin\DataType\ItemList::setValue(). + */ + public function setValue($values, $notify = TRUE) { + if (!isset($values) || $values === array()) { + $this->list = $values; + } + else { + // Support passing in only the value of the first item. + if (!is_array($values) || !is_numeric(current(array_keys($values)))) { + $values = array(0 => $values); + } + + // Clear the values of properties for which no value has been passed. + if (isset($this->list)) { + $this->list = array_intersect_key($this->list, $values); + } + + // Set the values. + foreach ($values as $delta => $value) { + if (!is_numeric($delta)) { + throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.'); + } + elseif (!isset($this->list[$delta])) { + $this->list[$delta] = $this->createItem($delta, $value); + } + else { + $this->list[$delta]->setValue($value, FALSE); + } + } + } + // Notify the parent of any changes. + if ($notify && isset($this->parent)) { + $this->parent->onChange($this->name); + } + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::getPropertyDefinition(). + */ + public function getPropertyDefinition($name) { + return $this->offsetGet(0)->getPropertyDefinition($name); + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::getPropertyDefinitions(). + */ + public function getPropertyDefinitions() { + return $this->offsetGet(0)->getPropertyDefinitions(); + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__get(). + */ + public function __get($property_name) { + return $this->offsetGet(0)->__get($property_name); + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::get(). + */ + public function get($property_name) { + return $this->offsetGet(0)->get($property_name); + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__set(). + */ + public function __set($property_name, $value) { + $this->offsetGet(0)->__set($property_name, $value); + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__isset(). + */ + public function __isset($property_name) { + return $this->offsetGet(0)->__isset($property_name); + } + + /** + * Implements \Drupal\Core\Entity\Field\FieldItemListInterface::__unset(). + */ + public function __unset($property_name) { + return $this->offsetGet(0)->__unset($property_name); + } + + /** + * {@inheritdoc} + */ + public function access($operation = 'view', AccountInterface $account = NULL) { + $access_controller = \Drupal::entityManager()->getAccessController($this->getParent()->entityType()); + return $access_controller->fieldAccess($operation, $this->getFieldDefinition(), $account, $this); + } + + /** + * {@inheritdoc} + */ + public function defaultAccess($operation = 'view', AccountInterface $account = NULL) { + // Grant access per default. + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function applyDefaultValue($notify = TRUE) { + $value = $this->getFieldDefinition()->getFieldDefaultValue($this->getEntity()); + + // NULL or array() mean "no default value", but 0, '0' and the empty string + // are valid default values. + if (!isset($value) || (is_array($value) && empty($value))) { + // Create one field item and apply defaults. + $this->offsetGet(0)->applyDefaultValue(FALSE); + } + else { + $this->setValue($value, $notify); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function preSave() { + // Filter out empty items. + $this->filterEmptyValues(); + + $this->delegateMethod('presave'); + } + + /** + * {@inheritdoc} + */ + public function insert() { + $this->delegateMethod('insert'); + } + + /** + * {@inheritdoc} + */ + public function update() { + $this->delegateMethod('update'); + } + + /** + * {@inheritdoc} + */ + public function delete() { + $this->delegateMethod('delete'); + } + + /** + * {@inheritdoc} + */ + public function deleteRevision() { + $this->delegateMethod('deleteRevision'); + } + + /** + * Calls a method on each FieldItem. + * + * @param string $method + * The name of the method. + */ + protected function delegateMethod($method) { + if (isset($this->list)) { + foreach ($this->list as $item) { + $item->{$method}(); + } + } + } } diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/IntegerItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/IntegerItem.php index 6bd8cf8..29cbe40 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/IntegerItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/IntegerItem.php @@ -18,7 +18,7 @@ * id = "integer_field", * label = @Translation("Integer field item"), * description = @Translation("An entity field containing an integer value."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class IntegerItem extends FieldItemBase { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageItem.php index b156a34..42f12a1 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageItem.php @@ -19,7 +19,7 @@ * id = "language_field", * label = @Translation("Language field item"), * description = @Translation("An entity field referencing a language."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList", + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList", * constraints = { * "ComplexData" = { * "value" = {"Length" = {"max" = 12}} diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/StringItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/StringItem.php index a243567..572cc86 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/StringItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/StringItem.php @@ -18,7 +18,7 @@ * id = "string_field", * label = @Translation("String field item"), * description = @Translation("An entity field containing a string value."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class StringItem extends FieldItemBase { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/UriItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/UriItem.php index 6ce5970..3e3ae0a 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/UriItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/UriItem.php @@ -18,7 +18,7 @@ * id = "uri_field", * label = @Translation("URI field item"), * description = @Translation("An entity field containing a URI."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class UriItem extends FieldItemBase { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/UuidItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/UuidItem.php index 3e28741..3b0b2a6 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/UuidItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/UuidItem.php @@ -19,7 +19,7 @@ * id = "uuid_field", * label = @Translation("UUID field item"), * description = @Translation("An entity field containing a UUID."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList", + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList", * constraints = { * "ComplexData" = { * "value" = {"Length" = {"max" = 128}} diff --git a/core/lib/Drupal/Core/TypedData/DataDefinition.php b/core/lib/Drupal/Core/TypedData/DataDefinition.php index e7016c7..0bb3ee5 100644 --- a/core/lib/Drupal/Core/TypedData/DataDefinition.php +++ b/core/lib/Drupal/Core/TypedData/DataDefinition.php @@ -20,6 +20,16 @@ class DataDefinition implements DataDefinitionInterface, \ArrayAccess { protected $definition = array(); /** + * Creates a new data definition. + * + * @return \Drupal\Core\TypedData\DataDefinition + */ + public static function create() { + $class = get_called_class(); + return new $class(); + } + + /** * Constructs a new data definition object. * * @param array $definition @@ -334,7 +344,9 @@ public static function createFromOldStyleDefinition(array $definition) { } } - // Take care of the item definition. + // Take care of the item definition now. 'required' applies to the list + // definition. + unset($definition['required']); $item_definition = new DataDefinition($definition); if (isset($definition['settings'])) { $item_definition->setSettings($definition['settings']); diff --git a/core/lib/Drupal/Core/TypedData/ListDefinition.php b/core/lib/Drupal/Core/TypedData/ListDefinition.php index fc6b557..d192e84 100644 --- a/core/lib/Drupal/Core/TypedData/ListDefinition.php +++ b/core/lib/Drupal/Core/TypedData/ListDefinition.php @@ -20,6 +20,16 @@ class ListDefinition extends DataDefinition implements ListDefinitionInterface { protected $itemDefinition; /** + * Creates a new list definition. + * + * @return \Drupal\Core\TypedData\ListDefinition + */ + public static function create() { + $class = get_called_class(); + return new $class(); + } + + /** * {@inheritdoc} */ public function __construct(array $definition = array()) { diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php index 5bb8b90..e7dca89 100644 --- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php @@ -101,18 +101,6 @@ public function getString() { } /** - * Overrides \Drupal\Core\TypedData\TypedData::getConstraints(). - */ - public function getConstraints() { - if (isset($this->definition['item_definition']) && isset($this->definition['constraints'])) { - return $this->definition['constraints']; - } - // BC: If no item definition is specified, we apply possibly specified - // constraints to the list items only. - return array(); - } - - /** * Implements \ArrayAccess::offsetExists(). */ public function offsetExists($offset) { diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index 107ad2f..0850e37 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -314,17 +314,19 @@ public function getValidationConstraintManager() { * @see \Drupal\Core\Validation\ConstraintManager * * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition - * A data definition array. + * A data definition. * * @return array * Array of constraints, each being an instance of * \Symfony\Component\Validator\Constraint. + * + * @todo: Having this as well as $definition->getConstraints() is confusing. */ - public function getConstraints($definition) { + public function getConstraints(DataDefinitionInterface $definition) { $constraints = array(); $validation_manager = $this->getValidationConstraintManager(); - $type_definition = $this->getDefinition($definition['type']); + $type_definition = $this->getDefinition($definition->getDataType()); // Auto-generate a constraint for data types implementing a primitive // interface. if (is_subclass_of($type_definition['class'], '\Drupal\Core\TypedData\PrimitiveInterface')) { @@ -341,19 +343,21 @@ public function getConstraints($definition) { } } // Add any constraints specified as part of the data definition. - if (isset($definition['constraints'])) { - foreach ($definition['constraints'] as $name => $options) { - $constraints[] = $validation_manager->create($name, $options); - } + $defined_constraints = $definition->getConstraints(); + foreach ($defined_constraints as $name => $options) { + $constraints[] = $validation_manager->create($name, $options); } // Add the NotNull constraint for required data. - if (!empty($definition['required']) && empty($definition['constraints']['NotNull'])) { + if ($definition->isRequired() && !isset($defined_constraints['NotNull'])) { $constraints[] = $validation_manager->create('NotNull', array()); } // If the definition does not provide a class use the class from the type // definition for performing interface checks. - $class = isset($definition['class']) ? $definition['class'] : $type_definition['class']; + $class = $definition->getClass(); + if (!$class) { + $class = $type_definition['class']; + } // Check if the class provides allowed values. if (array_key_exists('Drupal\Core\TypedData\AllowedValuesInterface', class_implements($class))) { $constraints[] = $validation_manager->create('AllowedValues', array()); diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemList.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemList.php index 90555cf..1a2a6d0 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemList.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemList.php @@ -7,9 +7,8 @@ namespace Drupal\field\Plugin\Type\FieldType; -use Drupal\Core\TypedData\DataDefinitionInterface; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\Core\Entity\Field\FieldItemList; +use Drupal\Core\Entity\Plugin\DataType\FieldItemList; use Drupal\field\Field as FieldAPI; /** diff --git a/core/modules/path/lib/Drupal/path/Plugin/DataType/PathItem.php b/core/modules/path/lib/Drupal/path/Plugin/DataType/PathItem.php index 11059b5..7a0f9fe 100644 --- a/core/modules/path/lib/Drupal/path/Plugin/DataType/PathItem.php +++ b/core/modules/path/lib/Drupal/path/Plugin/DataType/PathItem.php @@ -18,7 +18,7 @@ * id = "path_field", * label = @Translation("Path field item"), * description = @Translation("An entity field containing a path alias and related data."), - * list_class = "\Drupal\Core\Entity\Field\FieldItemList" + * list_class = "\Drupal\Core\Entity\Plugin\DataType\FieldItemList" * ) */ class PathItem extends FieldItemBase { diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php index 066e8f2..ed707fa 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php @@ -11,7 +11,9 @@ use Drupal\Core\Entity\Annotation\EntityType; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Entity\Field\FieldDefinition; use Drupal\Core\Language\Language; +use Drupal\Core\TypedData\DataDefinition; use Drupal\taxonomy\TermInterface; /** @@ -203,67 +205,66 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $ * {@inheritdoc} */ public static function baseFieldDefinitions($entity_type) { - $properties['tid'] = array( - 'label' => t('Term ID'), - 'description' => t('The term ID.'), - 'type' => 'integer_field', - 'read-only' => TRUE, - ); - $properties['uuid'] = array( - 'label' => t('UUID'), - 'description' => t('The term UUID.'), - 'type' => 'uuid_field', - 'read-only' => TRUE, - ); - $properties['vid'] = array( - 'label' => t('Vocabulary ID'), - 'description' => t('The ID of the vocabulary to which the term is assigned.'), - 'type' => 'string_field', - ); - $properties['langcode'] = array( - 'label' => t('Language code'), - 'description' => t('The term language code.'), - 'type' => 'language_field', - ); - $properties['name'] = array( - 'label' => t('Name'), - 'description' => t('The term name.'), - 'type' => 'string_field', - ); - $properties['description'] = array( - 'label' => t('Description'), - 'description' => t('A description of the term'), - 'type' => 'string_field', - ); + + $fields['tid'] = FieldDefinition::create() + ->setLabel(t('Term ID')) + ->setDescription(t('The term ID.')) + ->setFieldType('integer') + ->setReadOnly(TRUE); + + $fields['uuid'] = FieldDefinition::create() + ->setLabel(t('UUID')) + ->setDescription(t('The term UUID.')) + ->setFieldType('uuid') + ->setReadOnly(TRUE); + + $fields['vid'] = FieldDefinition::create() + ->setLabel(t('Vocabulary ID')) + ->setDescription(t('The ID of the vocabulary to which the term is assigned.')) + ->setFieldType('string'); + + $fields['langcode'] = FieldDefinition::create() + ->setLabel(t('Language code')) + ->setDescription(t('The term language code.')) + ->setFieldType('language'); + + $fields['name'] = FieldDefinition::create() + ->setLabel(t('Name')) + ->setDescription(t('The term name.')) + ->setFieldType('string'); + + $fields['description'] = FieldDefinition::create() + ->setLabel(t('Description')) + ->setDescription(t('A description of the term.')) + ->setFieldType('string'); + // @todo Combine with description. - $properties['format'] = array( - 'label' => t('Description format'), - 'description' => t('The filter format ID of the description.'), - 'type' => 'string_field', - ); - $properties['weight'] = array( - 'label' => t('Weight'), - 'description' => t('The weight of this term in relation to other terms.'), - 'type' => 'integer_field', - 'settings' => array('default_value' => 0), - ); - $properties['parent'] = array( - 'label' => t('Term Parents'), - 'description' => t('The parents of this term.'), - 'type' => 'integer_field', + $fields['format'] = FieldDefinition::create() + ->setLabel(t('Description format')) + ->setDescription(t('The filter format ID of the description.')) + ->setFieldType('string'); + + $fields['weight'] = FieldDefinition::create() + ->setLabel(t('Weight')) + ->setDescription(t('The weight of this term in relation to other terms.')) + ->setFieldType('integer') + ->setFieldSetting('default_value', 0); + + $fields['parent'] = FieldDefinition::create() + ->setLabel(t('Term Parents')) + ->setDescription(t('The parents of this term.')) + ->setFieldType('integer') // Save new terms with no parents by default. - 'settings' => array('default_value' => 0), - 'computed' => TRUE, - ); - $properties['changed'] = array( - 'label' => t('Changed'), - 'description' => t('The time that the term was last edited.'), - 'type' => 'integer_field', - 'property_constraints' => array( - 'value' => array('EntityChanged' => array()), - ), - ); - return $properties; + ->setFieldSetting('default_value', 0) + ->setComputed(TRUE); + + $fields['changed'] = FieldDefinition::create() + ->setLabel(t('Changed')) + ->setDescription(t('The time that the term was last edited.')) + ->setFieldType('integer') + ->setPropertyConstraints('value', array('EntityChanged' => array())); + + return $fields; } /** diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php index eee8cc8..dd1fe8e 100644 --- a/core/modules/text/lib/Drupal/text/TextProcessed.php +++ b/core/modules/text/lib/Drupal/text/TextProcessed.php @@ -7,7 +7,6 @@ namespace Drupal\text; -use Drupal\Core\TypedData\DataDefinitionInterface; use Drupal\Core\TypedData\TypedDataInterface; use Drupal\Core\TypedData\TypedData; use Drupal\Core\TypedData\ReadOnlyException;