8000 [DoctrineBridge] Fix UniqueEntity interaction with inheritance · lemoinem/symfony@9ca4343 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9ca4343

Browse files
committed
[DoctrineBridge] Fix UniqueEntity interaction with inheritance
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
1 parent d63d8d5 commit 9ca4343

File tree

5 files changed

+76
-25
lines changed

5 files changed

+76
-25
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
use Doctrine\ORM\Mapping\Id;
15+
use Doctrine\ORM\Mapping\Column;
16+
use Doctrine\ORM\Mapping\Entity;
17+
18+
/** @Entity */
19+
class ChildEntity extends SingleIntIdEntity
20+
{
21+
}

src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,17 @@
1313

1414
use Doctrine\ORM\Mapping\Id;
1515
use Doctrine\ORM\Mapping\Column;
16+
use Doctrine\ORM\Mapping\DiscriminatorColumn;
17+
use Doctrine\ORM\Mapping\DiscriminatorMap;
1618
use Doctrine\ORM\Mapping\Entity;
19+
use Doctrine\ORM\Mapping\InheritanceType;
1720

18-
/** @Entity */
21+
/**
22+
* @Entity
23+
* @InheritanceType("SINGLE_TABLE")
24+
* @DiscriminatorColumn(name="discr", type="string")
25+
* @DiscriminatorMap({"parent" = "SingleIntIdEntity", "child" = "ChildEntity"})
26+
*/
1927
class SingleIntIdEntity
2028
{
2129
/** @Id @Column(type="integer") */

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

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Doctrine\Common\Persistence\ObjectManager;
1616
use Doctrine\Common\Persistence\ObjectRepository;
1717
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
18+
use Symfony\Bridge\Doctrine\Tests\Fixtures\ChildEntity;
1819
use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity;
1920
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;
2021
use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity;
@@ -81,10 +82,13 @@ protected function createEntityManagerMock($repositoryMock)
8182
$em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager')
8283
->getMock()
8384
;
84-
$em->expects($this->any())
85-
->method('getRepository')
86-
->will($this->returnValue($repositoryMock))
87-
;
85+
86+
if ($repositoryMock) {
87+
$em->expects($this->any())
88+
->method('getRepository')
89+
->will($this->returnValue($repositoryMock))
90+
;
91+
}
8892

8993
$classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata');
9094
$classMetadata
@@ -140,6 +144,7 @@ public function testValidateUniqueness()
140144
'message' => 'myMessage',
141145
'fields' => array('name'),
142146
'em' => self::EM_NAME,
147+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
143148
));
144149

145150
$entity1 = new SingleIntIdEntity(1, 'Foo');
@@ -171,6 +176,7 @@ public function testValidateCustomErrorPath()
171176
'fields' => array('name'),
172177
'em' => self::EM_NAME,
173178
'errorPath' => 'bar',
179+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
174180
));
175181

176182
$entity1 = new SingleIntIdEntity(1, 'Foo');
@@ -193,6 +199,7 @@ public function testValidateUniquenessWithNull()
193199
'message' => 'myMessage',
194200
'fields' => array('name'),
195201
'em' => self::EM_NAME,
202+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
196203
));
197204

198205
$entity1 = new SingleIntIdEntity(1, null);
@@ -214,6 +221,7 @@ public function testValidateUniquenessWithIgnoreNull()
214221
'fields' => array('name', 'name2'),
215222
'em' => self::EM_NAME,
216223
'ignoreNull' => false,
224+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity',
217225
));
218226

219227
$entity1 = new DoubleNameEntity(1, 'Foo', null);
@@ -245,6 +253,7 @@ public function testValidateUniquenessWithValidCustomErrorPath()
245253
'fields' => array('name', 'name2'),
246254
'em' => self::EM_NAME,
247255
'errorPath' => 'name2',
256+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity',
248257
));
249258

250259
$entity1 = new DoubleNameEntity(1, 'Foo', 'Bar');
@@ -276,6 +285,7 @@ public function testValidateUniquenessUsingCustomRepositoryMethod()
276285
'fields' => array('name'),
277286
'em' => self::EM_NAME,
278287
'repositoryMethod' => 'findByCustom',
288+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
279289
));
280290

281291
$repository = $this->createRepositoryMock();
@@ -302,6 +312,7 @@ public function testValidateUniquenessWithUnrewoundArray()
302312
'fields' => array('name'),
303313
'em' => self::EM_NAME,
304314
'repositoryMethod' => 'findByCustom',
315+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
305316
));
306317

307318
$entity = new SingleIntIdEntity(1, 'foo');
@@ -336,6 +347,7 @@ public function testAssociatedEntity()
336347
'message' => 'myMessage',
337348
'fields' => array('single'),
338349
'em' => self::EM_NAME,
350+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity',
339351
));
340352

