diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index e9808d2..e7a9992 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -10,6 +10,7 @@ use Drupal\Component\Plugin\PluginManagerBase; use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Entity\Field\FieldDefinition; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\LanguageManager; use Drupal\Core\Language\Language; @@ -456,15 +457,8 @@ public function getAdminRouteInfo($entity_type, $bundle) { * is passed, no bundle-specific fields are included. Defaults to NULL. * * @return array - * An array of field definitions of entity fields, keyed by field - * name. In addition to the typed data definition keys as described at - * \Drupal\Core\TypedData\TypedDataManager::create() the following keys are - * supported: - * - queryable: Whether the field is queryable via QueryInterface. - * Defaults to TRUE if 'computed' is FALSE or not set, to FALSE otherwise. - * - translatable: Whether the field is translatable. Defaults to FALSE. - * - configurable: A boolean indicating whether the field is configurable - * via field.module. Defaults to FALSE. + * An array of entity field definitions, keyed by field name. See + * \Drupal\Core\Entity\Field\FieldDefinitionInterface. * * @see \Drupal\Core\TypedData\TypedDataManager::create() * @see \Drupal\Core\Entity\EntityManager::getFieldDefinitionsByConstraints() @@ -477,6 +471,7 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) { $this->entityFieldInfo[$entity_type] = $cache->data; } else { + // @todo: Refactor to allow for per-bundle overrides. $class = $this->factory->getPluginClass($entity_type, $this->getDefinition($entity_type)); $this->entityFieldInfo[$entity_type] = array( 'definitions' => $class::baseFieldDefinitions($entity_type), @@ -496,12 +491,20 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) { $hooks = array('entity_field_info', $entity_type . '_field_info'); $this->moduleHandler->alter($hooks, $this->entityFieldInfo[$entity_type], $entity_type); - // Enforce fields to be multiple by default. - foreach ($this->entityFieldInfo[$entity_type]['definitions'] as &$definition) { - $definition['list'] = TRUE; + // Enforce field definitions to be objects. + foreach ($this->entityFieldInfo[$entity_type]['definitions'] as $field_name => &$definition) { + if (is_array($definition)) { + $definition = FieldDefinition::createFromOldStyleDefinition($definition); + } + // Make sure the field name is properly set. + $definition->setFieldName($field_name); } - foreach ($this->entityFieldInfo[$entity_type]['optional'] as &$definition) { - $definition['list'] = TRUE; + foreach ($this->entityFieldInfo[$entity_type]['optional'] as $field_name => &$definition) { + if (is_array($definition)) { + $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 ef79967..e46bc69 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php @@ -6,34 +6,40 @@ */ namespace Drupal\Core\Entity\Field; + use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\TypedData\ListDefinition; /** * A class for defining entity fields. */ -class FieldDefinition implements FieldDefinitionInterface { +class FieldDefinition extends ListDefinition implements FieldDefinitionInterface, \ArrayAccess { /** - * The array holding values for all definition keys. + * Creates a new entity field definition. * - * @var array + * @return \Drupal\Core\Entity\Field\FieldDefinition */ - protected $definition = array(); + public static function create() { + $class = get_called_class(); + return new $class(); + } /** - * Constructs a new FieldDefinition object. - * - * @param array $definition - * (optional) If given, a definition represented as array. + * {@inheritdoc} */ public function __construct(array $definition = array()) { - $this->definition = $definition; + parent::__construct($definition); + // Set a default list type to use. + $this->setDataType('entity_field'); } /** * {@inheritdoc} */ public function getFieldName() { + // @todo: Should "name" be part of the data definition also? return $this->definition['field_name']; } @@ -55,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->definition['type']); - 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); + } } /** @@ -70,43 +85,68 @@ public function getFieldType() { * The object itself for chaining. */ public function setFieldType($type) { - $this->definition['type'] = '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; } /** - * Sets a field setting. + * {@inheritdoc} + */ + public function getFieldSettings() { + return $this->getItemDefinition()->getSettings(); + } + + /** + * Sets field settings. * - * @param string $type - * The field type to set. + * @param array $settings + * The value to set. * * @return \Drupal\Core\Entity\Field\FieldDefinition * The object itself for chaining. */ - public function setFieldSetting($setting_name, $value) { - $this->definition['settings'][$setting_name] = $value; + public function setFieldSettings(array $settings) { + $this->getItemDefinition()->setSettings($settings); return $this; } /** * {@inheritdoc} */ - public function getFieldSettings() { - return $this->definition['settings']; + public function getFieldSetting($setting_name) { + $settings = $this->getFieldSettings(); + return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL; } /** - * {@inheritdoc} + * Sets a field setting. + * + * @param string $setting_name + * The field setting to set. + * @param mixed $value + * The value to set. + * + * @return \Drupal\Core\Entity\Field\FieldDefinition + * The object itself for chaining. */ - public function getFieldSetting($setting_name) { - return isset($this->definition['settings'][$setting_name]) ? $this->definition['settings'][$setting_name] : NULL; + public function setFieldSetting($setting_name, $value) { + $settings = $this->getFieldSettings(); + $settings[$setting_name] = $value; + return $this->setFieldSettings($settings); } /** * {@inheritdoc} */ public function getFieldPropertyNames() { - return array_keys(\Drupal::typedData()->create($this->definition['type'])->getPropertyDefinitions()); + return array_keys(\Drupal::typedData()->create($this->getItemDefinition())->getPropertyDefinitions()); } /** @@ -134,42 +174,28 @@ public function setTranslatable($translatable) { * {@inheritdoc} */ public function getFieldLabel() { - return $this->definition['label']; + return $this->getLabel(); } /** - * Sets the field label. - * - * @param string $label - * The field label to set. - * - * @return \Drupal\Core\Entity\Field\FieldDefinition - * The object itself for chaining. + * {@inheritdoc} */ public function setFieldLabel($label) { - $this->definition['label'] = $label; - return $this; + return $this->setLabel($label); } /** * {@inheritdoc} */ public function getFieldDescription() { - return $this->definition['description']; + return $this->getDescription(); } /** - * Sets the field label. - * - * @param string $description - * The field label to set. - * - * @return \Drupal\Core\Entity\Field\FieldDefinition - * The object itself for chaining. + * {@inheritdoc} */ public function setFieldDescription($description) { - $this->definition['description'] = $description; - return $this; + return $this->setDescription($description); } /** @@ -184,21 +210,40 @@ public function getFieldCardinality() { * {@inheritdoc} */ public function isFieldRequired() { - return !empty($this->definition['required']); + return $this->isRequired(); } /** * Sets whether the field is required. * - * @param bool $required - * TRUE if the field is required, FALSE otherwise. + * @param boolean $required + * Whether the field is required. * * @return \Drupal\Core\Entity\Field\FieldDefinition * The object itself for chaining. */ public function setFieldRequired($required) { - $this->definition['required'] = $required; - return $this; + return $this->setRequired($required); + } + + /** + * {@inheritdoc} + */ + public function isFieldQueryable() { + return isset($this->definition['queryable']) ? $this->definition['queryable'] : !$this->isComputed(); + } + + /** + * Sets whether the field is queryable. + * + * @param boolean $queryable + * Whether the field is queryable. + * + * @return \Drupal\Core\Entity\Field\FieldDefinition + * The object itself for chaining. + */ + public function setFieldQueryable($queryable) { + return $this->setRequired($queryable); } /** @@ -213,7 +258,9 @@ public function setFieldRequired($required) { * The object itself for chaining. */ public function setPropertyConstraints($name, array $constraints) { - $this->definition['item_definition']['constraints']['ComplexData'][$name] = $constraints; + $item_constraints = $this->getItemDefinition()->getConstraints(); + $item_constraints['ComplexData'][$name] = $constraints; + $this->getItemDefinition()->setConstraints($item_constraints); return $this; } @@ -231,4 +278,72 @@ public function getFieldDefaultValue(EntityInterface $entity) { return $this->getFieldSetting('default_value'); } + /** + * Allows creating field definition objects from old style definition arrays. + * + * @todo: Remove once no old-style definition arrays need to be supported. + */ + public static function createFromOldStyleDefinition(array $definition) { + unset($definition['list']); + + // Separate the list item definition from the list definition. + $list_definition = $definition; + $list_definition['type'] = 'entity_field'; + + // Constraints and settings apply to the list item. + unset($list_definition['constraints']); + unset($list_definition['settings']); + + $field_definition = new FieldDefinition($list_definition); + if (isset($definition['list_class'])) { + $field_definition->setClass($definition['list_class']); + } + else { + $type_definition = \Drupal::typedData()->getDefinition($definition['type']); + if (isset($type_definition['list_class'])) { + $field_definition->setClass($type_definition['list_class']); + } + } + + // 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']); + } + if (isset($definition['constraints'])) { + $item_definition->setConstraints($definition['constraints']); + } + $field_definition->setItemDefinition($item_definition); + return $field_definition; + } + + /** + * {@inheritdoc} + */ + public function &offsetGet($offset) { + if ($offset == 'type') { + // What previously was "type" is now the type of the list item. + $type = &$this->itemDefinition->offsetGet('type'); + return $type; + } + if (!isset($this->definition[$offset])) { + $this->definition[$offset] = NULL; + } + return $this->definition[$offset]; + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value) { + if ($offset == 'type') { + // What previously was "type" is now the type of the list item. + $this->itemDefinition->setDataType($value); + } + else { + $this->definition[$offset] = $value; + } + } } diff --git a/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php index b8dc354..c2bc4ce 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php @@ -13,9 +13,10 @@ * Defines an interface for entity field definitions. * * An entity field is a data object that holds the values of a particular field - * for a particular entity (see \Drupal\Core\Entity\Field\FieldItemListInterface). For - * example, $node_1->body and $node_2->body contain different data and therefore - * are different field objects. + * for a particular entity (see + * \Drupal\Core\Entity\Field\FieldItemListInterface). For example, $node_1->body + * and $node_2->body contain different data and therefore are different field + * objects. * * In contrast, an entity field *definition* is an object that returns * information *about* a field (e.g., its type and settings) rather than its @@ -36,10 +37,9 @@ * * However, entity base fields, such as $node->title, are not managed by * field.module and its "field_entity"/"field_instance" configuration entities. - * Therefore, their definitions are provided by different objects that implement - * this interface. - * @todo That is still in progress: https://drupal.org/node/1949932. Update this - * documentation with details when that's implemented. + * Therefore, their definitions are provided by different objects based on the + * class \Drupal\Core\Entity\Field\FieldDefinition, which implements this + * interface as well. * * Field definitions may fully define a concrete data object (e.g., * $node_1->body), or may provide a best-guess definition for a data object that @@ -50,6 +50,8 @@ * abstractly, and present Views configuration options to the administrator * based on that abstract definition, even though that abstract definition can * differ from the concrete definition of any particular node's body field. + * + * @todo Extends this from DataDefinitionInterface. */ interface FieldDefinitionInterface { @@ -129,6 +131,13 @@ public function isFieldTranslatable(); public function isFieldConfigurable(); /** + * Determines whether the field is queryable via QueryInterface. + * + * @return bool + */ + public function isFieldQueryable(); + + /** * Returns the human-readable label for the field. * * @return string diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php index 15744c0..d459c49 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php @@ -8,6 +8,8 @@ namespace Drupal\Core\Entity\Field; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\TypedData\DataDefinitionInterface; use Drupal\Core\TypedData\Plugin\DataType\Map; use Drupal\Core\TypedData\TypedDataInterface; use Drupal\user; @@ -23,9 +25,16 @@ abstract class FieldItemBase extends Map implements FieldItemInterface { /** + * The field's definition. + * + * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface + */ + protected $definition; + + /** * Overrides \Drupal\Core\TypedData\TypedData::__construct(). */ - public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { + public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); // Initialize computed properties by default, such that they get cloned // with the whole item. 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/Field/FieldItemList.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php similarity index 76% rename from core/lib/Drupal/Core/Entity/Field/FieldItemList.php rename to core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php index 4b4e1eb..561aa1d 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemList.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldItemList.php @@ -2,28 +2,32 @@ /** * @file - * Contains \Drupal\Core\Entity\Field\FieldItemList. + * Contains \Drupal\Core\Entity\Plugin\DataType\FieldItemList. */ -namespace Drupal\Core\Entity\Field; +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\ItemList; +use Drupal\Core\TypedData\Plugin\DataType\ItemList; use Drupal\Core\Language\Language; +use Drupal\Core\TypedData\Annotation\DataType; +use Drupal\Core\Annotation\Translation; /** - * Represents an entity field; that is, a list of field item objects. + * Defines a data type plugin for entity fields, i.e. the list of field items. * - * An entity field is a list of field items, which contain only primitive - * properties or entity references. Note that even single-valued entity - * fields are represented as list of items, however for easy access to the - * contained item the entity field delegates __get() and __set() calls - * directly to the first item. + * 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. * - * Supported settings (below the definition's 'settings' key) are: - * - default_value: (optional) If set, the default value to apply to the field. + * @DataType( + * id = "entity_field", + * label = @Translation("Entity field"), + * class = "\Drupal\Core\Entity\Field\Field" + * ) */ class FieldItemList extends ItemList implements FieldItemListInterface { @@ -45,7 +49,7 @@ class FieldItemList extends ItemList implements FieldItemListInterface { /** * Overrides TypedData::__construct(). */ - public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { + 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 @@ -80,7 +84,7 @@ public function getLangcode() { * {@inheritdoc} */ public function getFieldDefinition() { - return new FieldDefinition($this->definition); + return $this->definition; } /** @@ -109,7 +113,7 @@ public function getValue($include_computed = FALSE) { } /** - * Overrides \Drupal\Core\TypedData\ItemList::setValue(). + * Overrides \Drupal\Core\TypedData\Plugin\DataType\ItemList::setValue(). */ public function setValue($values, $notify = TRUE) { if (!isset($values) || $values === array()) { @@ -214,10 +218,8 @@ public function defaultAccess($operation = 'view', AccountInterface $account = N * {@inheritdoc} */ public function applyDefaultValue($notify = TRUE) { - // @todo Remove getDefaultValue() and directly call - // FieldDefinition::getFieldDefaultValue() here, once - // https://drupal.org/node/2047229 is fixed. - $value = $this->getDefaultValue(); + $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))) { @@ -231,33 +233,6 @@ public function applyDefaultValue($notify = TRUE) { } /** - * Returns the default value for the field. - * - * @return array - * The default value for the field. - */ - protected function getDefaultValue() { - if (isset($this->definition['settings']['default_value'])) { - return $this->definition['settings']['default_value']; - } - } - - /** - * {@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() { 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/Annotation/DataType.php b/core/lib/Drupal/Core/TypedData/Annotation/DataType.php index ec9ef6d..2769c55 100644 --- a/core/lib/Drupal/Core/TypedData/Annotation/DataType.php +++ b/core/lib/Drupal/Core/TypedData/Annotation/DataType.php @@ -62,14 +62,6 @@ class DataType extends Plugin { public $description; /** - * The typed data class used for wrapping multiple data items of the type. - * Must implement the \Drupal\Core\TypedData\ListInterface. - * - * @var string - */ - public $list_class = '\Drupal\Core\TypedData\ItemList'; - - /** * The pre-defined primitive type that this data type maps to. * * If set, it must be a constant defined by \Drupal\Core\TypedData\Primitive diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php index 8acfaa3..2e3d0e7 100644 --- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php @@ -105,10 +105,6 @@ public function getPropertyDefinition($name); /** * Gets an array of property definitions of contained properties. * - * @param array $definition - * The definition of the container's property, e.g. the definition of an - * entity reference property. - * * @return array * An array of property definitions of contained properties, keyed by * property name. diff --git a/core/lib/Drupal/Core/TypedData/DataDefinition.php b/core/lib/Drupal/Core/TypedData/DataDefinition.php new file mode 100644 index 0000000..0bb3ee5 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/DataDefinition.php @@ -0,0 +1,360 @@ +definition = $definition; + } + + /** + * {@inheritdoc} + */ + public function getDataType() { + return $this->definition['type']; + } + + /** + * Sets the data type. + * + * @param string $type + * The data type to set. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setDataType($type) { + $this->definition['type'] = $type; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getLabel() { + return isset($this->definition['label']) ? $this->definition['label'] : NULL; + } + + /** + * Sets the human-readable label. + * + * @param string $label + * The label to set. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setLabel($label) { + $this->definition['label'] = $label; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getDescription() { + return isset($this->definition['description']) ? $this->definition['description'] : NULL; + } + + /** + * Sets the human-readable description. + * + * @param string $description + * The description to set. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setDescription($description) { + $this->definition['description'] = $description; + return $this; + } + + /** + * {@inheritdoc} + */ + public function isList() { + return ($this instanceof ListDefinitionInterface); + } + + /** + * {@inheritdoc} + */ + public function isReadOnly() { + if (!isset($this->definition['read-only'])) { + // Default to read-only if the data value is computed. + return $this->isComputed(); + } + return $this->definition['read-only']; + } + + /** + * Sets whether the data is read-only. + * + * @param boolean $read-only + * Whether the data is read-only. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setReadOnly($read_only) { + $this->definition['read-only'] = $read_only; + return $this; + } + + /** + * {@inheritdoc} + */ + public function isComputed() { + return !empty($this->definition['computed']); + } + + /** + * Sets whether the data is computed. + * + * @param boolean $computed + * Whether the data is computed. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setComputed($computed) { + $this->definition['computed'] = $computed; + return $this; + } + + /** + * {@inheritdoc} + */ + public function isRequired() { + return !empty($this->definition['required']); + } + + /** + * Sets whether the data is required. + * + * @param boolean $required + * Whether the data is required. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setRequired($required) { + $this->definition['required'] = $required; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getClass() { + return isset($this->definition['class']) ? $this->definition['class'] : NULL; + } + + /** + * Sets the class used for creating the typed data object. + * + * @param string|null $class + * The class to use. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setClass($class) { + $this->definition['class'] = $class; + return $this; + } + + /** + * Returns the array of settings, as required by the used class. + * + * See the documentation of the class for supported or required settings. + * + * @return array + * The array of settings. + */ + public function getSettings() { + return isset($this->definition['settings']) ? $this->definition['settings'] : array(); + } + + /** + * Sets the array of settings, as required by the used class. + * + * @param array $settings + * The array of settings. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setSettings(array $settings) { + $this->definition['settings'] = $settings; + return $this; + } + + /** + * Returns an array of validation constraints. + * + * See \Drupal\Core\TypedData\TypedDataManager::getConstraints() for details. + * + * @return array + * Array of constraints, each being an instance of + * \Symfony\Component\Validator\Constraint. + */ + public function getConstraints() { + return isset($this->definition['constraints']) ? $this->definition['constraints'] : array(); + } + + /** + * Sets the array of validation constraints. + * + * See \Drupal\Core\TypedData\TypedDataManager::getConstraints() for details. + * + * @param array $constraints + * The array of constraints. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function setConstraints(array $constraints) { + $this->definition['constraints'] = $constraints; + return $this; + } + + /** + * Adds a validation constraint. + * + * See \Drupal\Core\TypedData\TypedDataManager::getConstraints() for details. + * + * @param string $constraint_name + * The name of the constraint to add, i.e. its plugin id. + * @param array|null $options + * The constraint options as required by the constraint plugin, or NULL. + * + * @return \Drupal\Core\TypedData\DataDefinition + * The object itself for chaining. + */ + public function addConstraint($constraint_name, $options = NULL) { + $this->definition['constraints'][$constraint_name] = $options; + return $this; + } + + /** + * {@inheritdoc} + */ + public function offsetExists($offset) { + // PHP's array access does not work correctly with isset(), so we have to + // bake isset() in here. See https://bugs.php.net/bug.php?id=41727. + return array_key_exists($offset, $this->definition) && isset($this->definition[$offset]); + } + + /** + * {@inheritdoc} + */ + public function &offsetGet($offset) { + if (!isset($this->definition[$offset])) { + $this->definition[$offset] = NULL; + } + return $this->definition[$offset]; + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value) { + $this->definition[$offset] = $value; + } + + /** + * {@inheritdoc} + */ + public function offsetUnset($offset) { + unset($this->definition[$offset]); + } + + /** + * Returns all definition values as array. + * + * @return array + */ + public function toArray() { + return $this->definition; + } + + /** + * Allows creating data definition objects from old style definition arrays. + * + * @todo: Remove once no old-style definition arrays need to be supported. + */ + public static function createFromOldStyleDefinition(array $definition) { + if (empty($definition['list'])) { + return new DataDefinition($definition); + } + + // If the definition describes a list, separate the list item definition + // from the list definition. + unset($definition['list']); + + $list_definition = $definition; + $list_definition['type'] = 'list'; + + // Constraints and settings apply to the list item. + unset($list_definition['constraints']); + unset($list_definition['settings']); + + $list_definition = new ListDefinition($list_definition); + if (isset($definition['list_class'])) { + $list_definition->setClass($definition['list_class']); + } + else { + $type_definition = \Drupal::typedData()->getDefinition($definition['type']); + if (isset($type_definition['list_class'])) { + $list_definition->setClass($type_definition['list_class']); + } + } + + // 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']); + } + if (isset($definition['constraints'])) { + $item_definition->setConstraints($definition['constraints']); + } + $list_definition->setItemDefinition($item_definition); + return $list_definition; + } +} diff --git a/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php b/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php new file mode 100644 index 0000000..d866d15 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php @@ -0,0 +1,115 @@ +itemDefinition = new DataDefinition(); + } + + /** + * {@inheritdoc} + */ + public function getItemDefinition() { + return $this->itemDefinition; + } + + /** + * Sets the item definition. + */ + public function setItemDefinition(DataDefinitionInterface $definition) { + $this->itemDefinition = $definition; + return $this; + } +} diff --git a/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php b/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php new file mode 100644 index 0000000..c07d60e --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/ListDefinitionInterface.php @@ -0,0 +1,26 @@ + FALSE) + $this->definition; + return $this->definition->getItemDefinition(); } /** diff --git a/core/lib/Drupal/Core/TypedData/TypedData.php b/core/lib/Drupal/Core/TypedData/TypedData.php index 031828a..6e021e1 100644 --- a/core/lib/Drupal/Core/TypedData/TypedData.php +++ b/core/lib/Drupal/Core/TypedData/TypedData.php @@ -20,7 +20,7 @@ /** * The data definition. * - * @var array + * @var \Drupal\Core\TypedData\DataDefinitionInterface */ protected $definition; @@ -41,7 +41,7 @@ /** * Constructs a TypedData object given its definition and context. * - * @param array $definition + * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition * The data definition. * @param string $name * (optional) The name of the created property, or NULL if it is the root @@ -52,7 +52,7 @@ * * @see \Drupal\Core\TypedData\TypedDataManager::create() */ - public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { + public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { $this->definition = $definition; $this->parent = $parent; $this->name = $name; diff --git a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php index bbdf4ea..bef5a36 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataInterface.php @@ -18,7 +18,9 @@ * Gets the data definition. * * @return array - * The data definition array. + * The data definition represented as array. + * + * @see \Drupal\Core\TypedData\DataDefinition */ public function getDefinition(); diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index bbc0d7f..0850e37 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -52,77 +52,48 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac } /** - * Implements \Drupal\Component\Plugin\PluginManagerInterface::createInstance(). + * Instantiates a typed data object. * - * @param string $plugin_id - * The id of a plugin, i.e. the data type. + * @param string $data_type + * The data type, for which a typed object should be instantiated. * @param array $configuration - * The plugin configuration, i.e. the data definition. - * @param string $name - * (optional) If a property or list item is to be created, the name of the - * property or the delta of the list item. - * @param mixed $parent - * (optional) If a property or list item is to be created, the parent typed - * data object implementing either the ListInterface or the - * ComplexDataInterface. + * The plugin configuration array, i.e. an array with the following keys: + * - data definition: The data definition object, i.e. an instance of + * \Drupal\Core\TypedData\DataDefinitionInterface. + * - name: (optional) If a property or list item is to be created, the name + * of the property or the delta of the list item. + * - parent: (optional) If a property or list item is to be created, the + * parent typed data object implementing either the ListInterface or the + * ComplexDataInterface. * * @return \Drupal\Core\TypedData\TypedDataInterface * The instantiated typed data object. */ - public function createInstance($plugin_id, array $configuration, $name = NULL, $parent = NULL) { - $type_definition = $this->getDefinition($plugin_id); + public function createInstance($data_type, array $configuration) { + $data_definition = $configuration['data_definition']; + $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' => $plugin_id))); + throw new \InvalidArgumentException(format_string('Invalid data type %plugin_id has been given.', array('%plugin_id' => $data_type))); } // Allow per-data definition overrides of the used classes, i.e. take over // classes specified in the data definition. - $key = empty($configuration['list']) ? 'class' : 'list_class'; - if (isset($configuration[$key])) { - $class = $configuration[$key]; - } - elseif (isset($type_definition[$key])) { - $class = $type_definition[$key]; - } + $class = $data_definition->getClass(); + $class = isset($class) ? $class : $type_definition['class']; if (!isset($class)) { - throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id)); + throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $data_type)); } - return new $class($configuration, $name, $parent); + return new $class($data_definition, $configuration['name'], $configuration['parent']); } /** * Creates a new typed data object instance. * - * @param array $definition - * The data definition array with the following array keys and values: - * - type: The data type of the data to wrap. Required. - * - label: A human readable label. - * - description: A human readable description. - * - list: Whether the data is multi-valued, i.e. a list of data items. - * Defaults to FALSE. - * - computed: A boolean specifying whether the data value is computed by - * the object, e.g. depending on some other values. - * - read-only: A boolean specifying whether the data is read-only. Defaults - * to TRUE for computed properties, to FALSE otherwise. - * - class: If set and 'list' is FALSE, the class to use for creating the - * typed data object; otherwise the default class of the data type will be - * used. - * - list_class: If set and 'list' is TRUE, the class to use for creating - * the typed data object; otherwise the default list class of the data - * type will be used. - * - settings: An array of settings, as required by the used 'class'. See - * the documentation of the class for supported or required settings. - * - list_settings: An array of settings as required by the used - * 'list_class'. See the documentation of the list class for support or - * required settings. - * - constraints: An array of validation constraints. See - * \Drupal\Core\TypedData\TypedDataManager::getConstraints() for details. - * - required: A boolean specifying whether a non-NULL value is mandatory. - * Further keys may be supported in certain usages, e.g. for further keys - * supported for entity field definitions see - * \Drupal\Core\Entity\StorageControllerInterface::getPropertyDefinitions(). + * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition + * The data definition of the typed data object. For backwards-compatibility + * an array representation of the data definition may be passed also. * @param mixed $value * (optional) The data value. If set, it has to match one of the supported * data type format as documented for the data type classes. @@ -147,14 +118,20 @@ public function createInstance($plugin_id, array $configuration, $name = NULL, $ * @see \Drupal\Core\TypedData\Plugin\DataType\Date * @see \Drupal\Core\TypedData\Plugin\DataType\Uri * @see \Drupal\Core\TypedData\Plugin\DataType\Binary - * @see \Drupal\Core\Entity\Field\EntityWrapper */ - public function create(array $definition, $value = NULL, $name = NULL, $parent = NULL) { - $wrapper = $this->createInstance($definition['type'], $definition, $name, $parent); + public function create($definition, $value = NULL, $name = NULL, $parent = NULL) { + if (is_array($definition)) { + $definition = DataDefinition::createFromOldStyleDefinition($definition); + } + $typed_data = $this->createInstance($definition->getDataType(), array( + 'data_definition' => $definition, + 'name' => $name, + 'parent' => $parent, + )); if (isset($value)) { - $wrapper->setValue($value, FALSE); + $typed_data->setValue($value, FALSE); } - return $wrapper; + return $typed_data; } /** @@ -336,18 +313,20 @@ public function getValidationConstraintManager() { * * @see \Drupal\Core\Validation\ConstraintManager * - * @param array $definition - * A data definition array. + * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition + * 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')) { @@ -364,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/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php index ba827e6..647188d 100644 --- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php +++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php @@ -19,6 +19,9 @@ class ValidReferenceConstraintValidator extends ConstraintValidator { * {@inheritdoc} */ public function validate($value, Constraint $constraint) { + if (!isset($value)) { + return; + } $id = $value->get('target_id')->getValue(); // '0' or NULL are considered valid empty references. if (empty($id)) { diff --git a/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php b/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php index c0f6123..d6954b9 100644 --- a/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php +++ b/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php @@ -29,7 +29,7 @@ class DateTimeComputed extends TypedData { /** * {@inheritdoc} */ - public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { + public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); if (!isset($definition['settings']['date source'])) { throw new \InvalidArgumentException("The definition's 'date source' key has to specify the name of the date property to be computed."); diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index 463f5cb..b09c9bc 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -649,6 +649,20 @@ public function hasData() { } /** + * {@inheritdoc} + */ + public function isFieldQueryable() { + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function isFieldConfigurable() { + return TRUE; + } + + /** * Implements the magic __sleep() method. * * Using the Serialize interface and serialize() / unserialize() methods @@ -669,11 +683,4 @@ public function __wakeup() { $this->__construct($values); } - /** - * {@inheritdoc} - */ - public function isFieldConfigurable() { - return TRUE; - } - } diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php index d038977..def3c42 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php @@ -614,7 +614,14 @@ public function isFieldConfigurable() { return TRUE; } - /* + /** + * {@inheritdoc} + */ + public function isFieldQueryable() { + return TRUE; + } + + /** * Implements the magic __sleep() method. * * Using the Serialize interface and serialize() / unserialize() methods 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 32bea80..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 @@ -8,7 +8,7 @@ namespace Drupal\field\Plugin\Type\FieldType; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\Core\Entity\Field\FieldItemList; +use Drupal\Core\Entity\Plugin\DataType\FieldItemList; use Drupal\field\Field as FieldAPI; /** @@ -26,7 +26,7 @@ class ConfigFieldItemList extends FieldItemList implements ConfigFieldItemListIn /** * {@inheritdoc} */ - public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { + public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); if (isset($definition['instance'])) { $this->instance = $definition['instance']; @@ -69,13 +69,6 @@ public function getConstraints() { /** * {@inheritdoc} */ - protected function getDefaultValue() { - return $this->getFieldDefinition()->getFieldDefaultValue($this->getEntity()); - } - - /** - * {@inheritdoc} - */ public function defaultValuesForm(array &$form, array &$form_state) { if (empty($this->getFieldDefinition()->default_value_function)) { // Place the input in a separate place in the submitted values tree. diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItemList.php b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItemList.php index 22cd8a0..5d20b0c 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItemList.php +++ b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItemList.php @@ -102,8 +102,8 @@ public function deleteRevision() { * The name of the hook, e.g. 'presave', 'validate'. */ protected function legacyCallback($hook, $args = array()) { - $definition = $this->getPluginDefinition(); - $module = $definition['provider']; + $type_definition = \Drupal::typedData()->getDefinition($this->getItemDefinition()->getDataType()); + $module = $type_definition['provider']; $callback = "{$module}_field_{$hook}"; if (function_exists($callback)) { // We need to remove the empty "prototype" item here. diff --git a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php index 5d6b200..4abf5d3 100644 --- a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php +++ b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php @@ -11,6 +11,7 @@ use Drupal\Core\TypedData\ContextAwareInterface; use Drupal\Core\Config\Schema\Element; use Drupal\Core\Config\Schema\ArrayElement; +use Drupal\Core\TypedData\DataDefinitionInterface; /** * Defines the locale configuration wrapper object. @@ -41,7 +42,7 @@ class LocaleTypedConfig extends Element { /** * Constructs a configuration wrapper object. * - * @param array $definition + * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition * The data definition. * @param string $name * The configuration object name. @@ -50,7 +51,7 @@ class LocaleTypedConfig extends Element { * @param \Drupal\locale\LocaleConfigManager $localeConfig; * The locale configuration manager object. */ - public function __construct(array $definition, $name, $langcode, \Drupal\locale\LocaleConfigManager $localeConfig) { + public function __construct($definition, $name, $langcode, \Drupal\locale\LocaleConfigManager $localeConfig) { parent::__construct($definition, $name); $this->langcode = $langcode; $this->localeConfig = $localeConfig; 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/serialization/tests/Drupal/serialization/Tests/Normalizer/ListNormalizerTest.php b/core/modules/serialization/tests/Drupal/serialization/Tests/Normalizer/ListNormalizerTest.php index 399d8c1..8704c7f 100644 --- a/core/modules/serialization/tests/Drupal/serialization/Tests/Normalizer/ListNormalizerTest.php +++ b/core/modules/serialization/tests/Drupal/serialization/Tests/Normalizer/ListNormalizerTest.php @@ -9,8 +9,7 @@ use Drupal\Tests\UnitTestCase; use Drupal\serialization\Normalizer\ListNormalizer; -use Drupal\Core\TypedData\ItemList; -use Drupal\Core\TypedData\Plugin\DataType\Integer; +use Drupal\Core\TypedData\Plugin\DataType\ItemList; /** * Tests the ListNormalizer class. 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 bbf0fd0..dd1fe8e 100644 --- a/core/modules/text/lib/Drupal/text/TextProcessed.php +++ b/core/modules/text/lib/Drupal/text/TextProcessed.php @@ -29,7 +29,7 @@ class TextProcessed extends TypedData { /** * Overrides TypedData::__construct(). */ - public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { + public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); if (!isset($definition['settings']['text source'])) {