Loading core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php +21 −1 Original line number Diff line number Diff line Loading @@ -82,7 +82,7 @@ public function validate($items, Constraint $constraint) { // If our entity duplicates field values in any other entity, the query // will return all field values that belong to those entities. Narrow // down to only the specific duplicate values. $duplicate_values = array_intersect($item_values, $other_entity_values); $duplicate_values = $this->caseInsensitiveArrayIntersect($item_values, $other_entity_values); foreach ($duplicate_values as $delta => $dupe) { $violation = $this->context Loading Loading @@ -112,6 +112,26 @@ public function validate($items, Constraint $constraint) { } } /** * Perform a case-insensitive array intersection, but keep original capitalization. * * @param array $orig_values * The original values to be returned. * @param array $comp_values * The values to intersect $orig_values with. * * @return array * Elements of $orig_values contained in $comp_values when ignoring capitalization. */ private function caseInsensitiveArrayIntersect(array $orig_values, array $comp_values): array { $lowercase_comp_values = array_map('strtolower', $comp_values); $intersect_map = array_map(fn (string $x) => in_array(strtolower($x), $lowercase_comp_values, TRUE) ? $x : NULL, $orig_values); return array_filter($intersect_map, function ($x) { return $x !== NULL; }); } /** * Get an array of duplicate field values. * Loading core/tests/Drupal/KernelTests/Core/Validation/UniqueValuesConstraintValidatorTest.php +38 −0 Original line number Diff line number Diff line Loading @@ -288,4 +288,42 @@ public function testValidationMultiple() { } /** * Tests the UniqueField validation constraint validator with regards to case-insensitivity. * * Case 5. Try to create another entity with existing value for unique field with different capitalization. * * @throws \Drupal\Core\Entity\EntityStorageException * * @covers ::validate */ public function testValidationCaseInsensitive(): void { // Create entity with two values for the testing field. $definition = [ 'id' => (int) rand(0, getrandmax()), 'user_id' => 0, 'field_test_text' => [ 'text1', 'text2', ], ]; $entity = EntityTestUniqueConstraint::create($definition); $entity->save(); // Create another entity with two values for the testing field, one identical // to other value, but with different capitalization which should still trigger a validation error. $definition = [ 'id' => (int) rand(0, getrandmax()), 'user_id' => 0, 'field_test_text' => [ 'Text1', 'text3', ], ]; $entity = EntityTestUniqueConstraint::create($definition); $violations = $entity->validate(); $this->assertCount(1, $violations); $this->assertEquals('field_test_text.0', $violations[0]->getPropertyPath()); } } Loading
core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php +21 −1 Original line number Diff line number Diff line Loading @@ -82,7 +82,7 @@ public function validate($items, Constraint $constraint) { // If our entity duplicates field values in any other entity, the query // will return all field values that belong to those entities. Narrow // down to only the specific duplicate values. $duplicate_values = array_intersect($item_values, $other_entity_values); $duplicate_values = $this->caseInsensitiveArrayIntersect($item_values, $other_entity_values); foreach ($duplicate_values as $delta => $dupe) { $violation = $this->context Loading Loading @@ -112,6 +112,26 @@ public function validate($items, Constraint $constraint) { } } /** * Perform a case-insensitive array intersection, but keep original capitalization. * * @param array $orig_values * The original values to be returned. * @param array $comp_values * The values to intersect $orig_values with. * * @return array * Elements of $orig_values contained in $comp_values when ignoring capitalization. */ private function caseInsensitiveArrayIntersect(array $orig_values, array $comp_values): array { $lowercase_comp_values = array_map('strtolower', $comp_values); $intersect_map = array_map(fn (string $x) => in_array(strtolower($x), $lowercase_comp_values, TRUE) ? $x : NULL, $orig_values); return array_filter($intersect_map, function ($x) { return $x !== NULL; }); } /** * Get an array of duplicate field values. * Loading
core/tests/Drupal/KernelTests/Core/Validation/UniqueValuesConstraintValidatorTest.php +38 −0 Original line number Diff line number Diff line Loading @@ -288,4 +288,42 @@ public function testValidationMultiple() { } /** * Tests the UniqueField validation constraint validator with regards to case-insensitivity. * * Case 5. Try to create another entity with existing value for unique field with different capitalization. * * @throws \Drupal\Core\Entity\EntityStorageException * * @covers ::validate */ public function testValidationCaseInsensitive(): void { // Create entity with two values for the testing field. $definition = [ 'id' => (int) rand(0, getrandmax()), 'user_id' => 0, 'field_test_text' => [ 'text1', 'text2', ], ]; $entity = EntityTestUniqueConstraint::create($definition); $entity->save(); // Create another entity with two values for the testing field, one identical // to other value, but with different capitalization which should still trigger a validation error. $definition = [ 'id' => (int) rand(0, getrandmax()), 'user_id' => 0, 'field_test_text' => [ 'Text1', 'text3', ], ]; $entity = EntityTestUniqueConstraint::create($definition); $violations = $entity->validate(); $this->assertCount(1, $violations); $this->assertEquals('field_test_text.0', $violations[0]->getPropertyPath()); } }