vendor/lightbulb/symfony-common/src/EventSubscriber/ApiRequestPreProcessSubscriber.php line 36

Open in your IDE?
  1. <?php
  2. namespace Lightbulb\Symfony\EventSubscriber;
  3. use Lightbulb\Symfony\Controller\AbstractApiController;
  4. use Lightbulb\Symfony\Controller\RequiredInterface\FormContentTypeRequiredInterface;
  5. use Lightbulb\Symfony\Controller\RequiredInterface\JsonContentTypeRequiredInterface;
  6. use Lightbulb\Symfony\Controller\RequiredInterface\JsonRequestRequiredInterface;
  7. use Lightbulb\Symfony\Exception\ApiErrorException;
  8. use Lightbulb\Symfony\HttpFoundation\Response\NotAcceptableResponse;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. class ApiRequestPreProcessSubscriber implements EventSubscriberInterface
  15. {
  16.     /**
  17.      * {@inheritDoc}
  18.      */
  19.     public static function getSubscribedEvents(): array
  20.     {
  21.         return [
  22.             KernelEvents::CONTROLLER => 'onKernelController',
  23.         ];
  24.     }
  25.     /**
  26.      * @param ControllerEvent $event
  27.      *
  28.      * @return void
  29.      *
  30.      * @throws ApiErrorException
  31.      */
  32.     public function onKernelController(ControllerEvent $event): void
  33.     {
  34.         $controller $event->getController();
  35.         // when a controller class defines multiple action methods, the controller
  36.         // is returned as [$controllerInstance, 'methodName']
  37.         if (is_array($controller)) {
  38.             $controller $controller[0];
  39.         }
  40.         if ($controller instanceof AbstractApiController) {
  41.             $this->checkRequirements($controller$event->getRequest());
  42.         }
  43.     }
  44.     /**
  45.      * @param AbstractController $controller
  46.      * @param Request $request
  47.      *
  48.      * @return void
  49.      *
  50.      * @throws ApiErrorException
  51.      */
  52.     private function checkRequirements(AbstractController $controllerRequest $request): void
  53.     {
  54.         $this->checkControllerForRequirement(
  55.             $controller,
  56.             $request,
  57.             JsonRequestRequiredInterface::class,
  58.             'Accept',
  59.             ['json''application/json'],
  60.             ['GET''POST''PUT''PATCH''DELETE']
  61.         );
  62.         $this->checkControllerForRequirement(
  63.             $controller,
  64.             $request,
  65.             JsonContentTypeRequiredInterface::class,
  66.             'Content-type',
  67.             ['json''application/json'],
  68.             ['POST''PUT''PATCH'],
  69.             true
  70.         );
  71.         $this->checkControllerForRequirement(
  72.             $controller,
  73.             $request,
  74.             FormContentTypeRequiredInterface::class,
  75.             'Content-type',
  76.             ['multipart/form-data'],
  77.             ['POST''PUT''PATCH'],
  78.             true
  79.         );
  80.     }
  81.     /**
  82.      * @param AbstractController $controller
  83.      * @param Request $request
  84.      * @param string $interface
  85.      * @param string $headerType
  86.      * @param array $contentTypes
  87.      * @param array $applicableMethods
  88.      * @param bool $requestMustHaveContent
  89.      *
  90.      * @return void
  91.      *
  92.      * @throws ApiErrorException
  93.      */
  94.     private function checkControllerForRequirement(
  95.         AbstractController $controller,
  96.         Request $request,
  97.         string $interface,
  98.         string $headerType,
  99.         array $contentTypes,
  100.         array $applicableMethods,
  101.         bool $requestMustHaveContent false
  102.     ): void {
  103.         if ($controller instanceof $interface && in_array($request->getMethod(), $applicableMethods)) {
  104.             if (true === $requestMustHaveContent && true === empty($request->getContent())) {
  105.                 $validContentType true;
  106.             } else {
  107.                 $validContentType false;
  108.                 foreach ($contentTypes as $contentType) {
  109.                     if (
  110.                         $request->headers->has($headerType) &&
  111.                         false !== strpos($request->headers->get($headerType), $contentType)
  112.                     ) {
  113.                         $validContentType true;
  114.                         break;
  115.                     }
  116.                 }
  117.             }
  118.             if (false === $validContentType) {
  119.                 $message sprintf(
  120.                     'The API call needs to have a valid %s header (%s)! %s was given!',
  121.                     $headerType,
  122.                     implode(', '$contentTypes),
  123.                     $request->headers->get($headerType) ?? 'Nothing'
  124.                 );
  125.                 throw new ApiErrorException(new NotAcceptableResponse($message));
  126.             }
  127.         }
  128.     }
  129. }