diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php index 15744c0..793bfd5 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php @@ -224,4 +224,10 @@ public function delete() { } */ public function deleteRevision() { } + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + return 'value'; + } } diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php index 39d4506..30ab806 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php @@ -136,4 +136,18 @@ public function delete(); */ public function deleteRevision(); + /** + * Returns the name of the main property, if any. + * + * Some field items consist mainly of one main property, e.g. the value + * of a text field or the @code target_id @endcode of an entity reference. + * If the field item has no main property, the method returns NULL. + * + * @return string|null + * The name of the value property, or NULL if there is none. + * + * @todo: Move this to ComplexDataInterface once we improved Typed data to do + * not enforce having all methods on the data objects. + */ + public function getMainPropertyName(); } diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php index 5654747..97af7da 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReferenceItem.php @@ -134,4 +134,11 @@ public function onChange($property_name) { } parent::onChange($property_name); } + + /** + * {@inheritdoc} + */ + public function getMainPropertyName() { + return 'target_id'; + } } diff --git a/core/lib/Drupal/Core/TypedData/AllowedValuesInterface.php b/core/lib/Drupal/Core/TypedData/AllowedValuesInterface.php index bc58989..52bdd76 100644 --- a/core/lib/Drupal/Core/TypedData/AllowedValuesInterface.php +++ b/core/lib/Drupal/Core/TypedData/AllowedValuesInterface.php @@ -24,6 +24,11 @@ * as structured options arrays that can be used in an Options widget such as a * select box or checkboxes. * + * Note that this interface is mostly applicable for primitive data values, but + * can be used on complex data structures if a (primitive) main property is + * specified. In that case, the allowed values and options apply to the main + * property only. + * * @see \Drupal\options\Plugin\field\widget\OptionsWidgetBase */ interface AllowedValuesInterface { diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index f12c31e..42e6008 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -378,7 +378,7 @@ public function getConstraints($definition) { // definition for performing interface checks. $class = isset($definition['class']) ? $definition['class'] : $type_definition['class']; // Check if the class provides allowed values. - if (array_key_exists('Drupal\Core\TypedData\AllowedValuesInterface', class_implements($class)) && array_key_exists('Drupal\Core\TypedData\PrimitiveInterface', class_implements($class))) { + if (is_subclass_of($class,'Drupal\Core\TypedData\AllowedValuesInterface')) { $constraints[] = $validation_manager->create('AllowedValues', array()); } diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraintValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraintValidator.php index 7ad2cfd..8a12414 100644 --- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraintValidator.php +++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraintValidator.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Validation\Plugin\Validation\Constraint; use Drupal\Core\TypedData\AllowedValuesInterface; +use Drupal\Core\TypedData\ComplexDataInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\ChoiceValidator; @@ -20,11 +21,21 @@ class AllowedValuesConstraintValidator extends ChoiceValidator { * {@inheritdoc} */ public function validate($value, Constraint $constraint) { - if ($this->context->getMetadata()->getTypedData() instanceof AllowedValuesInterface) { + $typed_data = $this->context->getMetadata()->getTypedData(); + + if ($typed_data instanceof AllowedValuesInterface) { $account = \Drupal::currentUser(); $allowed_values = $this->context->getMetadata()->getTypedData()->getSettableValues($account); $constraint->choices = $allowed_values; } + // If the data is complex, we have to validate its main property. + if ($typed_data instanceof ComplexDataInterface) { + $name = $typed_data->getMainPropertyName(); + if (!isset($name)) { + throw new \LogicException('Cannot validate allowed values for complex data without a main property.'); + } + $value = $typed_data->get($name)->getValue(); + } return parent::validate($value, $constraint); } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php index 30dd181..ac4c3d1 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php @@ -12,8 +12,8 @@ /** * A common base class for configurable entity reference fields. * - * Extends the Core 'entity_reference_field' entity field item with common methods - * used in general configurable entity reference field. + * Extends the Core 'entity_reference_field' entity field item with common + * methods used in general configurable entity reference field. * * Required settings (below the definition's 'settings' key) are: * - target_type: The entity type to reference. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php index 5568dfd..5a663b5 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php @@ -71,7 +71,7 @@ public function getSettableValues(AccountInterface $account = NULL) { public function getSettableOptions(AccountInterface $account = NULL) { $instance = $this->getFieldDefinition(); $entity = $this->getParent()->getParent(); - $function = $this->getFieldSetting('options_list_callback') ?: 'taxonomy_allowed_values'; + $function = $this->getFieldSetting('options_list_callback') ? $this->getFieldSetting('options_list_callback') : 'taxonomy_allowed_values'; return $function($instance, $entity); } @@ -149,32 +149,6 @@ public function instanceSettingsForm(array $form, array &$form_state) { } /** - * {@inheritdoc} - * - * Taxonomy field settings allow for either a single vocabulary ID, multiple - * vocabulary IDs, or sub-trees of a vocabulary to be specified as allowed - * values, although only the first of these is supported via the field UI. - * Confirm that terms entered as values meet at least one of these conditions. - */ - public function getConstraints() { - $constraint_manager = \Drupal::typedData()->getValidationConstraintManager(); - $constraints = parent::getConstraints(); - - $target_id = $this->get('target_id')->getValue(); - $instance = $this->getFieldDefinition(); - if (!empty($target_id) && $target_id != 'autocreate') { - $constraints[] = $constraint_manager->create('ComplexData', array( - 'target_id' => array( - 'AllowedValues' => array( - 'message' => t('%name: illegal value.', array('%name' => $instance['label'])), - ), - ), - )); - } - return $constraints; - } - - /** * Flattens an array of allowed values. * * @param array $array