vendor/easycorp/easyadmin-bundle/src/Factory/EntityFactory.php line 115

  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Factory;
  3. use Doctrine\Common\Util\ClassUtils;
  4. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  5. use Doctrine\Persistence\ManagerRegistry;
  6. use Doctrine\Persistence\Mapping\ClassMetadata;
  7. use Doctrine\Persistence\ObjectManager;
  8. use Doctrine\Persistence\Proxy;
  9. use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
  10. use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection;
  11. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  12. use EasyCorp\Bundle\EasyAdminBundle\Dto\ActionConfigDto;
  13. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  14. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityBuiltEvent;
  15. use EasyCorp\Bundle\EasyAdminBundle\Exception\EntityNotFoundException;
  16. use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
  17. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  18. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  19. /**
  20.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  21.  */
  22. final class EntityFactory
  23. {
  24.     private FieldFactory $fieldFactory;
  25.     private ActionFactory $actionFactory;
  26.     private AuthorizationCheckerInterface $authorizationChecker;
  27.     private ManagerRegistry $doctrine;
  28.     private EventDispatcherInterface $eventDispatcher;
  29.     public function __construct(FieldFactory $fieldFactory, ActionFactory $actionFactory, AuthorizationCheckerInterface $authorizationChecker, ManagerRegistry $doctrine, EventDispatcherInterface $eventDispatcher)
  30.     {
  31.         $this->fieldFactory = $fieldFactory;
  32.         $this->actionFactory = $actionFactory;
  33.         $this->authorizationChecker = $authorizationChecker;
  34.         $this->doctrine = $doctrine;
  35.         $this->eventDispatcher = $eventDispatcher;
  36.     }
  37.     public function processFields(EntityDto $entityDto, FieldCollection $fields): void
  38.     {
  39.         $this->fieldFactory->processFields($entityDto, $fields);
  40.     }
  41.     public function processFieldsForAll(EntityCollection $entities, FieldCollection $fields): void
  42.     {
  43.         foreach ($entities as $entity) {
  44.             $this->processFields($entity, clone $fields);
  45.             $entities->set($entity);
  46.         }
  47.     }
  48.     public function processActions(EntityDto $entityDto, ActionConfigDto $actionConfigDto): void
  49.     {
  50.         $this->actionFactory->processEntityActions($entityDto, $actionConfigDto);
  51.     }
  52.     public function processActionsForAll(EntityCollection $entities, ActionConfigDto $actionConfigDto): ActionCollection
  53.     {
  54.         foreach ($entities as $entity) {
  55.             $this->processActions($entity, clone $actionConfigDto);
  56.         }
  57.         return $this->actionFactory->processGlobalActions($actionConfigDto);
  58.     }
  59.     public function create(string $entityFqcn, $entityId = null, ?string $entityPermission = null): EntityDto
  60.     {
  61.         return $this->doCreate($entityFqcn, $entityId, $entityPermission);
  62.     }
  63.     public function createForEntityInstance($entityInstance): EntityDto
  64.     {
  65.         return $this->doCreate(null, null, null, $entityInstance);
  66.     }
  67.     public function createCollection(EntityDto $entityDto, ?iterable $entityInstances): EntityCollection
  68.     {
  69.         $entityDtos = [];
  70.         foreach ($entityInstances as $entityInstance) {
  71.             $newEntityDto = $entityDto->newWithInstance($entityInstance);
  72.             $newEntityId = $newEntityDto->getPrimaryKeyValueAsString();
  73.             if (!$this->authorizationChecker->isGranted(Permission::EA_ACCESS_ENTITY, $newEntityDto)) {
  74.                 $newEntityDto->markAsInaccessible();
  75.             }
  76.             $entityDtos[$newEntityId] = $newEntityDto;
  77.         }
  78.         return EntityCollection::new($entityDtos);
  79.     }
  80.     /**
  81.      * @return ClassMetadata&ClassMetadataInfo
  82.      */
  83.     public function getEntityMetadata(string $entityFqcn): ClassMetadata
  84.     {
  85.         $entityManager = $this->getEntityManager($entityFqcn);
  86.         /** @var ClassMetadata&ClassMetadataInfo $entityMetadata */
  87.         $entityMetadata = $entityManager->getClassMetadata($entityFqcn);
  88.         if (1 !== \count($entityMetadata->getIdentifierFieldNames())) {
  89.             throw new \RuntimeException(sprintf('EasyAdmin does not support Doctrine entities with composite primary keys (such as the ones used in the "%s" entity).', $entityFqcn));
  90.         }
  91.         return $entityMetadata;
  92.     }
  93.     private function doCreate(?string $entityFqcn = null, $entityId = null, ?string $entityPermission = null, $entityInstance = null): EntityDto
  94.     {
  95.         if (null === $entityInstance && null !== $entityFqcn) {
  96.             $entityInstance = null === $entityId ? null : $this->getEntityInstance($entityFqcn, $entityId);
  97.         }
  98.         if (null !== $entityInstance && null === $entityFqcn) {
  99.             if ($entityInstance instanceof Proxy) {
  100.                 $entityInstance->__load();
  101.             }
  102.             $entityFqcn = ClassUtils::getClass($entityInstance);
  103.         }
  104.         $entityMetadata = $this->getEntityMetadata($entityFqcn);
  105.         $entityDto = new EntityDto($entityFqcn, $entityMetadata, $entityPermission, $entityInstance);
  106.         if (!$this->authorizationChecker->isGranted(Permission::EA_ACCESS_ENTITY, $entityDto)) {
  107.             $entityDto->markAsInaccessible();
  108.         }
  109.         $this->eventDispatcher->dispatch(new AfterEntityBuiltEvent($entityDto));
  110.         return $entityDto;
  111.     }
  112.     private function getEntityManager(string $entityFqcn): ObjectManager
  113.     {
  114.         if (null === $entityManager = $this->doctrine->getManagerForClass($entityFqcn)) {
  115.             throw new \RuntimeException(sprintf('There is no Doctrine Entity Manager defined for the "%s" class', $entityFqcn));
  116.         }
  117.         return $entityManager;
  118.     }
  119.     private function getEntityInstance(string $entityFqcn, $entityIdValue): object
  120.     {
  121.         $entityManager = $this->getEntityManager($entityFqcn);
  122.         if (null === $entityInstance = $entityManager->getRepository($entityFqcn)->find($entityIdValue)) {
  123.             $entityIdName = $entityManager->getClassMetadata($entityFqcn)->getIdentifierFieldNames()[0];
  124.             throw new EntityNotFoundException(['entity_name' => $entityFqcn, 'entity_id_name' => $entityIdName, 'entity_id_value' => $entityIdValue]);
  125.         }
  126.         return $entityInstance;
  127.     }
  128. }