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 a95d886..6da0a17 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 @@ -7,6 +7,8 @@ namespace Drupal\field\Plugin\Type\FieldType; +use Drupal\Core\Entity\Plugin\DataType\EntityReferenceItem; +use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemInterface; use Drupal\field\FieldInterface; /** @@ -18,7 +20,7 @@ * Required settings (below the definition's 'settings' key) are: * - target_type: The entity type to reference. */ -class ConfigEntityReferenceItemBase extends ConfigFieldItemBase { +class ConfigEntityReferenceItemBase extends EntityReferenceItem implements ConfigFieldItemInterface { /** * Definitions of the contained properties. @@ -34,7 +36,7 @@ class ConfigEntityReferenceItemBase extends ConfigFieldItemBase { * * @var \Drupal\field\Plugin\Core\Entity\FieldInstance */ - public $instance; + protected $instance; /** * Returns the field instance definition. @@ -60,25 +62,8 @@ public function getPropertyDefinitions() { $key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : ''; if (!isset(static::$propertyDefinitions[$key])) { - static::$propertyDefinitions[$key]['target_id'] = array( - // @todo: Lookup the entity type's ID data type and use it here. - 'type' => 'integer', - 'label' => t('Entity ID'), - 'constraints' => array( - 'Range' => array('min' => 0), - ), - ); - static::$propertyDefinitions[$key]['entity'] = array( - 'type' => 'entity_reference', - 'constraints' => array( - 'EntityType' => $this->definition['settings']['target_type'], - ), - 'label' => t('Entity'), - 'description' => t('The referenced entity'), - // The entity object is computed out of the entity ID. - 'computed' => TRUE, - 'read-only' => FALSE, - ); + // Call the parent to define the target_id and entity properties. + parent::getPropertyDefinitions(); static::$propertyDefinitions[$key]['revision_id'] = array( // @todo: Lookup the entity type's ID data type and use it here. @@ -98,9 +83,6 @@ public function getPropertyDefinitions() { 'label' => t('Access'), 'computed' => TRUE, ); - if (isset($this->definition['settings']['target_bundle'])) { - static::$propertyDefinitions[$key]['entity']['constraints']['Bundle'] = $this->definition['settings']['target_bundle']; - } } return static::$propertyDefinitions[$key]; } @@ -188,62 +170,96 @@ protected function getLegacyCallback($hook) { /** * {@inheritdoc} + * + * Copied from \Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase, + * since we cannot extend it. */ - public function __get($name) { - $name = ($name == 'value') ? 'target_id' : $name; - return parent::__get($name); + public function defaultValuesForm(array &$form, array &$form_state) { + $entity = $this->getParent()->getParent(); + $items = $this->getParent(); + $widget = $this->defaultValueWidget($form_state); + + $element = array('#parents' => array('default_value_input')); + $element += $widget->form($entity, $entity->language()->id, $items, $element, $form_state); + + return $element; } /** * {@inheritdoc} + * + * Copied from \Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase, + * since we cannot extend it. */ - public function get($property_name) { - $property_name = ($property_name == 'value') ? 'target_id' : $property_name; - return parent::get($property_name); + public function defaultValuesFormValidate(array $element, array &$form, array &$form_state) { + $entity = $this->getParent()->getParent(); + $items = $this->getParent(); + $widget = $this->defaultValueWidget($form_state); + + // Extract the 'default value'. + $widget->extractFormValues($entity, $entity->language()->id, $items, $element, $form_state); + $violations = $items->validate(); + + if (count($violations)) { + // Store reported errors in $form_state. + $field_name = $this->getFieldDefinition()->getFieldName(); + $field_state = field_form_get_state($element['#parents'], $field_name, $entity->language()->id, $form_state); + $field_state['constraint_violations'] = $violations; + field_form_set_state($element['#parents'], $field_name, $entity->language()->id, $form_state, $field_state); + + // Assign reported errors to the correct form element. + $widget->flagErrors($entity, $entity->language()->id, $this->getParent(), $element, $form_state); + } } /** * {@inheritdoc} + * + * Copied from \Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase, + * since we cannot extend it. */ - public function __isset($property_name) { - $property_name = ($property_name == 'value') ? 'target_id' : $property_name; - return parent::__isset($property_name); + public function defaultValuesFormSubmit(array $element, array &$form, array &$form_state) { + $entity = $this->getParent()->getParent(); + $items = $this->getParent(); + $widget = $this->defaultValueWidget($form_state); + + // Extract the 'default value', and return it as an array. + $widget->extractFormValues($entity, $entity->language()->id, $items, $element, $form_state); + return $items->getValue(); } /** - * {@inheritdoc} + * Returns the widget object used in default value form. + * + * Copied from \Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase, + * since we cannot extend it. + * + * @param array $form_state + * The form_state array. + * + * @return \Drupal\field\Plugin\Type\Widget\WidgetInterface + * A Widget object. */ - public function setValue($values, $notify = TRUE) { - if (isset($values) && !is_array($values)) { - // Directly update the property instead of invoking the parent, so it can - // handle objects and IDs. - $this->properties['entity']->setValue($values, $notify); - // If notify was FALSE, ensure the target_id property gets synched. - if (!$notify) { - $this->set('target_id', $this->properties['entity']->getTargetIdentifier(), FALSE); - } - } - else { - // Make sure that the 'entity' property gets set as 'target_id'. - if (isset($values['target_id']) && !isset($values['entity'])) { - $values['entity'] = $values['target_id']; + protected function defaultValueWidget(array &$form_state) { + if (!isset($form_state['default_value_widget'])) { + $entity = $this->getParent()->getParent(); + + // Force a non-required widget. + $this->getFieldDefinition()->required = FALSE; + $this->getFieldDefinition()->description = ''; + + // Use the widget currently configured for the 'default' form mode, or + // fallback to the default widget for the field type. + $entity_form_display = entity_get_form_display($entity->entityType(), $entity->bundle(), 'default'); + $widget = $entity_form_display->getRenderer($this->getFieldDefinition()->getFieldName()); + if (!$widget) { + $widget = \Drupal::service('plugin.manager.field.widget')->getInstance(array('field_definition' => $this->getFieldDefinition())); } - parent::setValue($values, $notify); - } - } - /** - * {@inheritdoc} - */ - public function onChange($property_name) { - // Make sure that the target ID and the target property stay in sync. - if ($property_name == 'target_id') { - $this->properties['entity']->setValue($this->target_id, FALSE); + $form_state['default_value_widget'] = $widget; } - elseif ($property_name == 'entity') { - $this->set('target_id', $this->properties['entity']->getTargetIdentifier(), FALSE); - } - parent::onChange($property_name); + + return $form_state['default_value_widget']; } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php index 01ba99a..6a9b286 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php @@ -8,7 +8,6 @@ namespace Drupal\field\Plugin\Type\FieldType; use Drupal\Core\Entity\Field\FieldItemBase; -use Drupal\Core\Language\Language; /** * Base class for 'configurable field type' plugin implementations. @@ -51,31 +50,13 @@ public function instanceSettingsForm(array $form, array &$form_state) { */ public function defaultValuesForm(array &$form, array &$form_state) { $entity = $this->getParent()->getParent(); - $default_value = $this->getFieldDefinition()->default_value; - $field_name = $this->getFieldDefinition()->getFieldName(); + $items = $this->getParent(); $widget = $this->defaultValueWidget($form_state); - $this->getFieldDefinition()->required = 0; + $element = array('#parents' => array('default_value_input')); + $element += $widget->form($entity, $entity->language()->id, $items, $element, $form_state); - // Insert the widget. Since we do not use the "official" instance definition, - // the whole flow cannot use field_invoke_method(). - $items = $entity->getNGEntity()->{$field_name}; - if (!empty($default_value)) { - $items->setValue($default_value); - } - - $element = array( - '#type' => 'details', - '#title' => t('Default value'), - '#tree' => TRUE, - '#description' => t('The default value for this field, used when creating new content.'), - // Stick to an empty 'parents' on this form in order not to breaks widgets - // that do not use field_widget_[field|instance]() and still access - // $form_state['field'] directly. - '#parents' => array(), - ); - - return $element += $widget->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + return $element; } /** @@ -83,38 +64,36 @@ public function defaultValuesForm(array &$form, array &$form_state) { */ public function defaultValuesFormValidate(array $element, array &$form, array &$form_state) { $entity = $this->getParent()->getParent(); + $items = $this->getParent(); $widget = $this->defaultValueWidget($form_state); - $field_name = $this->getFieldDefinition()->getFieldName(); // Extract the 'default value'. - $items = $entity->getNGEntity()->{$field_name}; - $widget->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + $widget->extractFormValues($entity, $entity->language()->id, $items, $element, $form_state); $violations = $items->validate(); - // Report errors. if (count($violations)) { - $field_state = field_form_get_state($element['#parents'], $field_name, Language::LANGCODE_NOT_SPECIFIED, $form_state); // Store reported errors in $form_state. + $field_name = $this->getFieldDefinition()->getFieldName(); + $field_state = field_form_get_state($element['#parents'], $field_name, $entity->language()->id, $form_state); $field_state['constraint_violations'] = $violations; - field_form_set_state($element['#parents'], $field_name, Language::LANGCODE_NOT_SPECIFIED, $form_state, $field_state); + field_form_set_state($element['#parents'], $field_name, $entity->language()->id, $form_state, $field_state); // Assign reported errors to the correct form element. - $widget->flagErrors($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + $widget->flagErrors($entity, $entity->language()->id, $this->getParent(), $element, $form_state); } } + /** * {@inheritdoc} */ public function defaultValuesFormSubmit(array $element, array &$form, array &$form_state) { $entity = $this->getParent()->getParent(); + $items = $this->getParent(); $widget = $this->defaultValueWidget($form_state); - $field_name = $this->getFieldDefinition()->getFieldName(); - - // Extract field values. - $items = $entity->getNGEntity()->{$field_name}; - $widget->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); - return $items->getValue() ?: NULL; + // Extract the 'default value', and return it as an array. + $widget->extractFormValues($entity, $entity->language()->id, $items, $element, $form_state); + return $items->getValue(); } /** @@ -128,16 +107,20 @@ public function defaultValuesFormSubmit(array $element, array &$form, array &$fo */ protected function defaultValueWidget(array &$form_state) { if (!isset($form_state['default_value_widget'])) { - $field_name = $this->getFieldDefinition()->getFieldName(); $entity = $this->getParent()->getParent(); - $entity_form_display = entity_get_form_display($entity->entityType(), $entity->bundle(), 'default'); - // Use the widget currently configured for the 'default' form mode, - // or fallback to the default widget for the field type. - $widget = $entity_form_display->getRenderer($field_name); + // Force a non-required widget. + $this->getFieldDefinition()->required = FALSE; + $this->getFieldDefinition()->description = ''; + + // Use the widget currently configured for the 'default' form mode, or + // fallback to the default widget for the field type. + $entity_form_display = entity_get_form_display($entity->entityType(), $entity->bundle(), 'default'); + $widget = $entity_form_display->getRenderer($this->getFieldDefinition()->getFieldName()); if (!$widget) { $widget = \Drupal::service('plugin.manager.field.widget')->getInstance(array('field_definition' => $this->getFieldDefinition())); } + $form_state['default_value_widget'] = $widget; } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php index 4c69088..0114b34 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php @@ -11,11 +11,8 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManager; use Drupal\Core\Entity\EntityNG; -use Drupal\Core\Entity\Field\FieldTypePluginManager; use Drupal\Core\Form\FormInterface; -use Drupal\Core\Language\Language; use Drupal\field\FieldInstanceInterface; -use Drupal\field\Plugin\Type\Widget\WidgetPluginManager; use Drupal\field_ui\FieldUI; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -84,6 +81,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac // Create an arbitrary entity object (used by the 'default value' widget). $ids = (object) array('entity_type' => $this->instance['entity_type'], 'bundle' => $this->instance['bundle'], 'entity_id' => NULL); $form['#entity'] = _field_create_entity_from_ids($ids); + $item = $this->getFieldItem($form['#entity'], $this->instance['field_name']); if (!empty($field['locked'])) { $form['locked'] = array( @@ -137,11 +135,18 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac ); // Add instance settings for the field type. - $form['instance']['settings'] = $this->getFieldItem($form['#entity'], $this->instance['field_name'])->instanceSettingsForm($form, $form_state); + $form['instance']['settings'] = $item->instanceSettingsForm($form, $form_state); $form['instance']['settings']['#weight'] = 10; // Add handling for default value. - $form['instance']['default_value_widget'] = $this->getFieldItem($form['#entity'], $this->instance['field_name'])->defaultValuesForm($form, $form_state); + if ($element = $item->defaultValuesForm($form, $form_state)) { + $element += array( + '#type' => 'details', + '#title' => t('Default value'), + '#description' => t('The default value for this field, used when creating new content.'), + ); + } + $form['instance']['default_value'] = $element; $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( @@ -160,7 +165,8 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac * {@inheritdoc} */ public function validateForm(array &$form, array &$form_state) { - $this->getFieldItem($form['#entity'], $this->instance['field_name'])->defaultValuesFormValidate($form['instance']['default_value_widget'], $form, $form_state); + $item = $this->getFieldItem($form['#entity'], $this->instance['field_name']); + $item->defaultValuesFormValidate($form['instance']['default_value'], $form, $form_state); } /** @@ -168,7 +174,8 @@ public function validateForm(array &$form, array &$form_state) { */ public function submitForm(array &$form, array &$form_state) { // Handle the default value. - $this->instance['default_value'] = $this->getFieldItem($form['#entity'], $this->instance['field_name'])->defaultValuesFormSubmit($form['instance']['default_value_widget'], $form, $form_state); + $item = $this->getFieldItem($form['#entity'], $this->instance['field_name']); + $this->instance['default_value'] = $item->defaultValuesFormSubmit($form['instance']['default_value'], $form, $form_state); // Merge incoming values into the instance. foreach ($form_state['values']['instance'] as $key => $value) { @@ -212,7 +219,7 @@ protected function getFieldItem(EntityInterface $entity, $field_name) { } else { $definitions = \Drupal::entityManager()->getFieldDefinitions($entity->entityType(), $entity->bundle()); - $item = \Drupal::typedData()->create($definitions[$field_name], array(), $field_name, $entity)->offsetGet(0); + $item = \Drupal::typedData()->create($definitions[$field_name], $this->instance->default_value, $field_name, $entity)->offsetGet(0); } return $item; }