diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/MachineNameWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/MachineNameWidget.php index f6e2940625..6412f4c8e6 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/MachineNameWidget.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/MachineNameWidget.php @@ -160,7 +160,11 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen '#source_field' => $this->getSetting('source_field'), '#process' => array_merge([[get_class($this), 'processMachineNameSource']], $element_info['#process']), '#machine_name' => [ - 'exists' => [get_called_class(), 'exists'], + // We don't need the default form-level validation because we enforce + // the 'UniqueField' constraint on the field that uses this widget. + 'exists' => function () { + return FALSE; + }, 'label' => $this->fieldDefinition->getLabel(), 'replace_pattern' => $this->getSetting('replace_pattern'), 'replace' => $this->getSetting('replace'), @@ -192,35 +196,14 @@ public static function processMachineNameSource($element, FormStateInterface $fo return $element; } - /** - * Determines if the source field value already exists. - * - * @param mixed $value - * The value entered into the machine name widget. - * @param array $element - * The form element. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * - * @return bool - * TRUE if the source field value already exists, FALSE otherwise. - */ - public static function exists($value, array $element, FormStateInterface $form_state) { - return (bool) \Drupal::entityTypeManager() - ->getStorage($element['#entity_type_id']) - ->getQuery() - ->condition($element['#field_name'], $value, '=') - ->execute(); - } - /** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { - // This widget is available only to entity identifier fields. - $entity_type = \Drupal::entityTypeManager()->getDefinition($field_definition->getTargetEntityTypeId()); - - return $field_definition->getName() === $entity_type->getKey('id'); + // This widget is only available to fields that have a 'UniqueField' + // constraint. + $constraints = $field_definition->getConstraints(); + return isset($constraints['UniqueField']); } } diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php index 05c322e967..042b3b781e 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php @@ -51,6 +51,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { // In order to work around the InnoDB 191 character limit on utf8mb4 // primary keys, we set the character set for the field to ASCII. ->setSetting('is_ascii', TRUE) + ->addConstraint('UniqueField', []) ->setDisplayConfigurable('form', TRUE); // Make the label field configurable in the UI. diff --git a/core/modules/workspaces/src/Entity/Workspace.php b/core/modules/workspaces/src/Entity/Workspace.php index 149bf0947a..1903fc9f73 100644 --- a/core/modules/workspaces/src/Entity/Workspace.php +++ b/core/modules/workspaces/src/Entity/Workspace.php @@ -79,8 +79,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setDescription(new TranslatableMarkup('The workspace ID.')) ->setSetting('max_length', 128) ->setRequired(TRUE) - ->addConstraint('UniqueField') - ->addConstraint('DeletedWorkspace') + ->addConstraint('UniqueField', []) + ->addConstraint('DeletedWorkspace', []) ->addPropertyConstraints('value', ['Regex' => ['pattern' => '/^[a-z0-9_]+$/']]) ->setDisplayOptions('form', [ 'type' => 'machine_name', diff --git a/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php b/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php index 36f62d1c05..edbec2b1f8 100644 --- a/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php +++ b/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php @@ -52,23 +52,24 @@ public function setUp() { } /** - * Test creating a workspace with special characters. + * Test creating a workspace. */ - public function testSpecialCharacters() { + public function testWorkspaceCreate() { $this->drupalLogin($this->editor1); + $page = $this->getSession()->getPage(); - // Test a valid workspace name. - $this->createWorkspaceThroughUi('Workspace 1', 'a0_$()+-/'); + // Test a valid workspace ID. + $workspace = $this->createWorkspaceThroughUi('Workspace 1', 'workspace_1'); + $this->assertEquals('workspace_1', $workspace->id()); - // Test and invalid workspace name. - $this->drupalGet('/admin/config/workflow/workspaces/add'); - $this->assertSession()->statusCodeEquals(200); + // Test an invalid workspace ID. + $workspace = $this->createWorkspaceThroughUi('Workspace 2', 'workspace A@-'); + $this->assertNull($workspace); + $this->assertTrue($page->hasContent('The machine-readable name must contain only lowercase letters, numbers, and underscores.')); - $page = $this->getSession()->getPage(); - $page->fillField('label[0][value]', 'workspace2'); - $page->fillField('id[0][value]', 'A!"£%^&*{}#~@?'); - $page->findButton('Save')->click(); - $page->hasContent("This value is not valid"); + // Test a duplicate workspace ID. + $this->createWorkspaceThroughUi('Workspace 1 again', 'workspace_1'); + $this->assertTrue($page->hasContent('A workspace with workspace id workspace_1 already exists.')); } /** diff --git a/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php b/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php index 43fbf5c777..67e1423569 100644 --- a/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php +++ b/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php @@ -59,8 +59,6 @@ protected function createWorkspaceThroughUi($label, $id) { 'label[0][value]' => $label, ], 'Save'); - $this->getSession()->getPage()->hasContent("$label ($id)"); - return Workspace::load($id); } diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Core/Field/Widget/MachineNameWidgetTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Core/Field/Widget/MachineNameWidgetTest.php index 94171cef89..ef778be702 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Core/Field/Widget/MachineNameWidgetTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Field/Widget/MachineNameWidgetTest.php @@ -222,7 +222,7 @@ public function testMachineNameWidget() { $this->submitForm([], 'Save'); // Check that a form-level error has been thrown. - $assert_session->pageTextContains('The machine-readable name is already in use. It must be unique.'); + $assert_session->pageTextContains('A test entity with string_id with id test-value2-0-9- already exists.'); } }