8000 bug #16772 Refactoring EntityUserProvider::__construct() to not do wo… · symfony/symfony@fb791fd · GitHub
[go: up one dir, main page]

Skip to content

Commit fb791fd

Browse files
committed
bug #16772 Refactoring EntityUserProvider::__construct() to not do work, cause cache warm error (weaverryan)
This PR was submitted for the 2.8 branch but it was merged into the 2.3 branch instead (closes #16772). Discussion ---------- Refactoring EntityUserProvider::__construct() to not do work, cause cache warm error | Q | A | ------------- | --- | Bug fix? | "yes" | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | none | License | MIT | Doc PR | n/a This fixes a "Database not Found" error when using `doctrine/orm` 2.5 while warming up your cache under certain situations. Basically, if you use the `EntityUserProvider`, then during cache warmup, Twig requires the `security.authorization_checker` which eventually requires this `EntityUserProvider`, which previously caused Doctrine to calculate the metadata for your User class. If no database exists (and you haven't specified the platform), you'll get the error. More broadly, this simply tries to do less work in the constructor. It's a "bug fix", only kind of, but as it's completely an internal refactoring, it should be quite safe. Thanks! Commits ------- 44a2861 Refactoring EntityUserProvider::__construct() to not do work, cause cache warm error
2 parents d9b8d0c + 44a2861 commit fb791fd

File tree

2 files changed

+51
-23
lines changed

2 files changed

+51
-23
lines changed

src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,17 @@
2727
*/
2828
class EntityUserProvider implements UserProviderInterface
2929
{
30+
private $registry;
31+
private $managerName;
32+
private $classOrAlias;
3033
private $class;
31-
private $repository;
3234
private $property;
33-
private $metadata;
3435

35-
public function __construct(ManagerRegistry $registry, $class, $property = null, $managerName = null)
36+
public function __construct(ManagerRegistry $registry, $classOrAlias, $property = null, $managerName = null)
3637
{
37-
$em = $registry->getManager($managerName);
38-
$this->class = $class;
39-
$this->metadata = $em->getClassMetadata($class);
40-
41-
if (false !== strpos($this->class, ':')) {
42-
$this->class = $this->metadata->getName();
43-
}
44-
45-
$this->repository = $em->getRepository($class);
38+
$this->registry = $registry;
39+
$this->managerName = $managerName;
40+
$this->classOrAlias = $classOrAlias;
4641
$this->property = $property;
4742
}
4843

@@ -51,14 +46,15 @@ public function __construct(ManagerRegistry $registry, $class, $property = null,
5146
*/
5247
public function loadUserByUsername($username)
5348
{
49+
$repository = $this->getRepository();
5450
if (null !== $this->property) {
55-
$user = $this->repository->findOneBy(array($this->property => $username));
51+
$user = $repository->findOneBy(array($this->property => $username));
5652
} else {
57-
if (!$this->repository instanceof UserProviderInterface) {
58-
throw new \InvalidArgumentException(sprintf('The Doctrine repository "%s" must implement UserProviderInterface.', get_class($this->repository)));
53+
if (!$repository instanceof UserProviderInterface) {
54+
throw new \InvalidArgumentException(sprintf('The Doctrine repository "%s" must implement UserProviderInterface.', get_class($repository)));
5955
}
6056

61-
$user = $this->repository->loadUserByUsername($username);
57+
$user = $repository->loadUserByUsername($username);
6258
}
6359

6460
if (null === $user) {
@@ -73,26 +69,28 @@ public function loadUserByUsername($username)
7369
*/
7470
public function refreshUser(UserInterface $user)
7571
{
76-
if (!$user instanceof $this->class) {
72+
$class = $this->getClass();
73+
if (!$user instanceof $class) {
7774
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
7875
}
7976

80-
if ($this->repository instanceof UserProviderInterface) {
81-
$refreshedUser = $this->repository->refreshUser($user);
77+
$repository = $this->getRepository();
78+
if ($repository instanceof UserProviderInterface) {
79+
$refreshedUser = $repository->refreshUser($user);
8280
} else {
8381
// The user must be reloaded via the primary key as all other data
8482
// might have changed without proper persistence in the database.
8583
// That's the case when the user has been changed by a form with
8684
// validation errors.
87-
if (!$id = $this->metadata->getIdentifierValues($user)) {
85+
if (!$id = $this->getClassMetadata()->getIdentifierValues($user)) {
8886
throw new \InvalidArgumentException('You cannot refresh a user '.
8987
'from the EntityUserProvider that does not contain an identifier. '.
9088
'The user object has to be serialized with its own identifier '.
9189
'mapped by Doctrine.'
9290
);
9391
}
9492

95-
$refreshedUser = $this->repository->find($id);
93+
$refreshedUser = $repository->find($id);
9694
if (null === $refreshedUser) {
9795
throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($id)));
9896
}
@@ -106,6 +104,36 @@ public function refreshUser(UserInterface $user)
106104
*/
107105
public function supportsClass($class)
108106
{
109-
return $class === $this->class || is_subclass_of($class, $this->class);
107+
return $class === $this->getClass() || is_subclass_of($class, $this->getClass());
108+
}
109+
110+
private function getObjectManager()
111+
{
112+
return $this->registry->getManager($this->managerName);
113+
}
114+
115+
private function getRepository()
116+
{
117+
return $this->getObjectManager()->getRepository($this->classOrAlias);
118+
}
119+
120+
private function getClass()
121+
{
122+
if (null === $this->class) {
123+
$class = $this->classOrAlias;
124+
125+
if (false !== strpos($class, ':')) {
126+
$class = $this->getClassMetadata()->getName();
127+
}
128+
129+
$this->class = $class;
130+
}
131+
132+
return $this->class;
133+
}
134+
135+
private function getClassMetadata()
136+
{
137+
return $this->getObjectManager()->getClassMetadata($this->classOrAlias);
110138
}
111139
}

src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function testSupportProxy()
9292
private function getManager($em, $name = null)
9393
{
9494
$manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
95-
$manager->expects($this->once())
95+
$manager->expects($this->any())
9696
->method('getManager')
9797
->with($this->equalTo($name))
9898
->will($this->returnValue($em));

0 commit comments

Comments
 (0)
0