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

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