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

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 $name
  272.      * @param array $parameters
  273.      * @param string $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 $name
  297.      * @param array $parameters
  298.      * @param string $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 $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.         $hash md5(Serialize::serialize($pipe));
  506.         $pipe->setName('auto_' $hash);
  507.         return $pipe;
  508.     }
  509.     /**
  510.      * This is mainly here for backward compatibility
  511.      *
  512.      * @internal
  513.      *
  514.      * @param array $config
  515.      *
  516.      * @return self
  517.      */
  518.     public static function getByLegacyConfig($config)
  519.     {
  520.         $pipe = new self();
  521.         if (isset($config['format'])) {
  522.             $pipe->setFormat($config['format']);
  523.         }
  524.         if (isset($config['quality'])) {
  525.             $pipe->setQuality($config['quality']);
  526.         }
  527.         if (isset($config['cover'])) {
  528.             $pipe->addItem('cover', [
  529.                 'width' => $config['width'],
  530.                 'height' => $config['height'],
  531.                 'positioning' => ((isset($config['positioning']) && !empty($config['positioning'])) ? (string)$config['positioning'] : 'center'),
  532.                 'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  533.             ]);
  534.         } elseif (isset($config['contain'])) {
  535.             $pipe->addItem('contain', [
  536.                 'width' => $config['width'],
  537.                 'height' => $config['height'],
  538.                 'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  539.             ]);
  540.         } elseif (isset($config['frame'])) {
  541.             $pipe->addItem('frame', [
  542.                 'width' => $config['width'],
  543.                 'height' => $config['height'],
  544.                 'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  545.             ]);
  546.         } elseif (isset($config['aspectratio']) && $config['aspectratio']) {
  547.             if (isset($config['height']) && isset($config['width']) && $config['height'] > && $config['width'] > 0) {
  548.                 $pipe->addItem('contain', [
  549.                     'width' => $config['width'],
  550.                     'height' => $config['height'],
  551.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  552.                 ]);
  553.             } elseif (isset($config['height']) && $config['height'] > 0) {
  554.                 $pipe->addItem('scaleByHeight', [
  555.                     'height' => $config['height'],
  556.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  557.                 ]);
  558.             } else {
  559.                 $pipe->addItem('scaleByWidth', [
  560.                     'width' => $config['width'],
  561.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  562.                 ]);
  563.             }
  564.         } else {
  565.             if (!isset($config['width']) && isset($config['height'])) {
  566.                 $pipe->addItem('scaleByHeight', [
  567.                     'height' => $config['height'],
  568.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  569.                 ]);
  570.             } elseif (isset($config['width']) && !isset($config['height'])) {
  571.                 $pipe->addItem('scaleByWidth', [
  572.                     'width' => $config['width'],
  573.                     'forceResize' => (isset($config['forceResize']) ? (bool)$config['forceResize'] : false),
  574.                 ]);
  575.             } elseif (isset($config['width']) && isset($config['height'])) {
  576.                 $pipe->addItem('resize', [
  577.                     'width' => $config['width'],
  578.                     'height' => $config['height'],
  579.                 ]);
  580.             }
  581.         }
  582.         if (isset($config['highResolution'])) {
  583.             $pipe->setHighResolution($config['highResolution']);
  584.         }
  585.         $hash md5(Serialize::serialize($pipe));
  586.         $pipe->setName('auto_' $hash);
  587.         return $pipe;
  588.     }
  589.     /**
  590.      * @internal
  591.      *
  592.      * @param Model\Asset\Image $asset
  593.      *
  594.      * @return array
  595.      */
  596.     public function getEstimatedDimensions($asset)
  597.     {
  598.         $originalWidth $asset->getWidth();
  599.         $originalHeight $asset->getHeight();
  600.         $dimensions = [
  601.             'width' => $originalWidth,
  602.             'height' => $originalHeight,
  603.         ];
  604.         $transformations $this->getItems();
  605.         if (is_array($transformations) && count($transformations) > 0) {
  606.             if ($originalWidth && $originalHeight) {
  607.                 foreach ($transformations as $transformation) {
  608.                     if (!empty($transformation)) {
  609.                         $arg $transformation['arguments'];
  610.                         $forceResize false;
  611.                         if (isset($arg['forceResize']) && $arg['forceResize'] === true) {
  612.                             $forceResize true;
  613.                         }
  614.                         if (in_array($transformation['method'], ['resize''cover''frame''crop'])) {
  615.                             $dimensions['width'] = $arg['width'];
  616.                             $dimensions['height'] = $arg['height'];
  617.                         } elseif ($transformation['method'] == '1x1_pixel') {
  618.                             return [
  619.                                 'width' => 1,
  620.                                 'height' => 1,
  621.                             ];
  622.                         } elseif ($transformation['method'] == 'scaleByWidth') {
  623.                             if ($arg['width'] <= $dimensions['width'] || $asset->isVectorGraphic() || $forceResize) {
  624.                                 $dimensions['height'] = round(($arg['width'] / $dimensions['width']) * $dimensions['height'], 0);
  625.                                 $dimensions['width'] = $arg['width'];
  626.                             }
  627.                         } elseif ($transformation['method'] == 'scaleByHeight') {
  628.                             if ($arg['height'] < $dimensions['height'] || $asset->isVectorGraphic() || $forceResize) {
  629.                                 $dimensions['width'] = round(($arg['height'] / $dimensions['height']) * $dimensions['width'], 0);
  630.                                 $dimensions['height'] = $arg['height'];
  631.                             }
  632.                         } elseif ($transformation['method'] == 'contain') {
  633.                             $x $dimensions['width'] / $arg['width'];
  634.                             $y $dimensions['height'] / $arg['height'];
  635.                             if (!$forceResize && $x <= && $y <= && !$asset->isVectorGraphic()) {
  636.                                 continue;
  637.                             }
  638.                             if ($x $y) {
  639.                                 $dimensions['height'] = round(($arg['width'] / $dimensions['width']) * $dimensions['height'], 0);
  640.                                 $dimensions['width'] = $arg['width'];
  641.                             } else {
  642.                                 $dimensions['width'] = round(($arg['height'] / $dimensions['height']) * $dimensions['width'], 0);
  643.                                 $dimensions['height'] = $arg['height'];
  644.                             }
  645.                         } elseif ($transformation['method'] == 'cropPercent') {
  646.                             $dimensions['width'] = ceil($dimensions['width'] * ($arg['width'] / 100));
  647.                             $dimensions['height'] = ceil($dimensions['height'] * ($arg['height'] / 100));
  648.                         } elseif (in_array($transformation['method'], ['rotate''trim'])) {
  649.                             // unable to calculate dimensions -> return empty
  650.                             return [];
  651.                         }
  652.                     }
  653.                 }
  654.             } else {
  655.                 // this method is only if we don't have the source dimensions
  656.                 // this doesn't necessarily return both with & height
  657.                 // and is only a very rough estimate, you should avoid falling back to this functionality
  658.                 foreach ($transformations as $transformation) {
  659.                     if (!empty($transformation)) {
  660.                         if (is_array($transformation['arguments']) && in_array($transformation['method'], ['resize''scaleByWidth''scaleByHeight''cover''frame'])) {
  661.                             foreach ($transformation['arguments'] as $key => $value) {
  662.                                 if ($key == 'width' || $key == 'height') {
  663.                                     $dimensions[$key] = $value;
  664.                                 }
  665.                             }
  666.                         }
  667.                     }
  668.                 }
  669.             }
  670.         }
  671.         // ensure we return int's, sometimes $arg[...] contain strings
  672.         $dimensions['width'] = (int) $dimensions['width'] * ($this->getHighResolution() ?: 1);
  673.         $dimensions['height'] = (int) $dimensions['height'] * ($this->getHighResolution() ?: 1);
  674.         return $dimensions;
  675.     }
  676.     /**
  677.      * @return int|null
  678.      */
  679.     public function getModificationDate()
  680.     {
  681.         return $this->modificationDate;
  682.     }
  683.     /**
  684.      * @param int $modificationDate
  685.      */
  686.     public function setModificationDate($modificationDate)
  687.     {
  688.         $this->modificationDate $modificationDate;
  689.     }
  690.     /**
  691.      * @return int|null
  692.      */
  693.     public function getCreationDate()
  694.     {
  695.         return $this->creationDate;
  696.     }
  697.     /**
  698.      * @param int $creationDate
  699.      */
  700.     public function setCreationDate($creationDate)
  701.     {
  702.         $this->creationDate $creationDate;
  703.     }
  704.     /**
  705.      * @return bool
  706.      */
  707.     public function isPreserveColor()
  708.     {
  709.         return $this->preserveColor;
  710.     }
  711.     /**
  712.      * @param bool $preserveColor
  713.      */
  714.     public function setPreserveColor($preserveColor)
  715.     {
  716.         $this->preserveColor $preserveColor;
  717.     }
  718.     /**
  719.      * @return bool
  720.      */
  721.     public function isPreserveMetaData()
  722.     {
  723.         return $this->preserveMetaData;
  724.     }
  725.     /**
  726.      * @param bool $preserveMetaData
  727.      */
  728.     public function setPreserveMetaData($preserveMetaData)
  729.     {
  730.         $this->preserveMetaData $preserveMetaData;
  731.     }
  732.     /**
  733.      * @return bool
  734.      */
  735.     public function isRasterizeSVG(): bool
  736.     {
  737.         return $this->rasterizeSVG;
  738.     }
  739.     /**
  740.      * @param bool $rasterizeSVG
  741.      */
  742.     public function setRasterizeSVG(bool $rasterizeSVG): void
  743.     {
  744.         $this->rasterizeSVG $rasterizeSVG;
  745.     }
  746.     /**
  747.      * @return bool
  748.      */
  749.     public function isSvgTargetFormatPossible()
  750.     {
  751.         $supportedTransformations = ['resize''scaleByWidth''scaleByHeight'];
  752.         foreach ($this->getItems() as $item) {
  753.             if (!in_array($item['method'], $supportedTransformations)) {
  754.                 return false;
  755.             }
  756.         }
  757.         return true;
  758.     }
  759.     /**
  760.      * @return string
  761.      */
  762.     public function getGroup(): string
  763.     {
  764.         return $this->group;
  765.     }
  766.     /**
  767.      * @param string $group
  768.      */
  769.     public function setGroup(string $group): void
  770.     {
  771.         $this->group $group;
  772.     }
  773.     /**
  774.      * @return bool
  775.      */
  776.     public function getPreserveAnimation(): bool
  777.     {
  778.         return $this->preserveAnimation;
  779.     }
  780.     /**
  781.      * @param bool $preserveAnimation
  782.      */
  783.     public function setPreserveAnimation(bool $preserveAnimation): void
  784.     {
  785.         $this->preserveAnimation $preserveAnimation;
  786.     }
  787.     /**
  788.      * @return bool
  789.      */
  790.     public function isDownloadable(): bool
  791.     {
  792.         return $this->downloadable;
  793.     }
  794.     /**
  795.      * @param bool $downloadable
  796.      */
  797.     public function setDownloadable(bool $downloadable): void
  798.     {
  799.         $this->downloadable $downloadable;
  800.     }
  801.     public function __clone()
  802.     {
  803.         if ($this->dao) {
  804.             $this->dao = clone $this->dao;
  805.             $this->dao->setModel($this);
  806.         }
  807.         //rebuild asset path for overlays
  808.         foreach ($this->items as &$item) {
  809.             if (in_array($item['method'], ['addOverlay''addOverlayFit'])) {
  810.                 if (isset($item['arguments']['id'])) {
  811.                     $img Model\Asset\Image::getById($item['arguments']['id']);
  812.                     if ($img) {
  813.                         $item['arguments']['path'] = $img->getFullPath();
  814.                     }
  815.                 }
  816.             }
  817.         }
  818.     }
  819.     /**
  820.      * @internal
  821.      *
  822.      * @return array
  823.      */
  824.     public static function getAutoFormats(): array
  825.     {
  826.         return \Pimcore::getContainer()->getParameter('pimcore.config')['assets']['image']['thumbnails']['auto_formats'];
  827.     }
  828.     /**
  829.      * @internal
  830.      *
  831.      * @return Config[]
  832.      */
  833.     public function getAutoFormatThumbnailConfigs(): array
  834.     {
  835.         $autoFormatThumbnails = [];
  836.         foreach ($this->getAutoFormats() as $autoFormat => $autoFormatConfig) {
  837.             if (Model\Asset\Image\Thumbnail::supportsFormat($autoFormat) && $autoFormatConfig['enabled']) {
  838.                 $autoFormatThumbnail = clone $this;
  839.                 $autoFormatThumbnail->setFormat($autoFormat);
  840.                 if (!empty($autoFormatConfig['quality'])) {
  841.                     $autoFormatThumbnail->setQuality($autoFormatConfig['quality']);
  842.                 }
  843.                 $autoFormatThumbnails[$autoFormat] = $autoFormatThumbnail;
  844.             }
  845.         }
  846.         return $autoFormatThumbnails;
  847.     }
  848. }