vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php line 34

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Bridge\Doctrine\Security\User;
  11. use Doctrine\Persistence\ManagerRegistry;
  12. use Doctrine\Persistence\Mapping\ClassMetadata;
  13. use Doctrine\Persistence\ObjectManager;
  14. use Doctrine\Persistence\ObjectRepository;
  15. use Doctrine\Persistence\Proxy;
  16. use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
  17. use Symfony\Component\Security\Core\Exception\UserNotFoundException;
  18. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  19. use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
  20. use Symfony\Component\Security\Core\User\UserInterface;
  21. use Symfony\Component\Security\Core\User\UserProviderInterface;
  22. /**
  23.  * Wrapper around a Doctrine ObjectManager.
  24.  *
  25.  * Provides provisioning for Doctrine entity users.
  26.  *
  27.  * @author Fabien Potencier <[email protected]>
  28.  * @author Johannes M. Schmitt <[email protected]>
  29.  */
  30. class EntityUserProvider implements UserProviderInterfacePasswordUpgraderInterface
  31. {
  32.     private $registry;
  33.     private $managerName;
  34.     private $classOrAlias;
  35.     private $class;
  36.     private $property;
  37.     public function __construct(ManagerRegistry $registrystring $classOrAlias, ?string $property null, ?string $managerName null)
  38.     {
  39.         $this->registry $registry;
  40.         $this->managerName $managerName;
  41.         $this->classOrAlias $classOrAlias;
  42.         $this->property $property;
  43.     }
  44.     /**
  45.      * {@inheritdoc}
  46.      */
  47.     public function loadUserByUsername(string $username)
  48.     {
  49.         trigger_deprecation('symfony/doctrine-bridge''5.3''Method "%s()" is deprecated, use loadUserByIdentifier() instead.'__METHOD__);
  50.         return $this->loadUserByIdentifier($username);
  51.     }
  52.     public function loadUserByIdentifier(string $identifier): UserInterface
  53.     {
  54.         $repository $this->getRepository();
  55.         if (null !== $this->property) {
  56.             $user $repository->findOneBy([$this->property => $identifier]);
  57.         } else {
  58.             if (!$repository instanceof UserLoaderInterface) {
  59.                 throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.'$this->classOrAliasget_debug_type($repository)));
  60.             }
  61.             // @deprecated since Symfony 5.3, change to $repository->loadUserByIdentifier() in 6.0
  62.             if (method_exists($repository'loadUserByIdentifier')) {
  63.                 $user $repository->loadUserByIdentifier($identifier);
  64.             } else {
  65.                 trigger_deprecation('symfony/doctrine-bridge''5.3''Not implementing method "loadUserByIdentifier()" in user loader "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.'get_debug_type($repository));
  66.                 $user $repository->loadUserByUsername($identifier);
  67.             }
  68.         }
  69.         if (null === $user) {
  70.             $e = new UserNotFoundException(sprintf('User "%s" not found.'$identifier));
  71.             $e->setUserIdentifier($identifier);
  72.             throw $e;
  73.         }
  74.         return $user;
  75.     }
  76.     /**
  77.      * {@inheritdoc}
  78.      */
  79.     public function refreshUser(UserInterface $user)
  80.     {
  81.         $class $this->getClass();
  82.         if (!$user instanceof $class) {
  83.             throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.'get_debug_type($user)));
  84.         }
  85.         $repository $this->getRepository();
  86.         if ($repository instanceof UserProviderInterface) {
  87.             $refreshedUser $repository->refreshUser($user);
  88.         } else {
  89.             // The user must be reloaded via the primary key as all other data
  90.             // might have changed without proper persistence in the database.
  91.             // That's the case when the user has been changed by a form with
  92.             // validation errors.
  93.             if (!$id $this->getClassMetadata()->getIdentifierValues($user)) {
  94.                 throw new \InvalidArgumentException('You cannot refresh a user from the EntityUserProvider that does not contain an identifier. The user object has to be serialized with its own identifier mapped by Doctrine.');
  95.             }
  96.             $refreshedUser $repository->find($id);
  97.             if (null === $refreshedUser) {
  98.                 $e = new UserNotFoundException('User with id '.json_encode($id).' not found.');
  99.                 $e->setUserIdentifier(json_encode($id));
  100.                 throw $e;
  101.             }
  102.         }
  103.         if ($refreshedUser instanceof Proxy && !$refreshedUser->__isInitialized()) {
  104.             $refreshedUser->__load();
  105.         }
  106.         return $refreshedUser;
  107.     }
  108.     /**
  109.      * {@inheritdoc}
  110.      */
  111.     public function supportsClass(string $class)
  112.     {
  113.         return $class === $this->getClass() || is_subclass_of($class$this->getClass());
  114.     }
  115.     /**
  116.      * {@inheritdoc}
  117.      *
  118.      * @final
  119.      */
  120.     public function upgradePassword($userstring $newHashedPassword): void
  121.     {
  122.         if (!$user instanceof PasswordAuthenticatedUserInterface) {
  123.             trigger_deprecation('symfony/doctrine-bridge''5.3''The "%s::upgradePassword()" method expects an instance of "%s" as first argument, the "%s" class should implement it.'PasswordUpgraderInterface::class, PasswordAuthenticatedUserInterface::class, get_debug_type($user));
  124.             if (!$user instanceof UserInterface) {
  125.                 throw new \TypeError(sprintf('The "%s()" method expects an instance of "%s" as first argument, "%s" given.'__METHOD__PasswordAuthenticatedUserInterface::class, get_debug_type($user)));
  126.             }
  127.         }
  128.         $class $this->getClass();
  129.         if (!$user instanceof $class) {
  130.             throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.'get_debug_type($user)));
  131.         }
  132.         $repository $this->getRepository();
  133.         if ($repository instanceof PasswordUpgraderInterface) {
  134.             $repository->upgradePassword($user$newHashedPassword);
  135.         }
  136.     }
  137.     private function getObjectManager(): ObjectManager
  138.     {
  139.         return $this->registry->getManager($this->managerName);
  140.     }
  141.     private function getRepository(): ObjectRepository
  142.     {
  143.         return $this->getObjectManager()->getRepository($this->classOrAlias);
  144.     }
  145.     private function getClass(): string
  146.     {
  147.         if (null === $this->class) {
  148.             $class $this->classOrAlias;
  149.             if (str_contains($class':')) {
  150.                 $class $this->getClassMetadata()->getName();
  151.             }
  152.             $this->class $class;
  153.         }
  154.         return $this->class;
  155.     }
  156.     private function getClassMetadata(): ClassMetadata
  157.     {
  158.         return $this->getObjectManager()->getClassMetadata($this->classOrAlias);
  159.     }
  160. }