src/Bundles/Liip/ImagineBundle/Controller/AppImagineController.php line 147

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the `liip/LiipImagineBundle` project.
  4.  *
  5.  * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE.md
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace App\Bundles\Liip\ImagineBundle\Controller;
  11. use App\Bundles\Liip\ImagineBundle\Cache\Resolver\AzureCacheResolver;
  12. use Imagine\Exception\RuntimeException;
  13. use Liip\ImagineBundle\Config\Controller\ControllerConfig;
  14. use Liip\ImagineBundle\Controller\ImagineController as ImagineController;
  15. use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
  16. use Liip\ImagineBundle\Exception\Imagine\Filter\NonExistingFilterException;
  17. use Liip\ImagineBundle\Imagine\Cache\Helper\PathHelper;
  18. use Liip\ImagineBundle\Imagine\Cache\SignerInterface;
  19. use Liip\ImagineBundle\Imagine\Data\DataManager;
  20. use Liip\ImagineBundle\Service\FilterService;
  21. use Symfony\Component\HttpFoundation\Exception\BadRequestException;
  22. use Symfony\Component\HttpFoundation\RedirectResponse;
  23. use Symfony\Component\HttpFoundation\Request;
  24. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  25. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  26. use Symfony\Component\HttpKernel\Kernel;
  27. class AppImagineController extends ImagineController
  28. {
  29.     /**
  30.      * @var FilterService
  31.      */
  32.     private $filterService;
  33.     /**
  34.      * @var DataManager
  35.      */
  36.     private $dataManager;
  37.     /**
  38.      * @var SignerInterface
  39.      */
  40.     private $signer;
  41.     /**
  42.      * @var ControllerConfig
  43.      */
  44.     private $controllerConfig;
  45.     private AzureCacheResolver $azureCacheResolver;
  46.     /**
  47.      * @param FilterService   $filterService
  48.      * @param DataManager     $dataManager
  49.      * @param SignerInterface $signer
  50.      */
  51.     public function __construct(
  52.         FilterService $filterService,
  53.         DataManager $dataManager,
  54.         SignerInterface $signer,
  55.         ?ControllerConfig $controllerConfig null,
  56.         AzureCacheResolver $azureCacheResolver null
  57.     )
  58.     {
  59.         $this->filterService $filterService;
  60.         $this->dataManager $dataManager;
  61.         $this->signer $signer;
  62.         $this->controllerConfig $controllerConfig ?: new ControllerConfig(301);
  63.         $this->azureCacheResolver $azureCacheResolver;
  64.     }
  65.     /**
  66.      * This action applies a given filter to a given image, saves the image and redirects the browser to the stored
  67.      * image.
  68.      *
  69.      * The resulting image is cached so subsequent requests will redirect to the cached image instead applying the
  70.      * filter and storing the image again.
  71.      *
  72.      * @param Request $request
  73.      * @param string  $path
  74.      * @param string  $filter
  75.      *
  76.      * @throws RuntimeException
  77.      * @throws NotFoundHttpException
  78.      *
  79.      * @return RedirectResponse
  80.      */
  81.     public function filterAction(Request $request$path$filter)
  82.     {
  83.         $path PathHelper::urlPathToFilePath($path);
  84.         $resolver 'azure_cache_resolver';
  85.         return $this->createRedirectResponse(function () use ($path$filter$resolver$request) {
  86.             return $this->filterService->getUrlOfFilteredImage(
  87.                 $path,
  88.                 $filter,
  89.                 $resolver,
  90.                 $this->isWebpSupported($request)
  91.             );
  92.         }, $path$filter);
  93.     }
  94.     private function isWebpSupported(Request $request): bool
  95.     {
  96.         return false !== mb_stripos($request->headers->get('accept'''), 'image/webp');
  97.     }
  98.     private function createRedirectResponse(\Closure $urlstring $pathstring $filter, ?string $hash null): RedirectResponse
  99.     {
  100.         try {
  101.             return new RedirectResponse($url(), $this->controllerConfig->getRedirectResponseCode());
  102.         } catch (NotLoadableException $exception) {
  103.             if (null !== $this->dataManager->getDefaultImageUrl($filter)) {
  104.                 return new RedirectResponse($this->dataManager->getDefaultImageUrl($filter));
  105.             }
  106.             throw new NotFoundHttpException(\sprintf('Source image for path "%s" could not be found'$path), $exception);
  107.         } catch (NonExistingFilterException $exception) {
  108.             throw new NotFoundHttpException(\sprintf('Requested non-existing filter "%s"'$filter), $exception);
  109.         } catch (RuntimeException $exception) {
  110.             throw new \RuntimeException(vsprintf('Unable to create image for path "%s" and filter "%s". Message was "%s"', [$hash \sprintf('%s/%s'$hash$path) : $path$filter$exception->getMessage()]), 0$exception);
  111.         }
  112.     }
  113.     /**
  114.      * This action applies a given filter -merged with additional runtime filters- to a given image, saves the image and
  115.      * redirects the browser to the stored image.
  116.      *
  117.      * The resulting image is cached so subsequent requests will redirect to the cached image instead applying the
  118.      * filter and storing the image again.
  119.      *
  120.      * @param Request $request
  121.      * @param string  $hash
  122.      * @param string  $path
  123.      * @param string  $filter
  124.      *
  125.      * @throws RuntimeException
  126.      * @throws BadRequestHttpException
  127.      * @throws NotFoundHttpException
  128.      *
  129.      * @return RedirectResponse
  130.      */
  131.     public function filterRuntimeAction(Request $request$hash$path$filter)
  132.     {
  133.         $resolver 'azure_cache_resolver';
  134.         $path PathHelper::urlPathToFilePath($path);
  135.         $runtimeConfig $this->getFiltersBc($request);
  136.         if (true !== $this->signer->check($hash$path$runtimeConfig)) {
  137.             throw new BadRequestHttpException(\sprintf('Signed url does not pass the sign check for path "%s" and filter "%s" and runtime config %s'$path$filterjson_encode($runtimeConfig)));
  138.         }
  139.         return $this->createRedirectResponse(function () use ($path$filter$runtimeConfig$resolver$request) {
  140.             return $this->filterService->getUrlOfFilteredImageWithRuntimeFilters(
  141.                 $path,
  142.                 $filter,
  143.                 $runtimeConfig,
  144.                 $resolver,
  145.                 $this->isWebpSupported($request)
  146.             );
  147.         }, $path$filter$hash);
  148.     }
  149.     private function getFiltersBc(Request $request): array
  150.     {
  151.         if (version_compare(Kernel::VERSION'5.1''>=')) {
  152.             try {
  153.                 return $request->query->all('filters');
  154.             } catch (BadRequestException $e) {
  155.                 // for strict BC - BadRequestException seems more suited to this situation.
  156.                 // remove the try-catch in version 3
  157.                 throw new NotFoundHttpException(\sprintf('Filters must be an array. Value was "%s"'$request->query->get('filters')));
  158.             }
  159.         }
  160.         $runtimeConfig $request->query->get('filters', []);
  161.         if (!\is_array($runtimeConfig)) {
  162.             throw new NotFoundHttpException(\sprintf('Filters must be an array. Value was "%s"'$runtimeConfig));
  163.         }
  164.         return $runtimeConfig;
  165.     }
  166. }