Skip to content
Snippets Groups Projects
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
No related branches found
No related tags found
20 merge requests!11628Update file MediaLibraryWidget.php,!7564Revert "Issue #3364773 by roshnichordiya, Chris Matthews, thakurnishant_06,...,!5752Issue #3275828 by joachim, quietone, bradjones1, Berdir: document the reason...,!5627Issue #3261805: Field not saved when change of 0 on string start,!5427Issue #3338518: send credentials in ajax if configured in CORS settings.,!5395Issue #3387916 by fjgarlin, Spokje: Each GitLab job exposes user email,!5217Issue #3386607 by alexpott: Improve spell checking in commit-code-check.sh,!5064Issue #3379522 by finnsky, Gauravvvv, kostyashupenko, smustgrave, Chi: Revert...,!5040SDC ComponentElement: Transform slots scalar values to #plain_text instead of throwing an exception,!4958Issue #3392147: Whitelist IP for a Ban module.,!4894Issue #3280279: Add API to allow sites to opt in to upload SVG images in CKEditor 5,!4857Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!4856Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!4788Issue #3272985: RSS Feed header reverts to text/html when cached,!4716Issue #3362929: Improve 400 responses for broken/invalid image style routes,!4553Draft: Issue #2980951: Permission to see own unpublished comments in comment thread,!3679Issue #115801: Allow password on registration without disabling e-mail verification,!3106Issue #3017548: "Filtered HTML" text format does not support manual teaser break (<!--break-->),!925Issue #2339235: Remove taxonomy hard dependency on node module,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links
......@@ -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);
......
......@@ -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.
......
......@@ -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]", '');
......
......@@ -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);
}
}
......@@ -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);
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment