Unverified Commit ee822bb0 authored by alexpott's avatar alexpott

Issue #3027745 by claudiu.cristea, idimopoulos, wengerk, alexpott:...

Issue #3027745 by claudiu.cristea, idimopoulos, wengerk, alexpott: UniqueFieldConstraint doesn't work for entities with string IDs
parent dcf633a9
......@@ -23,9 +23,16 @@ public function validate($items, Constraint $constraint) {
$entity_type_id = $entity->getEntityTypeId();
$id_key = $entity->getEntityType()->getKey('id');
$value_taken = (bool) \Drupal::entityQuery($entity_type_id)
// The id could be NULL, so we cast it to 0 in that case.
->condition($id_key, (int) $items->getEntity()->id(), '<>')
$query = \Drupal::entityQuery($entity_type_id);
$entity_id = $entity->id();
// Using isset() instead of !empty() as 0 and '0' are valid ID values for
// entity types using string IDs.
if (isset($entity_id)) {
$query->condition($id_key, $entity_id, '<>');
}
$value_taken = (bool) $query
->condition($field_name, $item->value)
->range(0, 1)
->count()
......
name: 'UniqueField Constraint Test'
type: module
description: 'Support module for UniqueField Constraint testing.'
package: Testing
version: VERSION
core: 8.x
<?php
/**
* @file
* Contains unique_field_constraint_test.module
*/
use Drupal\Core\Entity\EntityTypeInterface;
/**
* Implements hook_entity_base_field_info_alter().
*/
function unique_field_constraint_test_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
if ($entity_type->id() === 'entity_test_string_id') {
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
$fields['name']->addConstraint('UniqueField');
}
}
<?php
namespace Drupal\KernelTests\Core\Validation;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\entity_test\Entity\EntityTestStringId;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests the unique field value validation constraint.
*
* @coversDefaultClass \Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator
*
* @group Validation
*/
class UniqueFieldConstraintTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'entity_test',
'unique_field_constraint_test',
'user',
];
/**
* Tests cases where the validation passes for entities with string IDs.
*
* @covers ::validate
*/
public function testEntityWithStringId() {
$this->installEntitySchema('entity_test_string_id');
EntityTestStringId::create([
'id' => 'foo',
'name' => $this->randomString(),
])->save();
// Reload the entity.
$entity = EntityTestStringId::load('foo');
// Check that an existing entity validates when the value is preserved.
$violations = $entity->name->validate();
$this->assertCount(0, $violations);
// Create a new entity with a different ID and a different field value.
EntityTestStringId::create([
'id' => 'bar',
'name' => $this->randomString(),
]);
// Check that a new entity with a different field value validates.
$violations = $entity->name->validate();
$this->assertCount(0, $violations);
}
/**
* Tests cases when validation raises violations for entities with string IDs.
*
* @param string|int|null $id
* The entity ID.
*
* @covers ::validate
*
* @dataProvider providerTestEntityWithStringIdWithViolation
*/
public function testEntityWithStringIdWithViolation($id) {
$this->installEntitySchema('entity_test_string_id');
$value = $this->randomString();
EntityTestStringId::create([
'id' => 'first_entity',
'name' => $value,
])->save();
$entity = EntityTestStringId::create([
'id' => $id,
'name' => $value,
]);
/** @var \Symfony\Component\Validator\ConstraintViolationList $violations */
$violations = $entity->get('name')->validate();
$message = new FormattableMarkup('A @entity_type with @field_name %value already exists.', [
'%value' => $value,
'@entity_type' => $entity->getEntityType()->getLowercaseLabel(),
'@field_name' => 'name',
]);
// Check that the validation has created the appropriate violation.
$this->assertCount(1, $violations);
$this->assertEquals($message, $violations[0]->getMessage());
}
/**
* Data provider for ::testEntityWithStringIdWithViolation().
*
* @return array
* An array of test cases.
*
* @see self::testEntityWithStringIdWithViolation()
*/
public function providerTestEntityWithStringIdWithViolation() {
return [
'without an id' => [NULL],
'zero as integer' => [0],
'zero as string' => ["0"],
'non-zero as integer' => [mt_rand(1, 127)],
'non-zero as string' => [(string) mt_rand(1, 127)],
'alphanumeric' => [$this->randomMachineName()],
];
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment