X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FField%2FBaseFieldDefinition.php;h=0947bb132471d1c14ae8403d8ec0a368c2b14148;hb=refs%2Fheads%2Fd864;hp=c7bb23306d51a4616a05b9b1a56ab98255b39ef5;hpb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;p=yaffs-website diff --git a/web/core/lib/Drupal/Core/Field/BaseFieldDefinition.php b/web/core/lib/Drupal/Core/Field/BaseFieldDefinition.php index c7bb23306..0947bb132 100644 --- a/web/core/lib/Drupal/Core/Field/BaseFieldDefinition.php +++ b/web/core/lib/Drupal/Core/Field/BaseFieldDefinition.php @@ -15,6 +15,7 @@ use Drupal\Core\TypedData\OptionsProviderInterface; class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionInterface, FieldStorageDefinitionInterface, RequiredFieldStorageDefinitionInterface { use UnchangingCacheableDependencyTrait; + use FieldInputValueNormalizerTrait; /** * The field type. @@ -59,7 +60,6 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI $field_definition->itemDefinition = FieldItemDataDefinition::create($field_definition); // Create a definition for the items, and initialize it with the default // settings for the field type. - // @todo Cleanup in https://www.drupal.org/node/2116341. $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); $default_settings = $field_type_manager->getDefaultStorageSettings($type) + $field_type_manager->getDefaultFieldSettings($type); $field_definition->itemDefinition->setSettings($default_settings); @@ -89,7 +89,6 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI ->setLabel($definition->getLabel()) ->setName($definition->getName()) ->setProvider($definition->getProvider()) - ->setQueryable($definition->isQueryable()) ->setRevisionable($definition->isRevisionable()) ->setSettings($definition->getSettings()) ->setTargetEntityTypeId($definition->getTargetEntityTypeId()) @@ -234,7 +233,9 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI * {@inheritdoc} */ public function isRevisionable() { - return !empty($this->definition['revisionable']); + // Multi-valued base fields are always considered revisionable, just like + // configurable fields. + return !empty($this->definition['revisionable']) || $this->isMultiple(); } /** @@ -265,6 +266,10 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI * Possible values are positive integers or * FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED. * + * Note that if the entity type that this base field is attached to is + * revisionable and the field has a cardinality higher than 1, the field is + * considered revisionable by default. + * * @param int $cardinality * The field cardinality. * @@ -287,7 +292,8 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI * {@inheritdoc} */ public function isQueryable() { - return isset($this->definition['queryable']) ? $this->definition['queryable'] : !$this->isComputed(); + @trigger_error('BaseFieldDefinition::isQueryable() is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\Field\BaseFieldDefinition::hasCustomStorage(). See https://www.drupal.org/node/2856563.', E_USER_DEPRECATED); + return !$this->hasCustomStorage(); } /** @@ -298,8 +304,14 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI * * @return static * The object itself for chaining. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use + * \Drupal\Core\Field\BaseFieldDefinition::setCustomStorage() instead. + * + * @see https://www.drupal.org/node/2856563 */ public function setQueryable($queryable) { + @trigger_error('BaseFieldDefinition::setQueryable() is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\Field\BaseFieldDefinition::setCustomStorage(). See https://www.drupal.org/node/2856563.', E_USER_DEPRECATED); $this->definition['queryable'] = $queryable; return $this; } @@ -459,14 +471,7 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI else { $value = $this->getDefaultValueLiteral(); } - // Normalize into the "array keyed by delta" format. - if (isset($value) && !is_array($value)) { - $properties = $this->getPropertyNames(); - $property = reset($properties); - $value = [ - [$property => $value], - ]; - } + $value = $this->normalizeValue($value, $this->getMainPropertyName()); // Allow the field type to process default values. $field_item_list_class = $this->getClass(); return $field_item_list_class::processDefaultValue($value, $entity, $this); @@ -503,6 +508,79 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI return $this; } + /** + * Returns the initial value for the field. + * + * @return array + * The initial value for the field, as a numerically indexed array of items, + * each item being a property/value array (array() for no default value). + */ + public function getInitialValue() { + return $this->normalizeValue($this->definition['initial_value'], $this->getMainPropertyName()); + } + + /** + * Sets an initial value for the field. + * + * @param mixed $value + * The initial value for the field. This can be either: + * - a literal, in which case it will be assigned to the first property of + * the first item; + * - a numerically indexed array of items, each item being a property/value + * array; + * - a non-numerically indexed array, in which case the array is assumed to + * be a property/value array and used as the first item; + * - an empty array for no initial value. + * + * @return $this + */ + public function setInitialValue($value) { + // @todo Implement initial value support for multi-value fields in + // https://www.drupal.org/node/2883851. + if ($this->isMultiple()) { + throw new FieldException('Multi-value fields can not have an initial value.'); + } + + $this->definition['initial_value'] = $this->normalizeValue($value, $this->getMainPropertyName()); + return $this; + } + + /** + * Returns the name of the field that will be used for getting initial values. + * + * @return string|null + * The field name. + */ + public function getInitialValueFromField() { + return isset($this->definition['initial_value_from_field']) ? $this->definition['initial_value_from_field'] : NULL; + } + + /** + * Sets a field that will be used for getting initial values. + * + * @param string $field_name + * The name of the field that will be used for getting initial values. + * @param mixed $default_value + * (optional) The default value for the field, in case the inherited value + * is NULL. This can be either: + * - a literal, in which case it will be assigned to the first property of + * the first item; + * - a numerically indexed array of items, each item being a property/value + * array; + * - a non-numerically indexed array, in which case the array is assumed to + * be a property/value array and used as the first item; + * - an empty array for no initial value. + * If the field being added is required or an entity key, it is recommended + * to provide a default value. + * + * @return $this + */ + public function setInitialValueFromField($field_name, $default_value = NULL) { + $this->definition['initial_value_from_field'] = $field_name; + $this->setInitialValue($default_value); + return $this; + } + /** * {@inheritdoc} */ @@ -510,7 +588,7 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI // If the field item class implements the interface, create an orphaned // runtime item object, so that it can be used as the options provider // without modifying the entity being worked on. - if (is_subclass_of($this->getFieldItemClass(), OptionsProviderInterface::class)) { + if (is_subclass_of($this->getItemDefinition()->getClass(), OptionsProviderInterface::class)) { $items = $entity->get($this->getName()); return \Drupal::service('plugin.manager.field.field_type')->createFieldItem($items, 0); } @@ -535,7 +613,7 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI */ public function getPropertyDefinitions() { if (!isset($this->propertyDefinitions)) { - $class = $this->getFieldItemClass(); + $class = $this->getItemDefinition()->getClass(); $this->propertyDefinitions = $class::propertyDefinitions($this); } return $this->propertyDefinitions; @@ -552,17 +630,18 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI * {@inheritdoc} */ public function getMainPropertyName() { - $class = $this->getFieldItemClass(); + $class = $this->getItemDefinition()->getClass(); return $class::mainPropertyName(); } /** * Helper to retrieve the field item class. * - * @todo: Remove once getClass() adds in defaults. See - * https://www.drupal.org/node/2116341. + * @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use + * \Drupal\Core\TypedData\ListDataDefinition::getClass() instead. */ protected function getFieldItemClass() { + @trigger_error('BaseFieldDefinition::getFieldItemClass() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\TypedData\ListDataDefinition::getClass(). See https://www.drupal.org/node/2933964.', E_USER_DEPRECATED); if ($class = $this->getItemDefinition()->getClass()) { return $class; } @@ -579,7 +658,7 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI public function __sleep() { // Do not serialize the statically cached property definitions. $vars = get_object_vars($this); - unset($vars['propertyDefinitions']); + unset($vars['propertyDefinitions'], $vars['typedDataManager']); return array_keys($vars); } @@ -712,6 +791,39 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI return $this->getTargetEntityTypeId() . '-' . $this->getName(); } + /** + * {@inheritdoc} + */ + public function getUniqueIdentifier() { + // If we have a specified target bundle, we're dealing with a bundle base + // field definition, so we need to include it in the unique identifier. + if ($this->getTargetBundle()) { + return $this->getTargetEntityTypeId() . '-' . $this->getTargetBundle() . '-' . $this->getName(); + } + + return $this->getUniqueStorageIdentifier(); + } + + /** + * {@inheritdoc} + */ + public function isDeleted() { + return !empty($this->definition['deleted']); + } + + /** + * Sets whether the field storage is deleted. + * + * @param bool $deleted + * Whether the field storage is deleted. + * + * @return $this + */ + public function setDeleted($deleted) { + $this->definition['deleted'] = $deleted; + return $this; + } + /** * {@inheritdoc} */ @@ -749,4 +861,29 @@ class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionI return $this; } + /** + * Magic method: Implements a deep clone. + */ + public function __clone() { + parent::__clone(); + + // The itemDefinition (\Drupal\Core\Field\TypedData\FieldItemDataDefinition) + // has a property fieldDefinition, which is a recursive reference to the + // parent BaseFieldDefinition, therefore the reference to the old object has + // to be overwritten with a reference to the cloned one. + $this->itemDefinition->setFieldDefinition($this); + // Reset the static cache of the field property definitions in order to + // ensure that the clone will reference different field property definitions + // objects. + $this->propertyDefinitions = NULL; + } + + /** + * {@inheritdoc} + */ + public function isInternal() { + // All fields are not internal unless explicitly set. + return !empty($this->definition['internal']); + } + }