vendor/contao/core-bundle/src/Image/Studio/ImageResult.php line 161

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of Contao.
  5.  *
  6.  * (c) Leo Feyer
  7.  *
  8.  * @license LGPL-3.0-or-later
  9.  */
  10. namespace Contao\CoreBundle\Image\Studio;
  11. use Contao\CoreBundle\Image\ImageFactoryInterface;
  12. use Contao\CoreBundle\Image\PictureFactory;
  13. use Contao\CoreBundle\Image\PictureFactoryInterface;
  14. use Contao\Image\DeferredImageInterface;
  15. use Contao\Image\DeferredResizerInterface;
  16. use Contao\Image\Image;
  17. use Contao\Image\ImageDimensions;
  18. use Contao\Image\ImageInterface;
  19. use Contao\Image\PictureConfiguration;
  20. use Contao\Image\PictureInterface;
  21. use Contao\Image\ResizeOptions;
  22. use Psr\Container\ContainerInterface;
  23. use Webmozart\PathUtil\Path;
  24. class ImageResult
  25. {
  26.     /**
  27.      * @var ContainerInterface
  28.      */
  29.     private $locator;
  30.     /**
  31.      * @var string|ImageInterface
  32.      */
  33.     private $filePathOrImageInterface;
  34.     /**
  35.      * @var int|string|array|PictureConfiguration|null
  36.      */
  37.     private $sizeConfiguration;
  38.     /**
  39.      * @var ResizeOptions|null
  40.      */
  41.     private $resizeOptions;
  42.     /**
  43.      * Cached picture.
  44.      *
  45.      * @var PictureInterface|null
  46.      */
  47.     private $picture;
  48.     /**
  49.      * Cached image dimensions.
  50.      *
  51.      * @var ImageDimensions|null
  52.      */
  53.     private $originalDimensions;
  54.     /**
  55.      * @var string
  56.      */
  57.     private $projectDir;
  58.     /**
  59.      * @param string|ImageInterface                      $filePathOrImage
  60.      * @param array|PictureConfiguration|int|string|null $sizeConfiguration
  61.      *
  62.      * @internal Use the Contao\CoreBundle\Image\Studio\Studio factory to get an instance of this class
  63.      */
  64.     public function __construct(ContainerInterface $locatorstring $projectDir$filePathOrImage$sizeConfiguration nullResizeOptions $resizeOptions null)
  65.     {
  66.         $this->locator $locator;
  67.         $this->projectDir $projectDir;
  68.         $this->filePathOrImageInterface $filePathOrImage;
  69.         $this->sizeConfiguration $sizeConfiguration;
  70.         $this->resizeOptions $resizeOptions;
  71.     }
  72.     /**
  73.      * Creates a picture with the defined size configuration.
  74.      */
  75.     public function getPicture(): PictureInterface
  76.     {
  77.         if (null !== $this->picture) {
  78.             return $this->picture;
  79.         }
  80.         // Unlike the Contao\Image\PictureFactory the PictureFactoryInterface
  81.         // does not know about ResizeOptions. We therefore check if the third
  82.         // argument of the 'create' method allows setting them.
  83.         $canHandleResizeOptions = static function (PictureFactoryInterface $factory): bool {
  84.             if ($factory instanceof PictureFactory) {
  85.                 return true;
  86.             }
  87.             $createParameters = (new \ReflectionClass($factory))
  88.                 ->getMethod('create')
  89.                 ->getParameters()
  90.             ;
  91.             if (!isset($createParameters[2])) {
  92.                 return false;
  93.             }
  94.             $type $createParameters[2]->getType();
  95.             return $type instanceof \ReflectionNamedType && ResizeOptions::class === $type->getName();
  96.         };
  97.         $factory $this->pictureFactory();
  98.         $arguments = [$this->filePathOrImageInterface$this->sizeConfiguration];
  99.         if (null !== $this->resizeOptions && $canHandleResizeOptions($factory)) {
  100.             $arguments[] = $this->resizeOptions;
  101.         }
  102.         return $this->picture $this->pictureFactory()->create(...$arguments);
  103.     }
  104.     /**
  105.      * Returns the "sources" part of the current picture.
  106.      */
  107.     public function getSources(): array
  108.     {
  109.         return $this->getPicture()->getSources($this->projectDir$this->staticUrl());
  110.     }
  111.     /**
  112.      * Returns the "img" part of the current picture.
  113.      */
  114.     public function getImg(): array
  115.     {
  116.         return $this->getPicture()->getImg($this->projectDir$this->staticUrl());
  117.     }
  118.     /**
  119.      * Returns the "src" attribute of the image. This will return a URL by
  120.      * default. Set $asPath to true to get a relative file path instead.
  121.      */
  122.     public function getImageSrc(bool $asPath false): string
  123.     {
  124.         if ($asPath) {
  125.             /** @var Image $image */
  126.             $image $this->getPicture()->getImg()['src'];
  127.             return Path::makeRelative($image->getPath(), $this->projectDir);
  128.         }
  129.         return $this->getImg()['src'] ?? '';
  130.     }
  131.     /**
  132.      * Returns the image dimensions of the base resource.
  133.      */
  134.     public function getOriginalDimensions(): ImageDimensions
  135.     {
  136.         if (null !== $this->originalDimensions) {
  137.             return $this->originalDimensions;
  138.         }
  139.         if ($this->filePathOrImageInterface instanceof ImageInterface) {
  140.             return $this->originalDimensions $this->filePathOrImageInterface->getDimensions();
  141.         }
  142.         return $this->originalDimensions $this
  143.             ->imageFactory()
  144.             ->create($this->filePathOrImageInterface)
  145.             ->getDimensions()
  146.         ;
  147.     }
  148.     /**
  149.      * Returns the file path of the base resource.
  150.      *
  151.      * Set $absolute to true to return an absolute path instead of a path
  152.      * relative to the project dir.
  153.      */
  154.     public function getFilePath($absolute false): string
  155.     {
  156.         $path $this->filePathOrImageInterface instanceof ImageInterface
  157.             $this->filePathOrImageInterface->getPath()
  158.             : $this->filePathOrImageInterface;
  159.         return $absolute $path Path::makeRelative($path$this->projectDir);
  160.     }
  161.     /**
  162.      * Synchronously processes images if they are deferred.
  163.      *
  164.      * This will make sure that the target files physically exist instead of
  165.      * being generated by the Contao\CoreBundle\Controller\ImagesController
  166.      * on first access.
  167.      */
  168.     public function createIfDeferred(): void
  169.     {
  170.         $picture $this->getPicture();
  171.         $candidates = [];
  172.         foreach (array_merge([$picture->getImg()], $picture->getSources()) as $source) {
  173.             $candidates[] = $source['src'] ?? null;
  174.             foreach ($source['srcset'] ?? [] as $srcset) {
  175.                 $candidates[] = $srcset[0] ?? null;
  176.             }
  177.         }
  178.         $deferredImages array_filter(
  179.             $candidates,
  180.             static function ($image): bool {
  181.                 return $image instanceof DeferredImageInterface;
  182.             }
  183.         );
  184.         if (empty($deferredImages)) {
  185.             return;
  186.         }
  187.         $resizer $this->locator->get('contao.image.resizer');
  188.         if (!$resizer instanceof DeferredResizerInterface) {
  189.             throw new \RuntimeException('The "contao.image.resizer" service does not support deferred resizing.');
  190.         }
  191.         foreach ($deferredImages as $deferredImage) {
  192.             $resizer->resizeDeferredImage($deferredImage);
  193.         }
  194.     }
  195.     private function imageFactory(): ImageFactoryInterface
  196.     {
  197.         return $this->locator->get('contao.image.image_factory');
  198.     }
  199.     private function pictureFactory(): PictureFactoryInterface
  200.     {
  201.         return $this->locator->get('contao.image.picture_factory');
  202.     }
  203.     private function staticUrl(): string
  204.     {
  205.         return $this->locator->get('contao.assets.files_context')->getStaticUrl();
  206.     }
  207. }