Verified Commit eb42a777 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #3345149 by lauriii, shoroshanska, ranjith_kumar_k_u, quietone,...

Issue #3345149 by lauriii, shoroshanska, ranjith_kumar_k_u, quietone, smustgrave, tim.plunkett, mlncn, drugan, narendraR: Extra Default value field when adding a field with an unlimited values

(cherry picked from commit 93a509c6)
parent 779f8cd2
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -350,13 +350,27 @@ protected function defaultValueWidget(FormStateInterface $form_state) {
      $definition->setRequired(FALSE);
      $definition->setDescription('');

      // Use the widget currently configured for the 'default' form mode, or
      // fallback to the default widget for the field type.
      /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $entity_form_display */
      $entity_form_display = \Drupal::service('entity_display.repository')
        ->getFormDisplay($entity->getEntityTypeId(), $entity->bundle());
      $widget = $entity_form_display->getRenderer($this->getFieldDefinition()->getName());
      if (!$widget) {
        $widget = \Drupal::service('plugin.manager.field.widget')->getInstance(['field_definition' => $this->getFieldDefinition()]);
      /** @var \Drupal\Core\Field\WidgetPluginManager $field_widget_plugin_manager */
      $field_widget_plugin_manager = \Drupal::service('plugin.manager.field.widget');

      // Use the widget currently configured for the 'default' form mode, or
      // fallback to the default widget for the field type.
      if (($configuration = $entity_form_display->getComponent($definition->getName())) && isset($configuration['type'])) {
        // Get the plugin instance manually to ensure an up-to-date field
        // definition is used.
        // @see \Drupal\Core\Entity\Entity\EntityFormDisplay::getRenderer
        $widget = $field_widget_plugin_manager->getInstance([
          'field_definition' => $definition,
          'form_mode' => $entity_form_display->getOriginalMode(),
          'prepare' => FALSE,
          'configuration' => $configuration,
        ]);
      }
      else {
        $widget = $field_widget_plugin_manager->getInstance(['field_definition' => $definition]);
      }

      $form_state->set('default_value_widget', $widget);
+4 −0
Original line number Diff line number Diff line
@@ -157,6 +157,10 @@ public function testEntityReferenceDefaultConfigValue() {
      'default_value_input[' . $field_name . '][1][target_id]' => $referenced_node_type2->label() . ' (' . $referenced_node_type2->id() . ')',
    ];
    $this->drupalGet('admin/structure/types/manage/reference_content/fields/node.reference_content.' . $field_name);
    $this->assertSession()->fieldExists("default_value_input[{$field_name}][0][target_id]");
    $this->assertSession()->fieldNotExists("default_value_input[{$field_name}][1][target_id]");
    $this->submitForm([], 'Add another item');
    $this->assertSession()->fieldExists("default_value_input[{$field_name}][1][target_id]");
    $this->submitForm($field_edit, 'Save settings');

    // Check that the field has a dependency on the default value.
+7 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ class FormTest extends FieldTestBase {
    'options',
    'entity_test',
    'locale',
    'field_ui',
  ];

  /**
@@ -75,6 +76,7 @@ protected function setUp(): void {
    $web_user = $this->drupalCreateUser([
      'view test entity',
      'administer entity_test content',
      'administer entity_test fields',
    ]);
    $this->drupalLogin($web_user);

@@ -271,6 +273,11 @@ public function testFieldFormUnlimited() {
      ->setComponent($field_name)
      ->save();

    // Verify that only one "Default value" field
    // exists on the Manage field display.
    $this->drupalGet("entity_test/structure/entity_test/fields/entity_test.entity_test.{$field_name}");
    $this->assertSession()->elementsCount('xpath', "//table[@id='field-unlimited-values']/tbody/tr//input[contains(@class, 'form-text')]", 1);

    // Display creation form -> 1 widget.
    $this->drupalGet('entity_test/add');
    $this->assertSession()->fieldValueEquals("{$field_name}[0][value]", '');
+36 −6
Original line number Diff line number Diff line
@@ -4,9 +4,13 @@

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
use Drupal\Core\Field\FieldFilteredMarkup;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\Core\Url;
use Drupal\field\FieldConfigInterface;
use Drupal\field_ui\FieldUI;
@@ -38,8 +42,10 @@ class FieldConfigEditForm extends EntityForm {
   *
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info service.
   * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typedDataManager
   *   The type data manger.
   */
  public function __construct(EntityTypeBundleInfoInterface $entity_type_bundle_info) {
  public function __construct(EntityTypeBundleInfoInterface $entity_type_bundle_info, protected TypedDataManagerInterface $typedDataManager) {
    $this->entityTypeBundleInfo = $entity_type_bundle_info;
  }

@@ -48,7 +54,8 @@ public function __construct(EntityTypeBundleInfoInterface $entity_type_bundle_in
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.bundle.info')
      $container->get('entity_type.bundle.info'),
      $container->get('typed_data_manager')
    );
  }

@@ -107,7 +114,7 @@ public function form(array $form, FormStateInterface $form_state) {
      'entity_id' => NULL,
    ];
    $form['#entity'] = _field_create_entity_from_ids($ids);
    $items = $form['#entity']->get($this->entity->getName());
    $items = $this->getTypedData($form['#entity']);
    $item = $items->first() ?: $items->appendItem();

    // Add field settings for the field type and a container for third party
@@ -122,6 +129,10 @@ public function form(array $form, FormStateInterface $form_state) {
      '#weight' => 11,
    ];

    // Create a new instance of typed data for the field to ensure that default
    // value widget is always rendered from a clean state.
    $items = $this->getTypedData($form['#entity']);

    // Add handling for default value.
    if ($element = $items->defaultValuesForm($form, $form_state)) {
      $has_required = $this->hasAnyRequired($element);
@@ -219,9 +230,15 @@ protected function actions(array $form, FormStateInterface $form_state) {
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);

    // Before proceeding validation, rebuild the entity to make sure it's
    // up-to-date. This is needed because element validators may update form
    // state, and other validators use the entity for validating the field.
    // @todo remove in https://www.drupal.org/project/drupal/issues/3372934.
    $this->entity = $this->buildEntity($form, $form_state);

    if (isset($form['default_value']) && (!isset($form['set_default_value']) || $form_state->getValue('set_default_value'))) {
      $item = $form['#entity']->get($this->entity->getName());
      $item->defaultValuesFormValidate($form['default_value'], $form, $form_state);
      $items = $this->getTypedData($form['#entity']);
      $items->defaultValuesFormValidate($form['default_value'], $form, $form_state);
    }
  }

@@ -234,7 +251,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    // Handle the default value.
    $default_value = [];
    if (isset($form['default_value']) && (!isset($form['set_default_value']) || $form_state->getValue('set_default_value'))) {
      $items = $form['#entity']->get($this->entity->getName());
      $items = $this->getTypedData($form['#entity']);
      $default_value = $items->defaultValuesFormSubmit($form['default_value'], $form, $form_state);
    }
    $this->entity->setDefaultValue($default_value);
@@ -271,4 +288,17 @@ public function getTitle(FieldConfigInterface $field_config) {
    return $field_config->label();
  }

  /**
   * Gets typed data object for the field.
   *
   * @param \Drupal\Core\Entity\FieldableEntityInterface $parent
   *   The parent entity that the field is attached to.
   *
   * @return \Drupal\Core\TypedData\TypedDataInterface
   */
  private function getTypedData(FieldableEntityInterface $parent): TypedDataInterface {
    $entity_adapter = EntityAdapter::createFromEntity($parent);
    return $this->typedDataManager->create($this->entity, $this->entity->getDefaultValue($parent), $this->entity->getName(), $entity_adapter);
  }

}
+2 −1
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ protected function setUp(): void {
    parent::setUp();

    $entity_type_bundle_info = $this->createMock('\Drupal\Core\Entity\EntityTypeBundleInfoInterface');
    $this->fieldConfigEditForm = new FieldConfigEditForm($entity_type_bundle_info);
    $typed_data = $this->createMock('\Drupal\Core\TypedData\TypedDataManagerInterface');
    $this->fieldConfigEditForm = new FieldConfigEditForm($entity_type_bundle_info, $typed_data);
  }

  /**