diff --git a/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php b/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php deleted file mode 100644 index 4d8fbf9..0000000 --- a/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php +++ /dev/null @@ -1,63 +0,0 @@ -target_id; - if (!empty($target_id)) { - return FALSE; - } - // Allow auto-create entities. - if (empty($target_id) && ($entity = $this->get('entity')->getValue()) && $entity->isNew()) { - return FALSE; - } - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function getValue() { - $values = parent::getValue(); - - // If there is an unsaved entity, return it as part of the field item values - // to ensure idempotency of getValue() / setValue(). - if (empty($this->target_id) && !empty($this->entity)) { - $values['entity'] = $this->entity; - } - return $values; - } - - /** - * {@inheritdoc} - */ - public function preSave() { - $entity = $this->get('entity')->getValue(); - $target_id = $this->get('target_id')->getValue(); - - if (!$target_id && !empty($entity) && $entity->isNew()) { - $entity->save(); - $this->set('target_id', $entity->id()); - } - } - -} diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php index 3a776e2..31a7d8e 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -169,6 +169,20 @@ public function setValue($values, $notify = TRUE) { /** * {@inheritdoc} */ + public function getValue($include_computed = FALSE) { + $values = parent::getValue($include_computed); + + // If there is an unsaved entity, return it as part of the field item values + // to ensure idempotency of getValue() / setValue(). + if ($this->hasUnsavedEntity()) { + $values['entity'] = $this->entity; + } + return $values; + } + + /** + * {@inheritdoc} + */ public function onChange($property_name) { // Make sure that the target ID and the target property stay in sync. if ($property_name == 'target_id') { @@ -187,4 +201,44 @@ public function getMainPropertyName() { return 'target_id'; } + /** + * {@inheritdoc} + */ + public function isEmpty() { + // Avoid loading the entity by first checking the 'target_id'. + $target_id = $this->target_id; + if ($target_id !== NULL) { + return FALSE; + } + // Allow auto-create entities. + if ($this->hasUnsavedEntity()) { + return FALSE; + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function preSave() { + if ($this->hasUnsavedEntity()) { + $this->entity->save(); + $this->target_id = $this->entity->id(); + } + } + + /** + * Determines whether the item holds an unsaved entity. + * + * This is notably used for "autocreate" widgets, and more generally to + * support referencing freshly created entities (they will get saved + * automatically as the hosting entity gets saved). + * + * @return bool + * TRUE if the item holds an unsaved entity. + */ + public function hasUnsavedEntity() { + return $this->target_id === NULL && ($entity = $this->entity) && $entity->isNew(); + } + } diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php index 73cee86..c350955 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php @@ -8,12 +8,12 @@ namespace Drupal\entity_reference; use Drupal\Component\Utility\String; +use Drupal\Core\Field\ConfigFieldItemInterface; +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\AllowedValuesInterface; use Drupal\Core\TypedData\DataDefinition; -use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\Core\Field\ConfigEntityReferenceItemBase; -use Drupal\Core\Field\ConfigFieldItemInterface; use Drupal\Core\Validation\Plugin\Validation\Constraint\AllowedValuesConstraint; /** @@ -26,9 +26,8 @@ * - target_type: The entity type to reference. * * @see entity_reference_field_info_alter(). - * */ -class ConfigurableEntityReferenceItem extends ConfigEntityReferenceItemBase implements ConfigFieldItemInterface, AllowedValuesInterface { +class ConfigurableEntityReferenceItem extends EntityReferenceItem implements ConfigFieldItemInterface, AllowedValuesInterface { /** * {@inheritdoc} @@ -48,7 +47,7 @@ public function getPossibleOptions(AccountInterface $account = NULL) { * {@inheritdoc} */ public function getSettableValues(AccountInterface $account = NULL) { - // Flatten options firstly, because Settable Options may contain group + // Flatten options first, because "settable options" may contain group // arrays. $flatten_options = \Drupal::formBuilder()->flattenOptions($this->getSettableOptions($account)); return array_keys($flatten_options); diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php index 9c41b2a..05e7371 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php @@ -64,9 +64,10 @@ public function elementValidate($element, &$form_state, $form) { $value[] = array('target_id' => $match); } elseif ($auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1 || count($bundles) == 1)) { - // Auto-create item. see entity_reference_field_presave(). + // Auto-create item. See + // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave(). $value[] = array( - 'target_id' => 0, + 'target_id' => NULL, 'entity' => $this->createNewEntity($input, $element['#autocreate_uid']), ); } diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php index f0719fe..0898d68 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php @@ -8,7 +8,6 @@ namespace Drupal\entity_reference\Plugin\Field\FieldWidget; use Drupal\Core\Field\FieldItemListInterface; -use Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase; /** * Plugin implementation of the 'entity_reference autocomplete' widget. @@ -54,7 +53,7 @@ public function elementValidate($element, &$form_state, $form) { $auto_create = $this->getSelectionHandlerSetting('auto_create'); // If a value was entered into the autocomplete. - $value = ''; + $value = NULL; if (!empty($element['#value'])) { // Take "label (entity id)', match the id from parenthesis. // @todo: Lookup the entity type's ID data type and use it here. @@ -73,9 +72,10 @@ public function elementValidate($element, &$form_state, $form) { } if (!$value && $auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1)) { - // Auto-create item. see entity_reference_field_presave(). + // Auto-create item. See + // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave(). $value = array( - 'target_id' => 0, + 'target_id' => NULL, 'entity' => $this->createNewEntity($element['#value'], $element['#autocreate_uid']), // Keep the weight property. '_weight' => $element['#weight'], diff --git a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php index 9bb9dd0..886be52 100644 --- a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php +++ b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php @@ -197,13 +197,6 @@ public function instanceSettingsForm(array $form, array &$form_state) { } /** - * {@inheritdoc} - */ - public function isEmpty() { - return empty($this->target_id); - } - - /** * Form API callback * * Removes slashes from the beginning and end of the destination value and diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 1f5d8a5..e5f52ed 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -421,7 +421,7 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) { * * Transforms default image of image field from array into single value at save. */ -function image_entity_presave(EntityInterface $entity, $type) { +function image_entity_presave(EntityInterface $entity) { $field = FALSE; if ($entity instanceof FieldInstance) { $field = $entity->getField(); diff --git a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php index be20c66..849cec8 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php +++ b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php @@ -284,6 +284,8 @@ public function instanceSettingsForm(array $form, array &$form_state) { * {@inheritdoc} */ public function preSave() { + parent::preSave(); + $width = $this->width; $height = $this->height; diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php index b99024a..29beaf5 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php @@ -48,7 +48,7 @@ public function prepareView(array $entities_items) { $item->entity = $terms[$item->target_id]; } // Terms to be created are not in $terms, but are still legitimate. - elseif ($item->target_id === NULL && isset($item->entity)) { + elseif ($item->hasUnsavedEntity()) { // Leave the item in place. } // Otherwise, unset the instance value, since the term does not exist. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php index 98660eb..e183e05 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php @@ -7,9 +7,9 @@ namespace Drupal\taxonomy\Plugin\Field\FieldType; -use Drupal\Core\Field\ConfigEntityReferenceItemBase; use Drupal\Core\Field\ConfigFieldItemInterface; use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\AllowedValuesInterface; @@ -35,7 +35,7 @@ * list_class = "\Drupal\taxonomy\Plugin\Field\FieldType\TaxonomyTermReferenceFieldItemList" * ) */ -class TaxonomyTermReferenceItem extends ConfigEntityReferenceItemBase implements ConfigFieldItemInterface, AllowedValuesInterface { +class TaxonomyTermReferenceItem extends EntityReferenceItem implements ConfigFieldItemInterface, AllowedValuesInterface { /** * {@inheritdoc}