src/Hitso/Bundle/CommonBundle/Doctrine/Manager/AbstractManager.php line 261

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Hitso\Bundle\CommonBundle\Doctrine\Manager;
  4. use Carbon\Carbon;
  5. use Doctrine\Common\Collections\ArrayCollection;
  6. use Doctrine\Common\Collections\Collection;
  7. use Doctrine\Common\Collections\Criteria;
  8. use Doctrine\Common\Inflector\Inflector;
  9. use Doctrine\Common\Persistence\ObjectRepository;
  10. use Doctrine\Common\Util\ClassUtils;
  11. use Doctrine\Common\Util\Debug;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Doctrine\ORM\Mapping\ClassMetadata;
  14. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  15. use Hitso\Bundle\CatalogBundle\Entity\Product;
  16. use Hitso\Bundle\CatalogBundle\Entity\ProductEditable;
  17. use Hitso\Bundle\CommonBundle\Doctrine\Event\EntityEvent;
  18. use Hitso\Bundle\CommonBundle\Doctrine\Factory\EntityCloneFactory;
  19. use Hitso\Bundle\CommonBundle\Doctrine\Factory\EntityCloneFactoryInterface;
  20. use Hitso\Bundle\CommonBundle\Doctrine\Service\LoggableReverter;
  21. use Hitso\Bundle\CommonBundle\Entity\EntityInterface;
  22. use Hitso\Bundle\CommonBundle\Entity\User;
  23. use Hitso\Bundle\CommonBundle\Traits\DeletableInterface;
  24. use Hitso\Bundle\CommonBundle\Traits\EditableInterface;
  25. use Hitso\Bundle\CommonBundle\Traits\EnabledInterface;
  26. use Hitso\Bundle\FormBundle\Form\Handler\FormHandlerInterface;
  27. use Hitso\Bundle\MultiSiteBundle\MultiSite\SiteContext;
  28. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  29. use Symfony\Component\Form\FormFactoryInterface;
  30. use Symfony\Component\Form\FormInterface;
  31. use Symfony\Component\PropertyAccess\PropertyAccessor;
  32. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  33. /**
  34.  * Class AbstractManager
  35.  *
  36.  * @package Hitso\Bundle\CommonBundle\Doctrine\Manager
  37.  */
  38. abstract class AbstractManager implements ManagerInterface
  39. {
  40.     /**
  41.      * @var bool
  42.      */
  43.     protected $editable false;
  44.     /**
  45.      * @var EntityManagerInterface
  46.      */
  47.     protected $doctrine;
  48.     /**
  49.      * @var EventDispatcherInterface
  50.      */
  51.     protected $eventDispatcher;
  52.     /**
  53.      * @var FormFactoryInterface
  54.      */
  55.     protected $formHandler;
  56.     /**
  57.      * @var EntityCloneFactoryInterface
  58.      */
  59.     protected $entityCloneFactory;
  60.     /**
  61.      * @var ParameterBagInterface
  62.      */
  63.     protected $parameterBag;
  64.     /**
  65.      * AbstractManager constructor.
  66.      *
  67.      * @param EntityManagerInterface   $doctrine
  68.      * @param EventDispatcherInterface $eventDispatcher
  69.      * @param FormHandlerInterface     $formHandler
  70.      * @param EntityCloneFactory       $entityCloneFactory
  71.      * @param ParameterBagInterface    $parameterBag
  72.      */
  73.     public function __construct(
  74.         EntityManagerInterface $doctrine,
  75.         EventDispatcherInterface $eventDispatcher,
  76.         FormHandlerInterface $formHandler,
  77.         EntityCloneFactory $entityCloneFactory,
  78.         ParameterBagInterface $parameterBag
  79.     ) {
  80.         $this->doctrine           $doctrine;
  81.         $this->eventDispatcher    $eventDispatcher;
  82.         $this->formHandler        $formHandler;
  83.         $this->entityCloneFactory $entityCloneFactory;
  84.         $this->parameterBag       $parameterBag;
  85.     }
  86.     /**
  87.      * @return string
  88.      */
  89.     abstract protected function getFormTypeClass(): string;
  90.     /**
  91.      * @param EntityInterface $entity
  92.      * @param bool            $flush
  93.      *
  94.      * @throws \Doctrine\Common\Persistence\Mapping\MappingException
  95.      * @throws \Doctrine\ORM\ORMException
  96.      * @throws \ReflectionException
  97.      */
  98.     public function saveResource(EntityInterface $entitybool $flush true): void
  99.     {
  100.         if ($this->doctrine->contains($entity)) {
  101.             $this->updateResource($entity$flush);
  102.             return;
  103.         }
  104.         $this->createResource($entity$flush);
  105.     }
  106.     /**
  107.      * @param EntityInterface $entity
  108.      * @param bool            $flush
  109.      * @param User|null       $user
  110.      * @param bool            $isGranted
  111.      *
  112.      * @throws \ReflectionException
  113.      */
  114.     public function createResource(EntityInterface $entitybool $flush trueUser $user null$isGranted true): void
  115.     {
  116.         $this->dispatchEvent(self::PRE_ENTITY_CREATE_EVENT$entity);
  117.         $this->doctrine->persist($entity);
  118.         if ($flush) {
  119.             $this->flushResource();
  120.         }
  121.         $this->dispatchEvent(self::POST_ENTITY_CREATE_EVENT$entity);
  122.         $this->dispatchEvent(self::POST_ENTITY_SAVE_EVENT$entity);
  123.     }
  124.     /**
  125.      * @param EntityInterface $entity
  126.      * @param bool            $flush
  127.      * @param bool            $isGranted
  128.      *
  129.      * @throws \ReflectionException
  130.      */
  131.     public function updateResource(EntityInterface $entitybool $flush true$isGranted false): void
  132.     {
  133.         $this->dispatchEvent(self::PRE_ENTITY_UPDATE_EVENT$entity);
  134.         $this->doctrine->persist($entity);
  135.         if ($flush) {
  136.             $this->flushResource();
  137.         }
  138.         $this->dispatchEvent(self::POST_ENTITY_UPDATE_EVENT$entity);
  139.         $this->dispatchEvent(self::POST_ENTITY_SAVE_EVENT$entity);
  140.     }
  141.     /**
  142.      * @param EntityInterface $entity
  143.      * @param bool            $flush
  144.      *
  145.      * @throws \ReflectionException
  146.      */
  147.     public function removeResource(EntityInterface $entitybool $flush true): void
  148.     {
  149.         $this->dispatchEvent(self::PRE_ENTITY_REMOVE_EVENT$entity);
  150.         $this->doctrine->remove($entity);
  151.         if ($flush) {
  152.             $this->flushResource();
  153.         }
  154.         $this->dispatchEvent(self::POST_ENTITY_REMOVE_EVENT$entity);
  155.     }
  156.     public function flushResource(): void
  157.     {
  158.         $this->doctrine->flush();
  159.     }
  160.     /**
  161.      * @return ObjectRepository
  162.      */
  163.     public function getRepository(): ObjectRepository
  164.     {
  165.         return $this->doctrine->getRepository($this->getEntityClass());
  166.     }
  167.     /**
  168.      * @return ClassMetadata
  169.      */
  170.     public function getClassMetadata()
  171.     {
  172.         return $this->doctrine->getClassMetadata($this->getEntityClass());
  173.     }
  174.     /**
  175.      * @param Criteria|null $criteria
  176.      *
  177.      * @return Collection
  178.      */
  179.     public function getCollection(Criteria $criteria null): Collection
  180.     {
  181.         return $this->getRepository()->matching($criteria $criteria : new Criteria());
  182.     }
  183.     /**
  184.      * @param EntityInterface $data
  185.      * @param array           $options
  186.      * @param string|null     $formType
  187.      *
  188.      * @return FormInterface
  189.      */
  190.     public function initForm(EntityInterface $data, array $options = [], string $formType null): FormInterface
  191.     {
  192.         if (null === $formType) {
  193.             $formType $this->getFormTypeClass();
  194.         }
  195.         return $this->formHandler->createForm($data$options$formType);
  196.     }
  197.     /**
  198.      * @return EntityInterface
  199.      * @throws \ReflectionException
  200.      */
  201.     public function initResource(): EntityInterface
  202.     {
  203.         $class  $this->getEntityClass();
  204.         $entity = new $class();
  205.         $this->dispatchEvent(self::POST_ENTITY_INIT_EVENT$entity);
  206.         return $entity;
  207.     }
  208.     /**
  209.      * @param string          $name
  210.      * @param EntityInterface $entity
  211.      *
  212.      * @throws \ReflectionException
  213.      */
  214.     public function dispatchEvent(string $nameEntityInterface $entity): void
  215.     {
  216.         $eventName $this->getEventName($entity$name);
  217.         $event     = new EntityEvent($entity);
  218.         $this->eventDispatcher->dispatch($eventName$event);
  219.     }
  220.     /**
  221.      * @param EntityInterface $entity
  222.      * @param                 $name
  223.      *
  224.      * @return string
  225.      * @throws \ReflectionException
  226.      */
  227.     private function getEventName(EntityInterface $entity$name): string
  228.     {
  229.         if ($entity instanceof EventResourceNameInterface) {
  230.             $eventResourceName $entity->getEventResourceName();
  231.         } else {
  232.             $eventResourceName = (new \ReflectionClass($entity))->getShortName();
  233.         }
  234.         return sprintf('%s.%s'Inflector::tableize($eventResourceName), $name);
  235.     }
  236.     /**
  237.      * @param EntityInterface $entity
  238.      *
  239.      * @return ClassMetadata
  240.      */
  241.     public function getEntityMetadata(EntityInterface $entity): ClassMetadata
  242.     {
  243.         return $this->doctrine->getClassMetadata(ClassUtils::getClass($entity));
  244.     }
  245.     /**
  246.      * @param EntityInterface $entity
  247.      * @param User            $user
  248.      *
  249.      * @throws \ReflectionException
  250.      */
  251.     public function setDeletable(EntityInterface $entityUser $user)
  252.     {
  253.         if ($this->isDeletable($entity)) {
  254.             $entity->setDeletable(true);
  255.             $entity->setDeletableAt(Carbon::now());
  256.             $entity->setDeletableBy($user);
  257.             $this->updateResource($entity);
  258.         }
  259.     }
  260.     /**
  261.      * @param EntityInterface $entity
  262.      *
  263.      * @throws \Exception
  264.      */
  265.     public function resetDeletable(EntityInterface $entity)
  266.     {
  267.         if ($this->isDeletable($entity)) {
  268.             $entity->setDeletable(false);
  269.             $entity->setDeletableAt(null);
  270.             $entity->setDeletableBy(null);
  271.             $this->updateResource($entity);
  272.         }
  273.     }
  274.     /**
  275.      * @param EntityInterface $entityTo
  276.      * @param EntityInterface $entityFrom
  277.      * @param User|null       $user
  278.      *
  279.      * @return EntityInterface
  280.      * @throws \Exception
  281.      */
  282.     public function setCloningParams(EntityInterface $entityToEntityInterface $entityFrom nullUser $user null): EntityInterface
  283.     {
  284.         if ($this->isEditable($entityTo)) {
  285.             $entityTo->setEditable(true);
  286.             $entityTo->setEditableAt(Carbon::now());
  287.             if ($user) {
  288.                 $entityTo->setEditableBy($user);
  289.             }
  290.             if ($entityFrom) {
  291.                 $entityTo->setParentId($entityFrom $entityFrom->getId() : null);
  292.             }
  293.             $meta $this->getEntityMetadata($entityTo);
  294.             if ($entityFrom && $meta->hasAssociation('route')) {
  295.                 $entityTo->setRoute();
  296.             }
  297.         }
  298.         return $entityTo;
  299.     }
  300.     /**
  301.      * @param EntityInterface $entity
  302.      *
  303.      * @return EntityInterface
  304.      */
  305.     public function resetCloningParams(EntityInterface $entity): EntityInterface
  306.     {
  307.         if ($this->isEditable($entity)) {
  308.             $entity->setParentId(null);
  309.             $entity->setEditable(false);
  310.             $entity->setEditableAt(null);
  311.             $entity->setEditableBy(null);
  312.         }
  313.         return $entity;
  314.     }
  315.     /**
  316.      * @param EntityInterface      $entityTo
  317.      * @param EntityInterface|null $entityFrom
  318.      * @param User|null            $user
  319.      *
  320.      * @return EntityInterface
  321.      * @throws \Exception
  322.      */
  323.     public function updateCloningParams(EntityInterface $entityToEntityInterface $entityFrom nullUser $user null): EntityInterface
  324.     {
  325.         return $entityTo;
  326.     }
  327.     /**
  328.      * @param EntityInterface $entity
  329.      *
  330.      * @return bool
  331.      */
  332.     public function isEditable(EntityInterface $entity): bool
  333.     {
  334.         return $entity instanceof EditableInterface;
  335.     }
  336.     /**
  337.      * @param EntityInterface $entity
  338.      *
  339.      * @return bool
  340.      */
  341.     public function isDeletable(EntityInterface $entity): bool
  342.     {
  343.         return $entity instanceof DeletableInterface;
  344.     }
  345.     /**
  346.      * @param string|null $action
  347.      *
  348.      * @return array
  349.      */
  350.     public function getAcceptanceRoles(string $action null): array
  351.     {
  352.         $acceptanceRoles $this->parameterBag->get('common.acceptance');
  353.         $entityClass     ClassUtils::getRealClass($this->getEntityClass());
  354.         if (array_key_exists($entityClass$acceptanceRoles)) {
  355.             if (array_key_exists($action$acceptanceRoles[$entityClass]) && $acceptanceRoles[$entityClass][$action]) {
  356.                 return $acceptanceRoles[$entityClass][$action];
  357.             }
  358.             if (array_key_exists('roles'$acceptanceRoles[$entityClass])) {
  359.                 return $acceptanceRoles[$entityClass]['roles'];
  360.             }
  361.         }
  362.         return [];
  363.     }
  364.     /**
  365.      * @return array
  366.      */
  367.     public function getNoDuplicatedField(): array
  368.     {
  369.         return [];
  370.     }
  371.     /**
  372.      * @return array
  373.      */
  374.     public function getNoDuplicatedAssociation(): array
  375.     {
  376.         return [];
  377.     }
  378.     /**
  379.      * @param EntityInterface $entity
  380.      * @param EntityInterface $associationRecord
  381.      *
  382.      * @return EntityInterface
  383.      */
  384.     public function removeRecord(
  385.         EntityInterface $entity,
  386.         EntityInterface $associationRecord
  387.     ): EntityInterface {
  388.         $this->doctrine->remove($associationRecord);
  389.         return $entity;
  390.     }
  391. }