vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php line 40

Open in your IDE?
  1. <?php
  2. namespace Doctrine\Bundle\DoctrineBundle\Repository;
  3. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
  4. use Doctrine\ORM\EntityManagerInterface;
  5. use Doctrine\ORM\Mapping\ClassMetadata;
  6. use Doctrine\ORM\Repository\RepositoryFactory;
  7. use Doctrine\Persistence\ObjectRepository;
  8. use Psr\Container\ContainerInterface;
  9. use RuntimeException;
  10. use function class_exists;
  11. use function is_a;
  12. use function spl_object_hash;
  13. use function sprintf;
  14. /**
  15.  * Fetches repositories from the container or falls back to normal creation.
  16.  */
  17. final class ContainerRepositoryFactory implements RepositoryFactory
  18. {
  19.     /** @var array<string, ObjectRepository> */
  20.     private $managedRepositories = [];
  21.     /** @var ContainerInterface */
  22.     private $container;
  23.     /** @param ContainerInterface $container A service locator containing the repositories */
  24.     public function __construct(ContainerInterface $container)
  25.     {
  26.         $this->container $container;
  27.     }
  28.     /**
  29.      * {@inheritdoc}
  30.      *
  31.      * @template T of object
  32.      */
  33.     public function getRepository(EntityManagerInterface $entityManager$entityName): ObjectRepository
  34.     {
  35.         $metadata            $entityManager->getClassMetadata($entityName);
  36.         $repositoryServiceId $metadata->customRepositoryClassName;
  37.         $customRepositoryName $metadata->customRepositoryClassName;
  38.         if ($customRepositoryName !== null) {
  39.             // fetch from the container
  40.             if ($this->container->has($customRepositoryName)) {
  41.                 $repository $this->container->get($customRepositoryName);
  42.                 if (! $repository instanceof ObjectRepository) {
  43.                     throw new RuntimeException(sprintf('The service "%s" must implement ObjectRepository (or extend a base class, like ServiceEntityRepository).'$repositoryServiceId));
  44.                 }
  45.                 /** @psalm-var ObjectRepository<T> */
  46.                 return $repository;
  47.             }
  48.             // if not in the container but the class/id implements the interface, throw an error
  49.             if (is_a($customRepositoryNameServiceEntityRepositoryInterface::class, true)) {
  50.                 throw new RuntimeException(sprintf('The "%s" entity repository implements "%s", but its service could not be found. Make sure the service exists and is tagged with "%s".'$customRepositoryNameServiceEntityRepositoryInterface::class, ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG));
  51.             }
  52.             if (! class_exists($customRepositoryName)) {
  53.                 throw new RuntimeException(sprintf('The "%s" entity has a repositoryClass set to "%s", but this is not a valid class. Check your class naming. If this is meant to be a service id, make sure this service exists and is tagged with "%s".'$metadata->name$customRepositoryNameServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG));
  54.             }
  55.             // allow the repository to be created below
  56.         }
  57.         return $this->getOrCreateRepository($entityManager$metadata);
  58.     }
  59.     /**
  60.      * @param ClassMetadata<TEntity> $metadata
  61.      *
  62.      * @return ObjectRepository<TEntity>
  63.      *
  64.      * @template TEntity of object
  65.      */
  66.     private function getOrCreateRepository(
  67.         EntityManagerInterface $entityManager,
  68.         ClassMetadata $metadata
  69.     ): ObjectRepository {
  70.         $repositoryHash $metadata->getName() . spl_object_hash($entityManager);
  71.         if (isset($this->managedRepositories[$repositoryHash])) {
  72.             /** @psalm-var ObjectRepository<TEntity> */
  73.             return $this->managedRepositories[$repositoryHash];
  74.         }
  75.         $repositoryClassName $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName();
  76.         /** @psalm-var ObjectRepository<TEntity> */
  77.         return $this->managedRepositories[$repositoryHash] = new $repositoryClassName($entityManager$metadata);
  78.     }
  79. }