vendor/pimcore/pimcore/models/Asset/Image/Thumbnail/Config.php line 169

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Model\Asset\Image\Thumbnail;
  15. use Pimcore\Cache\RuntimeCache;
  16. use Pimcore\Logger;
  17. use Pimcore\Model;
  18. use Pimcore\Tool\Serialize;
  19. /**
  20.  * @method bool isWriteable()
  21.  * @method string getWriteTarget()
  22.  * @method void delete(bool $forceClearTempFiles = false)
  23.  * @method void save(bool $forceClearTempFiles = false)
  24.  */
  25. final class Config extends Model\AbstractModel
  26. {
  27.     use Model\Asset\Thumbnail\ClearTempFilesTrait;
  28.     /**
  29.      * @internal
  30.      */
  31.     protected const PREVIEW_THUMBNAIL_NAME 'pimcore-system-treepreview';
  32.     /**
  33.      * format of array:
  34.      * array(
  35.      array(
  36.      "method" => "myName",
  37.      "arguments" =>
  38.      array(
  39.      "width" => 345,
  40.      "height" => 200
  41.      )
  42.      )
  43.      * )
  44.      *
  45.      * @internal
  46.      *
  47.      * @var array
  48.      */
  49.     protected $items = [];
  50.     /**
  51.      * @internal
  52.      *
  53.      * @var array
  54.      */
  55.     protected $medias = [];
  56.     /**
  57.      * @internal
  58.      *
  59.      * @var string
  60.      */
  61.     protected $name '';
  62.     /**
  63.      * @internal
  64.      *
  65.      * @var string
  66.      */
  67.     protected $description '';
  68.     /**
  69.      * @internal
  70.      *
  71.      * @var string
  72.      */
  73.     protected $group '';
  74.     /**
  75.      * @internal
  76.      *
  77.      * @var string
  78.      */
  79.     protected $format 'SOURCE';
  80.     /**
  81.      * @internal
  82.      *
  83.      * @var int
  84.      */
  85.     protected $quality 85;
  86.     /**
  87.      * @internal
  88.      *
  89.      * @var float|null
  90.      */
  91.     protected $highResolution;
  92.     /**
  93.      * @internal
  94.      *
  95.      * @var bool
  96.      */
  97.     protected $preserveColor false;
  98.     /**
  99.      * @internal
  100.      *
  101.      * @var bool
  102.      */
  103.     protected $preserveMetaData false;
  104.     /**
  105.      * @internal
  106.      *
  107.      * @var bool
  108.      */
  109.     protected $rasterizeSVG false;
  110.     /**
  111.      * @internal
  112.      *
  113.      * @var bool
  114.      */
  115.     protected $downloadable false;
  116.     /**
  117.      * @internal
  118.      *
  119.      * @var int|null
  120.      */
  121.     protected $modificationDate;
  122.     /**
  123.      * @internal
  124.      *
  125.      * @var int|null
  126.      */
  127.     protected $creationDate;
  128.     /**
  129.      * @internal
  130.      *
  131.      * @var string|null
  132.      */
  133.     protected $filenameSuffix;
  134.     /**
  135.      * @internal
  136.      *
  137.      * @var bool
  138.      */
  139.     protected $preserveAnimation false;
  140.     /**
  141.      * @internal
  142.      *
  143.      * @param string|array|self $config
  144.      *
  145.      * @return self|null
  146.      */
  147.     public static function getByAutoDetect($config)
  148.     {
  149.         $thumbnail null;
  150.         if (is_string($config)) {
  151.             try {
  152.                 $thumbnail self::getByName($config);
  153.             } catch (\Exception $e) {
  154.                 Logger::error('requested thumbnail ' $config ' is not defined');
  155.                 return null;
  156.             }
  157.         } elseif (is_array($config)) {
  158.             // check if it is a legacy config or a new one
  159.             if (array_key_exists('items'$config)) {
  160.                 $thumbnail self::getByArrayConfig($config);
  161.             } else {
  162.                 $thumbnail self::getByLegacyConfig($config);
  163.             }
  164.         } elseif ($config instanceof self) {
  165.             $thumbnail $config;
  166.         }
  167.         return $thumbnail;
  168.     }
  169.     /**
  170.      * @param string $name
  171.      *
  172.      * @return null|Config
  173.      *
  174.      * @throws \Exception
  175.      */
  176.     public static function getByName($name)
  177.     {
  178.         $cacheKey self::getCacheKey($name);
  179.         if ($name === self::PREVIEW_THUMBNAIL_NAME) {
  180.             return self::getPreviewConfig();
  181.         }
  182.         try {
  183.             $thumbnail RuntimeCache::get($cacheKey);
  184.             if (!$thumbnail) {
  185.                 throw new \Exception('Thumbnail in registry is null');
  186.             }
  187.             $thumbnail->setName($name);
  188.         } catch (\Exception $e) {
  189.             try {
  190.                 $thumbnail = new self();
  191.                 /** @var Model\Asset\Image\Thumbnail\Config\Dao $dao */
  192.                 $dao $thumbnail->getDao();
  193.                 $dao->getByName($name);
  194.                 RuntimeCache::set($cacheKey$thumbnail);
  195.             } catch (Model\Exception\NotFoundException $e) {
  196.                 return null;
  197.             }
  198.         }
  199.         // only return clones of configs, this is necessary since we cache the configs in the registry (see above)
  200.         // sometimes, e.g. when using the cropping tools, the thumbnail configuration is modified on-the-fly, since
  201.         // pass-by-reference this modifications would then go to the cache/registry (singleton), by cloning the config
  202.         // we can bypass this problem in an elegant way without parsing the XML config again and again
  203.         $clone = clone $thumbnail;
  204.         return $clone;
  205.     }
  206.     /**
  207.      * @param string $name
  208.      *
  209.      * @return string
  210.      */
  211.     protected static function getCacheKey(string $name): string
  212.     {
  213.         return 'imagethumb_' crc32($name);
  214.     }
  215.     /**
  216.      * @param string $name
  217.      *
  218.      * @return bool
  219.      */
  220.     public static function exists(string $name): bool
  221.     {
  222.         $cacheKey self::getCacheKey($name);
  223.         if (RuntimeCache::isRegistered($cacheKey)) {
  224.             return true;
  225.         }
  226.         if ($name === self::PREVIEW_THUMBNAIL_NAME) {
  227.             return true;
  228.         }
  229.         return (bool) self::getByName($name);
  230.     }
  231.     /**
  232.      * @internal
  233.      *
  234.      * @return Config
  235.      */
  236.     public static function getPreviewConfig()
  237.     {
  238.         $customPreviewImageThumbnail \Pimcore::getContainer()->getParameter('pimcore.config')['assets']['preview_image_thumbnail'];
  239.         $thumbnail null;
  240.         if ($customPreviewImageThumbnail) {
  241.             $thumbnail self::getByName($customPreviewImageThumbnail);
  242.         }
  243.         if (!$thumbnail) {
  244.             $thumbnail = new self();
  245.             $thumbnail->setName(self::PREVIEW_THUMBNAIL_NAME);
  246.             $thumbnail->addItem('scaleByWidth', [
  247.                 'width' => 400,
  248.             ]);
  249.             $thumbnail->addItem('setBackgroundImage', [
  250.                 'path' => '/bundles/pimcoreadmin/img/tree-preview-transparent-background.png',
  251.                 'mode' => 'asTexture',
  252.             ]);
  253.             $thumbnail->setQuality(60);
  254.             $thumbnail->setFormat('PJPEG');
  255.         }
  256.         $thumbnail->setHighResolution(2);
  257.         return $thumbnail;
  258.     }
  259.     /**
  260.      * @param string $name
  261.      */
  262.     protected function createMediaIfNotExists($name)
  263.     {
  264.         if (!array_key_exists($name$this->medias)) {
  265.             $this->medias[$name] = [];
  266.         }
  267.     }
  268.     /**
  269.      * @internal
  270.      *
  271.      * @param string|callable $name
  272.      * @param array $parameters
  273.      * @param string|null $media
  274.      *
  275.      * @return bool
  276.      */
  277.     public function addItem($name$parameters$media null)
  278.     {
  279.         $item = [
  280.             'method' => $name,
  281.             'arguments' => $parameters,
  282.         ];
  283.         // default is added to $this->items for compatibility reasons
  284.         if (!$media || $media == 'default') {
  285.             $this->items[] = $item;
  286.         } else {
  287.             $this->createMediaIfNotExists($media);
  288.             $this->medias[$media][] = $item;
  289.         }
  290.         return true;
  291.     }
  292.     /**
  293.      * @internal
  294.      *
  295.      * @param int $position
  296.      * @param string|callable $name
  297.      * @param array $parameters
  298.      * @param string|null $media
  299.      *
  300.      * @return bool
  301.      */
  302.     public function addItemAt($position$name$parameters$media null)
  303.     {
  304.         if (!$media || $media == 'default') {
  305.             $itemContainer = &$this->items;
  306.         } else {
  307.             $this->createMediaIfNotExists($media);
  308.             $itemContainer = &$this->medias[$media];
  309.         }
  310.         array_splice($itemContainer$position0, [[
  311.             'method' => $name,
  312.             'arguments' => $parameters,
  313.         ]]);
  314.         return true;
  315.     }
  316.     /**
  317.      * @internal
  318.      */
  319.     public function resetItems()
  320.     {
  321.         $this->items = [];
  322.         $this->medias = [];
  323.     }
  324.     /**
  325.      * @param string $name
  326.      *
  327.      * @return bool
  328.      */
  329.     public function selectMedia($name)
  330.     {
  331.         if (preg_match('/^[0-9a-f]{8}$/'$name)) {
  332.             $hash $name;
  333.         } else {
  334.             $hash hash('crc32b'$name);
  335.         }
  336.         foreach ($this->medias as $key => $value) {
  337.             $currentHash hash('crc32b'$key);
  338.             if ($key === $name || $currentHash === $hash) {
  339.                 $this->setItems($value);
  340.                 $this->setFilenameSuffix('media--' $currentHash '--query');
  341.                 return true;
  342.             }
  343.         }
  344.         return false;
  345.     }
  346.     /**
  347.      * @param string $description
  348.      *
  349.      * @return $this
  350.      */
  351.     public function setDescription($description)
  352.     {
  353.         $this->description $description;
  354.         return $this;
  355.     }
  356.     /**
  357.      * @return string
  358.      */
  359.     public function getDescription()
  360.     {
  361.         return $this->description;
  362.     }
  363.     /**
  364.      * @param array $items
  365.      *
  366.      * @return $this
  367.      */
  368.     public function setItems($items)
  369.     {
  370.         $this->items $items;
  371.         return $this;
  372.     }
  373.     /**
  374.      * @return array
  375.      */
  376.     public function getItems()
  377.     {
  378.         return $this->items;
  379.     }
  380.     /**
  381.      * @param string $name
  382.      *
  383.      * @return $this
  384.      */
  385.     public function setName($name)
  386.     {
  387.         $this->name $name;
  388.         return $this;
  389.     }
  390.     /**
  391.      * @return string
  392.      */
  393.     public function getName()
  394.     {
  395.         return $this->name;
  396.     }
  397.     /**
  398.      * @param string $format
  399.      *
  400.      * @return $this
  401.      */
  402.     public function setFormat($format)
  403.     {
  404.         $this->format $format;
  405.         return $this;
  406.     }
  407.     /**
  408.      * @return string
  409.      */
  410.     public function getFormat()
  411.     {
  412.         return $this->format;
  413.     }
  414.     /**
  415.      * @param int $quality
  416.      *
  417.      * @return $this
  418.      */
  419.     public function setQuality($quality)
  420.     {
  421.         if ($quality) {
  422.             $this->quality = (int) $quality;
  423.         }
  424.         return $this;
  425.     }
  426.     /**
  427.      * @return int
  428.      */
  429.     public function getQuality()
  430.     {
  431.         return $this->quality;
  432.     }
  433.     /**
  434.      * @param float|null $highResolution
  435.      */
  436.     public function setHighResolution($highResolution)
  437.     {
  438.         $this->highResolution = (float) $highResolution;
  439.     }
  440.     /**
  441.      * @return float|null
  442.      */
  443.     public function getHighResolution()
  444.     {
  445.         return $this->highResolution;
  446.     }
  447.     /**
  448.      * @param array $medias
  449.      */
  450.     public function setMedias($medias)
  451.     {
  452.         $this->medias $medias;
  453.     }
  454.     /**
  455.      * @return array
  456.      */
  457.     public function getMedias()
  458.     {
  459.         return $this->medias;
  460.     }
  461.     /**
  462.      * @return bool
  463.      */
  464.     public function hasMedias()
  465.     {
  466.         return !empty($this->medias);
  467.     }
  468.     /**
  469.      * @param string $filenameSuffix
  470.      */
  471.     public function setFilenameSuffix($filenameSuffix)
  472.     {
  473.         $this->filenameSuffix $filenameSuffix;
  474.     }
  475.     /**
  476.      * @return string|null
  477.      */
  478.     public function getFilenameSuffix()
  479.     {
  480.         return $this->filenameSuffix;
  481.     }
  482.     /**
  483.      * @internal
  484.      *
  485.      * @param array $config
  486.      *
  487.      * @return self
  488.      */
  489.     public static function getByArrayConfig($config)
  490.     {
  491.         $pipe = new self();
  492.         if (isset($config['format']) && $config['format']) {
  493.             $pipe->setFormat($config['format']);
  494.         }
  495.         if (isset($config['quality']) && $config['quality']) {
  496.             $pipe->setQuality($config['quality']);
  497.         }
  498.         if (isset($config['items']) && $config['items']) {
  499.             $pipe->setItems($config['items']);
  500.         }
  501.         if (isset($config['highResolution']) && $config['highResolution']) {
  502.             $pipe->setHighResolution($config['highResolution']);
  503.         }
  504.         // set name
  505.         $pipe->generateAutoName();
  506.         return $pipe;
  507.     }
  508.     /**
  509.      * This is mainly here for backward compatibility
  510.      *
  511.      * @internal
  512.      *
  513.      * @param array $config
  514.      *
  515.      * @return self
  516.      */
  517.     public static function getByLegacyConfig($config)
  518.     {
  519.         $pipe = new self();
  520.         if (isset($config['format'])) {
  521.             $pipe->setFormat($config['format']);
  522.         }
  523.         if (isset($config['quality'])) {
  524.             $pipe->setQuality($config['quality']);
  525.         }
  526.         if (isset($config['cover'])) {
  527.             $pipe->addItem('cover', [
  528.                 'width' => $config['width'],
  529.                 'height' => $config['height'],
  530.                 'positioning' => ((isset($config['positioning']) && !empty($config['positioning'])) ? (string)$config['positioning'] : 'center'),
  531.                 'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  532.             ]);
  533.         } elseif (isset($config['contain'])) {
  534.             $pipe->addItem('contain', [
  535.                 'width' => $config['width'],
  536.                 'height' => $config['height'],
  537.                 'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  538.             ]);
  539.         } elseif (isset($config['frame'])) {
  540.             $pipe->addItem('frame', [
  541.                 'width' => $config['width'],
  542.                 'height' => $config['height'],
  543.                 'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  544.             ]);
  545.         } elseif (isset($config['aspectratio']) && $config['aspectratio']) {
  546.             if (isset($config['height']) && isset($config['width']) && $config['height'] > && $config['width'] > 0) {
  547.                 $pipe->addItem('contain', [
  548.                     'width' => $config['width'],
  549.                     'height' => $config['height'],
  550.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  551.                 ]);
  552.             } elseif (isset($config['height']) && $config['height'] > 0) {
  553.                 $pipe->addItem('scaleByHeight', [
  554.                     'height' => $config['height'],
  555.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  556.                 ]);
  557.             } else {
  558.                 $pipe->addItem('scaleByWidth', [
  559.                     'width' => $config['width'],
  560.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  561.                 ]);
  562.             }
  563.         } else {
  564.             if (!isset($config['width']) && isset($config['height'])) {
  565.                 $pipe->addItem('scaleByHeight', [
  566.                     'height' => $config['height'],
  567.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  568.                 ]);
  569.             } elseif (isset($config['width']) && !isset($config['height'])) {
  570.                 $pipe->addItem('scaleByWidth', [
  571.                     'width' => $config['width'],
  572.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  573.                 ]);
  574.             } elseif (isset($config['width']) && isset($config['height'])) {
  575.                 $pipe->addItem('resize', [
  576.                     'width' => $config['width'],
  577.                     'height' => $config['height'],
  578.                 ]);
  579.             }
  580.         }
  581.         if (isset($config['highResolution'])) {
  582.             $pipe->setHighResolution($config['highResolution']);
  583.         }
  584.         $pipe->generateAutoName();
  585.         return $pipe;
  586.     }
  587.     /**
  588.      * @internal
  589.      *
  590.      * @param Model\Asset\Image $asset
  591.      *
  592.      * @return array
  593.      */
  594.     public function getEstimatedDimensions($asset)
  595.     {
  596.         $originalWidth $asset->getWidth();
  597.         $originalHeight $asset->getHeight();
  598.         $dimensions = [
  599.             'width' => $originalWidth,
  600.             'height' => $originalHeight,
  601.         ];
  602.         $transformations $this->getItems();
  603.         if (is_array($transformations) && count($transformations) > 0) {
  604.             if ($originalWidth && $originalHeight) {
  605.                 foreach ($transformations as $transformation) {
  606.                     if (!empty($transformation)) {
  607.                         $arg $transformation['arguments'];
  608.                         $forceResize false;
  609.                         if (isset($arg['forceResize']) && $arg['forceResize'] === true) {
  610.                             $forceResize true;
  611.                         }
  612.                         if (in_array($transformation['method'], ['resize''cover''frame''crop'])) {
  613.                             $dimensions['width'] = $arg['width'];
  614.                             $dimensions['height'] = $arg['height'];
  615.                         } elseif ($transformation['method'] == '1x1_pixel') {
  616.                             return [
  617.                                 'width' => 1,
  618.                                 'height' => 1,
  619.                             ];
  620.                         } elseif ($transformation['method'] == 'scaleByWidth') {
  621.                             if ($arg['width'] <= $dimensions['width'] || $asset->isVectorGraphic() || $forceResize) {
  622.                                 $dimensions['height'] = round(($arg['width'] / $dimensions['width']) * $dimensions['height'], 0);
  623.                                 $dimensions['width'] = $arg['width'];
  624.                             }
  625.                         } elseif ($transformation['method'] == 'scaleByHeight') {
  626.                             if ($arg['height'] < $dimensions['height'] || $asset->isVectorGraphic() || $forceResize) {
  627.                                 $dimensions['width'] = round(($arg['height'] / $dimensions['height']) * $dimensions['width'], 0);
  628.                                 $dimensions['height'] = $arg['height'];
  629.                             }
  630.                         } elseif ($transformation['method'] == 'contain') {
  631.                             $x $dimensions['width'] / $arg['width'];
  632.                             $y $dimensions['height'] / $arg['height'];
  633.                             if (!$forceResize && $x <= && $y <= && !$asset->isVectorGraphic()) {
  634.                                 continue;
  635.                             }
  636.                             if ($x $y) {
  637.                                 $dimensions['height'] = round(($arg['width'] / $dimensions['width']) * $dimensions['height'], 0);
  638.                                 $dimensions['width'] = $arg['width'];
  639.                             } else {
  640.                                 $dimensions['width'] = round(($arg['height'] / $dimensions['height']) * $dimensions['width'], 0);
  641.                                 $dimensions['height'] = $arg['height'];
  642.                             }
  643.                         } elseif ($transformation['method'] == 'cropPercent') {
  644.                             $dimensions['width'] = ceil($dimensions['width'] * ($arg['width'] / 100));
  645.                             $dimensions['height'] = ceil($dimensions['height'] * ($arg['height'] / 100));
  646.                         } elseif (in_array($transformation['method'], ['rotate''trim'])) {
  647.                             // unable to calculate dimensions -> return empty
  648.                             return [];
  649.                         }
  650.                     }
  651.                 }
  652.             } else {
  653.                 // this method is only if we don't have the source dimensions
  654.                 // this doesn't necessarily return both with & height
  655.                 // and is only a very rough estimate, you should avoid falling back to this functionality
  656.                 foreach ($transformations as $transformation) {
  657.                     if (!empty($transformation)) {
  658.                         if (is_array($transformation['arguments']) && in_array($transformation['method'], ['resize''scaleByWidth''scaleByHeight''cover''frame'])) {
  659.                             foreach ($transformation['arguments'] as $key => $value) {
  660.                                 if ($key == 'width' || $key == 'height') {
  661.                                     $dimensions[$key] = $value;
  662.                                 }
  663.                             }
  664.                         }
  665.                     }
  666.                 }
  667.             }
  668.         }
  669.         // ensure we return int's, sometimes $arg[...] contain strings
  670.         $dimensions['width'] = (int) $dimensions['width'] * ($this->getHighResolution() ?: 1);
  671.         $dimensions['height'] = (int) $dimensions['height'] * ($this->getHighResolution() ?: 1);
  672.         return $dimensions;
  673.     }
  674.     /**
  675.      * @return int|null
  676.      */
  677.     public function getModificationDate()
  678.     {
  679.         return $this->modificationDate;
  680.     }
  681.     /**
  682.      * @param int $modificationDate
  683.      */
  684.     public function setModificationDate($modificationDate)
  685.     {
  686.         $this->modificationDate $modificationDate;
  687.     }
  688.     /**
  689.      * @return int|null
  690.      */
  691.     public function getCreationDate()
  692.     {
  693.         return $this->creationDate;
  694.     }
  695.     /**
  696.      * @param int $creationDate
  697.      */
  698.     public function setCreationDate($creationDate)
  699.     {
  700.         $this->creationDate $creationDate;
  701.     }
  702.     /**
  703.      * @return bool
  704.      */
  705.     public function isPreserveColor()
  706.     {
  707.         return $this->preserveColor;
  708.     }
  709.     /**
  710.      * @param bool $preserveColor
  711.      */
  712.     public function setPreserveColor($preserveColor)
  713.     {
  714.         $this->preserveColor $preserveColor;
  715.     }
  716.     /**
  717.      * @return bool
  718.      */
  719.     public function isPreserveMetaData()
  720.     {
  721.         return $this->preserveMetaData;
  722.     }
  723.     /**
  724.      * @param bool $preserveMetaData
  725.      */
  726.     public function setPreserveMetaData($preserveMetaData)
  727.     {
  728.         $this->preserveMetaData $preserveMetaData;
  729.     }
  730.     /**
  731.      * @return bool
  732.      */
  733.     public function isRasterizeSVG(): bool
  734.     {
  735.         return $this->rasterizeSVG;
  736.     }
  737.     /**
  738.      * @param bool $rasterizeSVG
  739.      */
  740.     public function setRasterizeSVG(bool $rasterizeSVG): void
  741.     {
  742.         $this->rasterizeSVG $rasterizeSVG;
  743.     }
  744.     /**
  745.      * @return bool
  746.      */
  747.     public function isSvgTargetFormatPossible()
  748.     {
  749.         $supportedTransformations = ['resize''scaleByWidth''scaleByHeight'];
  750.         foreach ($this->getItems() as $item) {
  751.             if (!in_array($item['method'], $supportedTransformations)) {
  752.                 return false;
  753.             }
  754.         }
  755.         return true;
  756.     }
  757.     /**
  758.      * @return string
  759.      */
  760.     public function getGroup(): string
  761.     {
  762.         return $this->group;
  763.     }
  764.     /**
  765.      * @param string $group
  766.      */
  767.     public function setGroup(string $group): void
  768.     {
  769.         $this->group $group;
  770.     }
  771.     /**
  772.      * @return bool
  773.      */
  774.     public function getPreserveAnimation(): bool
  775.     {
  776.         return $this->preserveAnimation;
  777.     }
  778.     /**
  779.      * @param bool $preserveAnimation
  780.      */
  781.     public function setPreserveAnimation(bool $preserveAnimation): void
  782.     {
  783.         $this->preserveAnimation $preserveAnimation;
  784.     }
  785.     /**
  786.      * @return bool
  787.      */
  788.     public function isDownloadable(): bool
  789.     {
  790.         return $this->downloadable;
  791.     }
  792.     /**
  793.      * @param bool $downloadable
  794.      */
  795.     public function setDownloadable(bool $downloadable): void
  796.     {
  797.         $this->downloadable $downloadable;
  798.     }
  799.     public function __clone()
  800.     {
  801.         if ($this->dao) {
  802.             $this->dao = clone $this->dao;
  803.             $this->dao->setModel($this);
  804.         }
  805.         //rebuild asset path for overlays
  806.         foreach ($this->items as &$item) {
  807.             if (in_array($item['method'], ['addOverlay''addOverlayFit'])) {
  808.                 if (isset($item['arguments']['id'])) {
  809.                     $img Model\Asset\Image::getById($item['arguments']['id']);
  810.                     if ($img) {
  811.                         $item['arguments']['path'] = $img->getFullPath();
  812.                     }
  813.                 }
  814.             }
  815.         }
  816.     }
  817.     /**
  818.      * @internal
  819.      *
  820.      * @return array
  821.      */
  822.     public static function getAutoFormats(): array
  823.     {
  824.         return \Pimcore::getContainer()->getParameter('pimcore.config')['assets']['image']['thumbnails']['auto_formats'];
  825.     }
  826.     /**
  827.      * @internal
  828.      *
  829.      * @return Config[]
  830.      */
  831.     public function getAutoFormatThumbnailConfigs(): array
  832.     {
  833.         $autoFormatThumbnails = [];
  834.         foreach ($this->getAutoFormats() as $autoFormat => $autoFormatConfig) {
  835.             if ($autoFormatConfig['enabled'] && Model\Asset\Image\Thumbnail::supportsFormat($autoFormat)) {
  836.                 $autoFormatThumbnail = clone $this;
  837.                 $autoFormatThumbnail->setFormat($autoFormat);
  838.                 if (!empty($autoFormatConfig['quality'])) {
  839.                     $autoFormatThumbnail->setQuality($autoFormatConfig['quality']);
  840.                 }
  841.                 $autoFormatThumbnails[$autoFormat] = $autoFormatThumbnail;
  842.             }
  843.         }
  844.         return $autoFormatThumbnails;
  845.     }
  846.     /**
  847.      * @internal
  848.      */
  849.     public function generateAutoName(): void
  850.     {
  851.         $serialized Serialize::serialize($this->getItems());
  852.         $this->setName($this->getName() . '_auto_' md5($serialized));
  853.     }
  854. }