341353
$entity1 = new SingleIntIdEntity(1, 'foo');
@@ -370,6 +382,7 @@ public function testAssociatedEntityWithNull()
370382
'fields' => array('single'),
371383
'em' => self::EM_NAME,
372384
'ignoreNull' => false,
385+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity',
373386
));
374387

375388
$associated = new AssociationEntity();
@@ -393,6 +406,7 @@ public function testAssociatedCompositeEntity()
393406
'message' => 'myMessage',
394407
'fields' => array('composite'),
395408
'em' => self::EM_NAME,
409+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity',
396410
));
397411

398412
$composite = new CompositeIntIdEntity(1, 1, 'test');
@@ -416,6 +430,7 @@ public function testDedicatedEntityManagerNullObject()
416430
'message' => 'myMessage',
417431
'fields' => array('name'),
418432
'em' => self::EM_NAME,
433+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
419434
));
420435

421436
$this->em = null;
@@ -428,24 +443,28 @@ public function testDedicatedEntityManagerNullObject()
428443
$this->validator->validate($entity, $constraint);
429444
}
430445

431-
/**
432-
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
433-
* @expectedExceptionMessage Unable to find the object manager associated with an entity of class "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity"
434-
*/
435-
public function testEntityManagerNullObject()
446+
public function testTargetsRepoIsUsedForChildren()
436447
{
437448
$constraint = new UniqueEntity(array(
438449
'message' => 'myMessage',
439450
'fields' => array('name'),
440-
// no "em" option set
451+
'em' => self::EM_NAME,
452+
'target' => 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity',
441453
));
442454

443-
$this->em = null;
455+
$repository = $this->createRepositoryMock();
456+
$this->em = $this->createEntityManagerMock(null);
457+
$this->em->expects($this->atLeastOnce())
458+
->method('getRepository')
459+
->with('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity')
460+
->will($this->returnValue($repository))
461+
;
444462
$this->registry = $this->createRegistryMock($this->em);
463+
445464
$this->validator = $this->createValidator();
446465
$this->validator->initialize($this->context);
447466

448-
$entity = new SingleIntIdEntity(1, null);
467+
$entity = new ChildEntity(1, 'Foo');
449468

450469
$this->validator->validate($entity, $constraint);
451470
}

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Bridge\Doctrine\Validator\Constraints;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Constraints\TargetAwareConstraintInterface;
16+
use Symfony\Component\Validator\Constraints\TargetAwareConstraintTrait;
1517

1618
/**
1719
* Constraint for the Unique Entity validator.
@@ -21,8 +23,10 @@
2123
*
2224
* @author Benjamin Eberlei <kontakt@beberlei.de>
2325
*/
24-
class UniqueEntity extends Constraint
26+
class UniqueEntity extends Constraint implements TargetAwareConstraintInterface
2527
{
28+
use TargetAwareConstraintTrait;
29+
2630
public $message = 'This value is already used.';
2731
public $service = 'doctrine.orm.validator.unique';
2832
public $em = null;
@@ -46,14 +50,6 @@ public function validatedBy()
4650
return $this->service;
4751
}
4852

49-
/**
50-
* {@inheritdoc}
51-
*/
52-
public function getTargets()
53-
{
54-
return self::CLASS_CONSTRAINT;
55-
}
56-
5753
public function getDefaultOption()
5854
{
5955
return 'fields';

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,28 @@ public function validate($entity, Constraint $constraint)
6262
throw new ConstraintDefinitionException('At least one field has to be specified.');
6363
}
6464

65+
$target = $constraint->target;
66+
/* @var $target string */
67+
if (!$constraint->target) {
68+
@trigger_error('Not providing a target for a UniqueEntity constraint is deprecated since version 3.1 and will be removed in 4.0.', E_USER_DEPRECATED);
69+
$target = get_class($entity);
70+
}
71+
6572
if ($constraint->em) {
6673
$em = $this->registry->getManager($constraint->em);
6774

6875
if (!$em) {
6976
throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em));
7077
}
7178
} else {
72-
$em = $this->registry->getManagerForClass(get_class($entity));
79+
$em = $this->registry->getManagerForClass($target);
7380

7481
if (!$em) {
7582
throw new ConstraintDefinitionException(sprintf('Unable to find the object manager associated with an entity of class "%s".', get_class($entity)));
7683
}
7784
}
7885

79-
$class = $em->getClassMetadata(get_class($entity));
86+
$class = $em->getClassMetadata($target);
8087
/* @var $class \Doctrine\Common\Persistence\Mapping\ClassMetadata */
8188

8289
$criteria = array();
@@ -111,7 +118,7 @@ public function validate($entity, Constraint $constraint)
111118
}
112119
}
113120

114-
$repository = $em->getRepository(get_class($entity));
121+
$repository = $em->getRepository($target);
115122
$result = $repository->{$constraint->repositoryMethod}($criteria);
116123

117124
/* If the result is a MongoCursor, it must be advanced to the first

0 commit comments

Comments
 (0)
0