vendor/sylius/resource-bundle/src/Bundle/Controller/ResourceController.php line 558

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Sylius package.
  4.  *
  5.  * (c) Paweł Jędrzejewski
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace Sylius\Bundle\ResourceBundle\Controller;
  12. use Doctrine\Common\Persistence\ObjectManager;
  13. use FOS\RestBundle\View\View;
  14. use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
  15. use Sylius\Component\Resource\Exception\DeleteHandlingException;
  16. use Sylius\Component\Resource\Exception\UpdateHandlingException;
  17. use Sylius\Component\Resource\Factory\FactoryInterface;
  18. use Sylius\Component\Resource\Metadata\MetadataInterface;
  19. use Sylius\Component\Resource\Model\ResourceInterface;
  20. use Sylius\Component\Resource\Repository\RepositoryInterface;
  21. use Sylius\Component\Resource\ResourceActions;
  22. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  23. use Symfony\Component\HttpFoundation\Request;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  26. use Symfony\Component\HttpKernel\Exception\HttpException;
  27. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  28. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  29. class ResourceController extends Controller
  30. {
  31.     /** @var MetadataInterface */
  32.     protected $metadata;
  33.     /** @var RequestConfigurationFactoryInterface */
  34.     protected $requestConfigurationFactory;
  35.     /** @var ViewHandlerInterface */
  36.     protected $viewHandler;
  37.     /** @var RepositoryInterface */
  38.     protected $repository;
  39.     /** @var FactoryInterface */
  40.     protected $factory;
  41.     /** @var NewResourceFactoryInterface */
  42.     protected $newResourceFactory;
  43.     /** @var ObjectManager */
  44.     protected $manager;
  45.     /** @var SingleResourceProviderInterface */
  46.     protected $singleResourceProvider;
  47.     /** @var ResourcesCollectionProviderInterface */
  48.     protected $resourcesCollectionProvider;
  49.     /** @var ResourceFormFactoryInterface */
  50.     protected $resourceFormFactory;
  51.     /** @var RedirectHandlerInterface */
  52.     protected $redirectHandler;
  53.     /** @var FlashHelperInterface */
  54.     protected $flashHelper;
  55.     /** @var AuthorizationCheckerInterface */
  56.     protected $authorizationChecker;
  57.     /** @var EventDispatcherInterface */
  58.     protected $eventDispatcher;
  59.     /** @var StateMachineInterface */
  60.     protected $stateMachine;
  61.     /** @var ResourceUpdateHandlerInterface */
  62.     protected $resourceUpdateHandler;
  63.     /** @var ResourceDeleteHandlerInterface */
  64.     protected $resourceDeleteHandler;
  65.     public function __construct(
  66.         MetadataInterface $metadata,
  67.         RequestConfigurationFactoryInterface $requestConfigurationFactory,
  68.         ViewHandlerInterface $viewHandler,
  69.         RepositoryInterface $repository,
  70.         FactoryInterface $factory,
  71.         NewResourceFactoryInterface $newResourceFactory,
  72.         ObjectManager $manager,
  73.         SingleResourceProviderInterface $singleResourceProvider,
  74.         ResourcesCollectionProviderInterface $resourcesFinder,
  75.         ResourceFormFactoryInterface $resourceFormFactory,
  76.         RedirectHandlerInterface $redirectHandler,
  77.         FlashHelperInterface $flashHelper,
  78.         AuthorizationCheckerInterface $authorizationChecker,
  79.         EventDispatcherInterface $eventDispatcher,
  80.         StateMachineInterface $stateMachine,
  81.         ResourceUpdateHandlerInterface $resourceUpdateHandler,
  82.         ResourceDeleteHandlerInterface $resourceDeleteHandler
  83.     ) {
  84.         $this->metadata $metadata;
  85.         $this->requestConfigurationFactory $requestConfigurationFactory;
  86.         $this->viewHandler $viewHandler;
  87.         $this->repository $repository;
  88.         $this->factory $factory;
  89.         $this->newResourceFactory $newResourceFactory;
  90.         $this->manager $manager;
  91.         $this->singleResourceProvider $singleResourceProvider;
  92.         $this->resourcesCollectionProvider $resourcesFinder;
  93.         $this->resourceFormFactory $resourceFormFactory;
  94.         $this->redirectHandler $redirectHandler;
  95.         $this->flashHelper $flashHelper;
  96.         $this->authorizationChecker $authorizationChecker;
  97.         $this->eventDispatcher $eventDispatcher;
  98.         $this->stateMachine $stateMachine;
  99.         $this->resourceUpdateHandler $resourceUpdateHandler;
  100.         $this->resourceDeleteHandler $resourceDeleteHandler;
  101.     }
  102.     public function showAction(Request $request): Response
  103.     {
  104.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  105.         $this->isGrantedOr403($configurationResourceActions::SHOW);
  106.         $resource $this->findOr404($configuration);
  107.         $this->eventDispatcher->dispatch(ResourceActions::SHOW$configuration$resource);
  108.         $view View::create($resource);
  109.         if ($configuration->isHtmlRequest()) {
  110.             $view
  111.                 ->setTemplate($configuration->getTemplate(ResourceActions::SHOW '.html'))
  112.                 ->setTemplateVar($this->metadata->getName())
  113.                 ->setData([
  114.                     'configuration' => $configuration,
  115.                     'metadata' => $this->metadata,
  116.                     'resource' => $resource,
  117.                     $this->metadata->getName() => $resource,
  118.                 ])
  119.             ;
  120.         }
  121.         return $this->viewHandler->handle($configuration$view);
  122.     }
  123.     public function indexAction(Request $request): Response
  124.     {
  125.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  126.         $this->isGrantedOr403($configurationResourceActions::INDEX);
  127.         $resources $this->resourcesCollectionProvider->get($configuration$this->repository);
  128.         $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX$configuration$resources);
  129.         $view View::create($resources);
  130.         if ($configuration->isHtmlRequest()) {
  131.             $view
  132.                 ->setTemplate($configuration->getTemplate(ResourceActions::INDEX '.html'))
  133.                 ->setTemplateVar($this->metadata->getPluralName())
  134.                 ->setData([
  135.                     'configuration' => $configuration,
  136.                     'metadata' => $this->metadata,
  137.                     'resources' => $resources,
  138.                     $this->metadata->getPluralName() => $resources,
  139.                 ])
  140.             ;
  141.         }
  142.         return $this->viewHandler->handle($configuration$view);
  143.     }
  144.     public function createAction(Request $request): Response
  145.     {
  146.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  147.         $this->isGrantedOr403($configurationResourceActions::CREATE);
  148.         $newResource $this->newResourceFactory->create($configuration$this->factory);
  149.         $form $this->resourceFormFactory->create($configuration$newResource);
  150.         if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
  151.             $newResource $form->getData();
  152.             $event $this->eventDispatcher->dispatchPreEvent(ResourceActions::CREATE$configuration$newResource);
  153.             if ($event->isStopped() && !$configuration->isHtmlRequest()) {
  154.                 throw new HttpException($event->getErrorCode(), $event->getMessage());
  155.             }
  156.             if ($event->isStopped()) {
  157.                 $this->flashHelper->addFlashFromEvent($configuration$event);
  158.                 $eventResponse $event->getResponse();
  159.                 if (null !== $eventResponse) {
  160.                     return $eventResponse;
  161.                 }
  162.                 return $this->redirectHandler->redirectToIndex($configuration$newResource);
  163.             }
  164.             if ($configuration->hasStateMachine()) {
  165.                 $this->stateMachine->apply($configuration$newResource);
  166.             }
  167.             $this->repository->add($newResource);
  168.             if ($configuration->isHtmlRequest()) {
  169.                 $this->flashHelper->addSuccessFlash($configurationResourceActions::CREATE$newResource);
  170.             }
  171.             $postEvent $this->eventDispatcher->dispatchPostEvent(ResourceActions::CREATE$configuration$newResource);
  172.             if (!$configuration->isHtmlRequest()) {
  173.                 return $this->viewHandler->handle($configurationView::create($newResourceResponse::HTTP_CREATED));
  174.             }
  175.             $postEventResponse $postEvent->getResponse();
  176.             if (null !== $postEventResponse) {
  177.                 return $postEventResponse;
  178.             }
  179.             return $this->redirectHandler->redirectToResource($configuration$newResource);
  180.         }
  181.         if (!$configuration->isHtmlRequest()) {
  182.             return $this->viewHandler->handle($configurationView::create($formResponse::HTTP_BAD_REQUEST));
  183.         }
  184.         $initializeEvent $this->eventDispatcher->dispatchInitializeEvent(ResourceActions::CREATE$configuration$newResource);
  185.         $initializeEventResponse $initializeEvent->getResponse();
  186.         if (null !== $initializeEventResponse) {
  187.             return $initializeEventResponse;
  188.         }
  189.         $view View::create()
  190.             ->setData([
  191.                 'configuration' => $configuration,
  192.                 'metadata' => $this->metadata,
  193.                 'resource' => $newResource,
  194.                 $this->metadata->getName() => $newResource,
  195.                 'form' => $form->createView(),
  196.             ])
  197.             ->setTemplate($configuration->getTemplate(ResourceActions::CREATE '.html'))
  198.         ;
  199.         return $this->viewHandler->handle($configuration$view);
  200.     }
  201.     public function updateAction(Request $request): Response
  202.     {
  203.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  204.         $this->isGrantedOr403($configurationResourceActions::UPDATE);
  205.         $resource $this->findOr404($configuration);
  206.         $form $this->resourceFormFactory->create($configuration$resource);
  207.         if (in_array($request->getMethod(), ['POST''PUT''PATCH'], true) && $form->handleRequest($request)->isValid()) {
  208.             $resource $form->getData();
  209.             /** @var ResourceControllerEvent $event */
  210.             $event $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE$configuration$resource);
  211.             if ($event->isStopped() && !$configuration->isHtmlRequest()) {
  212.                 throw new HttpException($event->getErrorCode(), $event->getMessage());
  213.             }
  214.             if ($event->isStopped()) {
  215.                 $this->flashHelper->addFlashFromEvent($configuration$event);
  216.                 $eventResponse $event->getResponse();
  217.                 if (null !== $eventResponse) {
  218.                     return $eventResponse;
  219.                 }
  220.                 return $this->redirectHandler->redirectToResource($configuration$resource);
  221.             }
  222.             try {
  223.                 $this->resourceUpdateHandler->handle($resource$configuration$this->manager);
  224.             } catch (UpdateHandlingException $exception) {
  225.                 if (!$configuration->isHtmlRequest()) {
  226.                     return $this->viewHandler->handle(
  227.                         $configuration,
  228.                         View::create($form$exception->getApiResponseCode())
  229.                     );
  230.                 }
  231.                 $this->flashHelper->addErrorFlash($configuration$exception->getFlash());
  232.                 return $this->redirectHandler->redirectToReferer($configuration);
  233.             }
  234.             if ($configuration->isHtmlRequest()) {
  235.                 $this->flashHelper->addSuccessFlash($configurationResourceActions::UPDATE$resource);
  236.             }
  237.             $postEvent $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE$configuration$resource);
  238.             if (!$configuration->isHtmlRequest()) {
  239.                 $view $configuration->getParameters()->get('return_content'false) ? View::create($resourceResponse::HTTP_OK) : View::create(nullResponse::HTTP_NO_CONTENT);
  240.                 return $this->viewHandler->handle($configuration$view);
  241.             }
  242.             $postEventResponse $postEvent->getResponse();
  243.             if (null !== $postEventResponse) {
  244.                 return $postEventResponse;
  245.             }
  246.             return $this->redirectHandler->redirectToResource($configuration$resource);
  247.         }
  248.         if (!$configuration->isHtmlRequest()) {
  249.             return $this->viewHandler->handle($configurationView::create($formResponse::HTTP_BAD_REQUEST));
  250.         }
  251.         $initializeEvent $this->eventDispatcher->dispatchInitializeEvent(ResourceActions::UPDATE$configuration$resource);
  252.         $initializeEventResponse $initializeEvent->getResponse();
  253.         if (null !== $initializeEventResponse) {
  254.             return $initializeEventResponse;
  255.         }
  256.         $view View::create()
  257.             ->setData([
  258.                 'configuration' => $configuration,
  259.                 'metadata' => $this->metadata,
  260.                 'resource' => $resource,
  261.                 $this->metadata->getName() => $resource,
  262.                 'form' => $form->createView(),
  263.             ])
  264.             ->setTemplate($configuration->getTemplate(ResourceActions::UPDATE '.html'))
  265.         ;
  266.         return $this->viewHandler->handle($configuration$view);
  267.     }
  268.     public function deleteAction(Request $request): Response
  269.     {
  270.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  271.         $this->isGrantedOr403($configurationResourceActions::DELETE);
  272.         $resource $this->findOr404($configuration);
  273.         if ($configuration->isCsrfProtectionEnabled() && !$this->isCsrfTokenValid((string) $resource->getId(), $request->request->get('_csrf_token'))) {
  274.             throw new HttpException(Response::HTTP_FORBIDDEN'Invalid csrf token.');
  275.         }
  276.         $event $this->eventDispatcher->dispatchPreEvent(ResourceActions::DELETE$configuration$resource);
  277.         if ($event->isStopped() && !$configuration->isHtmlRequest()) {
  278.             throw new HttpException($event->getErrorCode(), $event->getMessage());
  279.         }
  280.         if ($event->isStopped()) {
  281.             $this->flashHelper->addFlashFromEvent($configuration$event);
  282.             $eventResponse $event->getResponse();
  283.             if (null !== $eventResponse) {
  284.                 return $eventResponse;
  285.             }
  286.             return $this->redirectHandler->redirectToIndex($configuration$resource);
  287.         }
  288.         try {
  289.             $this->resourceDeleteHandler->handle($resource$this->repository);
  290.         } catch (DeleteHandlingException $exception) {
  291.             if (!$configuration->isHtmlRequest()) {
  292.                 return $this->viewHandler->handle(
  293.                     $configuration,
  294.                     View::create(null$exception->getApiResponseCode())
  295.                 );
  296.             }
  297.             $this->flashHelper->addErrorFlash($configuration$exception->getFlash());
  298.             return $this->redirectHandler->redirectToReferer($configuration);
  299.         }
  300.         if ($configuration->isHtmlRequest()) {
  301.             $this->flashHelper->addSuccessFlash($configurationResourceActions::DELETE$resource);
  302.         }
  303.         $postEvent $this->eventDispatcher->dispatchPostEvent(ResourceActions::DELETE$configuration$resource);
  304.         if (!$configuration->isHtmlRequest()) {
  305.             return $this->viewHandler->handle($configurationView::create(nullResponse::HTTP_NO_CONTENT));
  306.         }
  307.         $postEventResponse $postEvent->getResponse();
  308.         if (null !== $postEventResponse) {
  309.             return $postEventResponse;
  310.         }
  311.         return $this->redirectHandler->redirectToIndex($configuration$resource);
  312.     }
  313.     public function bulkDeleteAction(Request $request): Response
  314.     {
  315.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  316.         $this->isGrantedOr403($configurationResourceActions::BULK_DELETE);
  317.         $resources $this->resourcesCollectionProvider->get($configuration$this->repository);
  318.         if (
  319.             $configuration->isCsrfProtectionEnabled() &&
  320.             !$this->isCsrfTokenValid(ResourceActions::BULK_DELETE$request->request->get('_csrf_token'))
  321.         ) {
  322.             throw new HttpException(Response::HTTP_FORBIDDEN'Invalid csrf token.');
  323.         }
  324.         $this->eventDispatcher->dispatchMultiple(ResourceActions::BULK_DELETE$configuration$resources);
  325.         foreach ($resources as $resource) {
  326.             $event $this->eventDispatcher->dispatchPreEvent(ResourceActions::DELETE$configuration$resource);
  327.             if ($event->isStopped() && !$configuration->isHtmlRequest()) {
  328.                 throw new HttpException($event->getErrorCode(), $event->getMessage());
  329.             }
  330.             if ($event->isStopped()) {
  331.                 $this->flashHelper->addFlashFromEvent($configuration$event);
  332.                 $eventResponse $event->getResponse();
  333.                 if (null !== $eventResponse) {
  334.                     return $eventResponse;
  335.                 }
  336.                 return $this->redirectHandler->redirectToIndex($configuration$resource);
  337.             }
  338.             try {
  339.                 $this->resourceDeleteHandler->handle($resource$this->repository);
  340.             } catch (DeleteHandlingException $exception) {
  341.                 if (!$configuration->isHtmlRequest()) {
  342.                     return $this->viewHandler->handle(
  343.                         $configuration,
  344.                         View::create(null$exception->getApiResponseCode())
  345.                     );
  346.                 }
  347.                 $this->flashHelper->addErrorFlash($configuration$exception->getFlash());
  348.                 return $this->redirectHandler->redirectToReferer($configuration);
  349.             }
  350.             $postEvent $this->eventDispatcher->dispatchPostEvent(ResourceActions::DELETE$configuration$resource);
  351.         }
  352.         if (!$configuration->isHtmlRequest()) {
  353.             return $this->viewHandler->handle($configurationView::create(nullResponse::HTTP_NO_CONTENT));
  354.         }
  355.         $this->flashHelper->addSuccessFlash($configurationResourceActions::BULK_DELETE);
  356.         if (isset($postEvent)) {
  357.             $postEventResponse $postEvent->getResponse();
  358.             if (null !== $postEventResponse) {
  359.                 return $postEventResponse;
  360.             }
  361.         }
  362.         return $this->redirectHandler->redirectToIndex($configuration);
  363.     }
  364.     public function applyStateMachineTransitionAction(Request $request): Response
  365.     {
  366.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  367.         $this->isGrantedOr403($configurationResourceActions::UPDATE);
  368.         $resource $this->findOr404($configuration);
  369.         if ($configuration->isCsrfProtectionEnabled() && !$this->isCsrfTokenValid((string) $resource->getId(), $request->get('_csrf_token'))) {
  370.             throw new HttpException(Response::HTTP_FORBIDDEN'Invalid CSRF token.');
  371.         }
  372.         $event $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE$configuration$resource);
  373.         if ($event->isStopped() && !$configuration->isHtmlRequest()) {
  374.             throw new HttpException($event->getErrorCode(), $event->getMessage());
  375.         }
  376.         if ($event->isStopped()) {
  377.             $this->flashHelper->addFlashFromEvent($configuration$event);
  378.             $eventResponse $event->getResponse();
  379.             if (null !== $eventResponse) {
  380.                 return $eventResponse;
  381.             }
  382.             return $this->redirectHandler->redirectToResource($configuration$resource);
  383.         }
  384.         if (!$this->stateMachine->can($configuration$resource)) {
  385.             throw new BadRequestHttpException();
  386.         }
  387.         try {
  388.             $this->resourceUpdateHandler->handle($resource$configuration$this->manager);
  389.         } catch (UpdateHandlingException $exception) {
  390.             if (!$configuration->isHtmlRequest()) {
  391.                 return $this->viewHandler->handle(
  392.                     $configuration,
  393.                     View::create($resource$exception->getApiResponseCode())
  394.                 );
  395.             }
  396.             $this->flashHelper->addErrorFlash($configuration$exception->getFlash());
  397.             return $this->redirectHandler->redirectToReferer($configuration);
  398.         }
  399.         if ($configuration->isHtmlRequest()) {
  400.             $this->flashHelper->addSuccessFlash($configurationResourceActions::UPDATE$resource);
  401.         }
  402.         $postEvent $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE$configuration$resource);
  403.         if (!$configuration->isHtmlRequest()) {
  404.             $view $configuration->getParameters()->get('return_content'true) ? View::create($resourceResponse::HTTP_OK) : View::create(nullResponse::HTTP_NO_CONTENT);
  405.             return $this->viewHandler->handle($configuration$view);
  406.         }
  407.         $postEventResponse $postEvent->getResponse();
  408.         if (null !== $postEventResponse) {
  409.             return $postEventResponse;
  410.         }
  411.         return $this->redirectHandler->redirectToResource($configuration$resource);
  412.     }
  413.     /**
  414.      * @throws AccessDeniedException
  415.      */
  416.     protected function isGrantedOr403(RequestConfiguration $configurationstring $permission): void
  417.     {
  418.         if (!$configuration->hasPermission()) {
  419.             return;
  420.         }
  421.         $permission $configuration->getPermission($permission);
  422.         if (!$this->authorizationChecker->isGranted($configuration$permission)) {
  423.             throw new AccessDeniedException();
  424.         }
  425.     }
  426.     /**
  427.      * @throws NotFoundHttpException
  428.      */
  429.     protected function findOr404(RequestConfiguration $configuration): ResourceInterface
  430.     {
  431.         if (null === $resource $this->singleResourceProvider->get($configuration$this->repository)) {
  432.             throw new NotFoundHttpException(sprintf('The "%s" has not been found'$this->metadata->getHumanizedName()));
  433.         }
  434.         return $resource;
  435.     }
  436. }