8000 feature #49293 [DoctrineBridge] Allow to ignore specific nullable fie… · weaverryan/symfony@95aa09e · GitHub
[go: up one dir, main page]

Skip to content

Commit 95aa09e

Browse files
feature symfony#49293 [DoctrineBridge] Allow to ignore specific nullable fields in UniqueEntity (VincentLanglet)
This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [DoctrineBridge] Allow to ignore specific nullable fields in UniqueEntity | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT | Doc PR | symfony/symfony-docs#... TODO When the UniqueEntity is applied on multiple things the only option was - ignore all nullable values - do not ignore any nullable values With this feature, it would be possible to ignore nullable values for specific field only and do not ignore nullable values for others. Commits ------- 0e61a66 [DoctrineBridge] Allow to ignore specific nullable fields in UniqueEntity
2 parents eab290d + 0e61a66 commit 95aa09e

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ public function testValidateUniquenessWithNull(UniqueEntity $constraint)
251251

252252
/**
253253
* @dataProvider provideConstraintsWithIgnoreNullDisabled
254+
* @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField
254255
*/
255-
public function testValidateUniquenessWithIgnoreNullDisabled(UniqueEntity $constraint)
256+
public function testValidateUniquenessWithIgnoreNullDisableOnSecondField(UniqueEntity $constraint)
256257
{
257258
$entity1 = new DoubleNameEntity(1, 'Foo', null);
258259
$entity2 = new DoubleNameEntity(2, 'Foo', null);
@@ -304,6 +305,7 @@ public function testAllConfiguredFieldsAreCheckedOfBeingMappedByDoctrineWithIgno
304305

305306
/**
306307
* @dataProvider provideConstraintsWithIgnoreNullEnabled
308+
* @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField
307309
*/
308310
public function testNoValidationIfFirstFieldIsNullAndNullValuesAreIgnored(UniqueEntity $constraint)
309311
{
@@ -338,6 +340,18 @@ public static function provideConstraintsWithIgnoreNullEnabled(): iterable
338340
yield 'Named arguments' => [new UniqueEntity(message: 'myMessage', fields: ['name', 'name2'], em: 'foo', ignoreNull: true)];
339341
}
340342

343+
public static function provideConstraintsWithIgnoreNullEnabledOnFirstField(): iterable
344+
{
345+
yield 'Doctrine style (name field)' => [new UniqueEntity([
346+
'message' => 'myMessage',
347+
'fields' => ['name', 'name2'],
348+
'em' => self::EM_NAME,
349+
'ignoreNull' => 'name',
350+
])];
351+
352+
yield 'Named arguments (name field)' => [new UniqueEntity(message: 'myMessage', fields: ['name', 'name2'], em: 'foo', ignoreNull: 'name')];
353+
}
354+
341355
public function testValidateUniquenessWithValidCustomErrorPath()
342356
{
343357
$constraint = new UniqueEntity([

src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class UniqueEntity extends Constraint
4545
protected static $errorNames = self::ERROR_NAMES;
4646

4747
/**
48-
* @param array|string $fields the combination of fields that must contain unique values or a set of options
48+
* @param array|string $fields The combination of fields that must contain unique values or a set of options
49+
* @param bool|array|string $ignoreNull The combination of fields that ignore null values
4950
*/
5051
public function __construct(
5152
$fields,
@@ -55,7 +56,7 @@ public function __construct(
5556
string $entityClass = null,
5657
string $repositoryMethod = null,
5758
string $errorPath = null,
58-
bool $ignoreNull = null,
59+
bool|string|array $ignoreNull = null,
5960
array $groups = null,
6061
$payload = null,
6162
array $options = []

src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function validate(mixed $entity, Constraint $constraint)
8787
$class = $em->getClassMetadata($entity::class);
8888

8989
$criteria = [];
90-
$hasNullValue = false;
90+
$hasIgnorableNullValue = false;
9191

9292
foreach ($fields as $fieldName) {
9393
if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) {
@@ -96,11 +96,9 @@ public function validate(mixed $entity, Constraint $constraint)
9696

9797
$fieldValue = $class->reflFields[$fieldName]->getValue($entity);
9898

99-
if (null === $fieldValue) {
100-
$hasNullValue = true;
101-
}
99+
if (null === $fieldValue && $this->ignoreNullForField($constraint, $fieldName)) {
100+
$hasIgnorableNullValue = true;
102101

103-
if ($constraint->ignoreNull && null === $fieldValue) {
104102
continue;
105103
}
106104

@@ -116,7 +114,7 @@ public function validate(mixed $entity, Constraint $constraint)
116114
}
117115

118116
// validation doesn't fail if one of the fields is null and if null values should be ignored
119-
if ($hasNullValue && $constraint->ignoreNull) {
117+
if ($hasIgnorableNullValue) {
120118
return;
121119
}
122120

@@ -195,6 +193,15 @@ public function validate(mixed $entity, Constraint $constraint)
195193
->addViolation();
196194
}
197195

196+
private function ignoreNullForField(UniqueEntity $constraint, string $fieldName): bool
197+
{
198+
if (\is_bool($constraint->ignoreNull)) {
199+
return $constraint->ignoreNull;
200+
}
201+
202+
return \in_array($fieldName, (array) $constraint->ignoreNull, true);
203+
}
204+
198205
private function formatWithIdentifiers(ObjectManager $em, ClassMetadata $class, mixed $value): string
199206
{
200207
if (!\is_object($value) || $value instanceof \DateTimeInterface) {

0 commit comments

Comments
 (0)
0