vendor/pimcore/pimcore/models/Document/Editable/Image.php line 26

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\Document\Editable;
  15. use Pimcore\Model;
  16. use Pimcore\Model\Asset;
  17. use Pimcore\Model\Element;
  18. use Pimcore\Tool\Serialize;
  19. /**
  20.  * @method \Pimcore\Model\Document\Editable\Dao getDao()
  21.  */
  22. class Image extends Model\Document\Editable implements IdRewriterInterfaceEditmodeDataInterface
  23. {
  24.     /**
  25.      * ID of the referenced image
  26.      *
  27.      * @internal
  28.      *
  29.      * @var int
  30.      */
  31.     protected $id;
  32.     /**
  33.      * The ALT text of the image
  34.      *
  35.      * @internal
  36.      *
  37.      * @var string
  38.      */
  39.     protected $alt;
  40.     /**
  41.      * Contains the imageobject itself
  42.      *
  43.      * @internal
  44.      *
  45.      * @var Asset\Image|null
  46.      */
  47.     protected $image;
  48.     /**
  49.      * @internal
  50.      *
  51.      * @var bool
  52.      */
  53.     protected $cropPercent false;
  54.     /**
  55.      * @internal
  56.      *
  57.      * @var float
  58.      */
  59.     protected $cropWidth;
  60.     /**
  61.      * @internal
  62.      *
  63.      * @var float
  64.      */
  65.     protected $cropHeight;
  66.     /**
  67.      * @internal
  68.      *
  69.      * @var float
  70.      */
  71.     protected $cropTop;
  72.     /**
  73.      * @internal
  74.      *
  75.      * @var float
  76.      */
  77.     protected $cropLeft;
  78.     /**
  79.      * @internal
  80.      *
  81.      * @var array
  82.      */
  83.     protected $hotspots = [];
  84.     /**
  85.      * @internal
  86.      *
  87.      * @var array
  88.      */
  89.     protected $marker = [];
  90.     /**
  91.      * {@inheritdoc}
  92.      */
  93.     public function getType()
  94.     {
  95.         return 'image';
  96.     }
  97.     /**
  98.      * {@inheritdoc}
  99.      */
  100.     public function getData()
  101.     {
  102.         return [
  103.             'id' => $this->id,
  104.             'alt' => $this->alt,
  105.             'cropPercent' => $this->cropPercent,
  106.             'cropWidth' => $this->cropWidth,
  107.             'cropHeight' => $this->cropHeight,
  108.             'cropTop' => $this->cropTop,
  109.             'cropLeft' => $this->cropLeft,
  110.             'hotspots' => $this->hotspots,
  111.             'marker' => $this->marker,
  112.         ];
  113.     }
  114.     /**
  115.      * {@inheritdoc}
  116.      */
  117.     public function getDataForResource()
  118.     {
  119.         return [
  120.             'id' => $this->id,
  121.             'alt' => $this->alt,
  122.             'cropPercent' => $this->cropPercent,
  123.             'cropWidth' => $this->cropWidth,
  124.             'cropHeight' => $this->cropHeight,
  125.             'cropTop' => $this->cropTop,
  126.             'cropLeft' => $this->cropLeft,
  127.             'hotspots' => $this->hotspots,
  128.             'marker' => $this->marker,
  129.         ];
  130.     }
  131.     /**
  132.      * {@inheritdoc}
  133.      */
  134.     public function getDataEditmode() /** : mixed */
  135.     {
  136.         $image $this->getImage();
  137.         if ($image instanceof Asset\Image) {
  138.             $rewritePath = function ($data) {
  139.                 if (!is_array($data)) {
  140.                     return [];
  141.                 }
  142.                 foreach ($data as &$element) {
  143.                     if (array_key_exists('data'$element) && is_array($element['data']) && count($element['data']) > 0) {
  144.                         foreach ($element['data'] as &$metaData) {
  145.                             if ($metaData['value'] instanceof Element\ElementInterface) {
  146.                                 $metaData['value'] = $metaData['value']->getRealFullPath();
  147.                             }
  148.                         }
  149.                     }
  150.                 }
  151.                 return $data;
  152.             };
  153.             $marker $rewritePath($this->marker);
  154.             $hotspots $rewritePath($this->hotspots);
  155.             return [
  156.                 'id' => $this->id,
  157.                 'path' => $image->getRealFullPath(),
  158.                 'alt' => $this->alt,
  159.                 'cropPercent' => $this->cropPercent,
  160.                 'cropWidth' => $this->cropWidth,
  161.                 'cropHeight' => $this->cropHeight,
  162.                 'cropTop' => $this->cropTop,
  163.                 'cropLeft' => $this->cropLeft,
  164.                 'hotspots' => $hotspots,
  165.                 'marker' => $marker,
  166.                 'predefinedDataTemplates' => $this->getConfig()['predefinedDataTemplates'] ?? null,
  167.             ];
  168.         }
  169.         return null;
  170.     }
  171.     /**
  172.      * {@inheritdoc}
  173.      */
  174.     public function getConfig()
  175.     {
  176.         $config parent::getConfig();
  177.         if (isset($config['thumbnail']) && !isset($config['focal_point_context_menu_item'])) {
  178.             $thumbConfig Asset\Image\Thumbnail\Config::getByAutoDetect($config['thumbnail']);
  179.             if ($thumbConfig) {
  180.                 foreach ($thumbConfig->getItems() as $item) {
  181.                     if ($item['method'] == 'cover') {
  182.                         $config['focal_point_context_menu_item'] = true;
  183.                         $this->config['focal_point_context_menu_item'] = true;
  184.                         break;
  185.                     }
  186.                 }
  187.             }
  188.         }
  189.         return $config;
  190.     }
  191.     /**
  192.      * {@inheritdoc}
  193.      */
  194.     public function frontend()
  195.     {
  196.         if (!is_array($this->config)) {
  197.             $this->config = [];
  198.         }
  199.         $image $this->getImage();
  200.         if ($image instanceof Asset) {
  201.             $thumbnailName $this->config['thumbnail'] ?? null;
  202.             if ($thumbnailName || $this->cropPercent) {
  203.                 // create a thumbnail first
  204.                 $autoName false;
  205.                 $thumbConfig $image->getThumbnailConfig($thumbnailName);
  206.                 if (!$thumbConfig && $this->cropPercent) {
  207.                     $thumbConfig = new Asset\Image\Thumbnail\Config();
  208.                 }
  209.                 if ($this->cropPercent) {
  210.                     $this->applyCustomCropping($thumbConfig);
  211.                     $autoName true;
  212.                 }
  213.                 if (isset($this->config['highResolution']) && $this->config['highResolution'] > 1) {
  214.                     $thumbConfig->setHighResolution($this->config['highResolution']);
  215.                 }
  216.                 // autogenerate a name for the thumbnail because it's different from the original
  217.                 if ($autoName) {
  218.                     $hash md5(Serialize::serialize($thumbConfig->getItems()));
  219.                     $thumbConfig->setName($thumbConfig->getName() . '_auto_' $hash);
  220.                 }
  221.                 $deferred true;
  222.                 if (isset($this->config['deferred'])) {
  223.                     $deferred $this->config['deferred'];
  224.                 }
  225.                 $thumbnail $image->getThumbnail($thumbConfig$deferred);
  226.             } else {
  227.                 // we're using the thumbnail class only to generate the HTML
  228.                 $thumbnail $image->getThumbnail();
  229.             }
  230.             $attributes array_merge($this->config, [
  231.                 'alt' => $this->alt,
  232.                 'title' => $this->alt,
  233.             ]);
  234.             $removeAttributes = [];
  235.             if (isset($this->config['removeAttributes']) && is_array($this->config['removeAttributes'])) {
  236.                 $removeAttributes $this->config['removeAttributes'];
  237.             }
  238.             // thumbnail's HTML is always generated by the thumbnail itself
  239.             return $thumbnail->getHtml($attributes);
  240.         }
  241.         return '';
  242.     }
  243.     /**
  244.      * {@inheritdoc}
  245.      */
  246.     public function setDataFromResource($data)
  247.     {
  248.         if (strlen($data) > 2) {
  249.             $data Serialize::unserialize($data);
  250.         }
  251.         $rewritePath = function ($data) {
  252.             if (!is_array($data)) {
  253.                 return [];
  254.             }
  255.             foreach ($data as &$element) {
  256.                 if (array_key_exists('data'$element) && is_array($element['data']) && count($element['data']) > 0) {
  257.                     foreach ($element['data'] as &$metaData) {
  258.                         // this is for backward compatibility (Array vs. MarkerHotspotItem)
  259.                         if (is_array($metaData)) {
  260.                             $metaData = new Element\Data\MarkerHotspotItem($metaData);
  261.                         }
  262.                     }
  263.                 }
  264.             }
  265.             return $data;
  266.         };
  267.         if (array_key_exists('marker'$data) && is_array($data['marker']) && count($data['marker']) > 0) {
  268.             $data['marker'] = $rewritePath($data['marker']);
  269.         }
  270.         if (array_key_exists('hotspots'$data) && is_array($data['hotspots']) && count($data['hotspots']) > 0) {
  271.             $data['hotspots'] = $rewritePath($data['hotspots']);
  272.         }
  273.         $this->id $data['id'] ?? null;
  274.         $this->alt $data['alt'] ?? null;
  275.         $this->cropPercent $data['cropPercent'] ?? null;
  276.         $this->cropWidth $data['cropWidth'] ?? null;
  277.         $this->cropHeight $data['cropHeight'] ?? null;
  278.         $this->cropTop $data['cropTop'] ?? null;
  279.         $this->cropLeft $data['cropLeft'] ?? null;
  280.         $this->marker $data['marker'] ?? null;
  281.         $this->hotspots $data['hotspots'] ?? null;
  282.         return $this;
  283.     }
  284.     /**
  285.      * {@inheritdoc}
  286.      */
  287.     public function setDataFromEditmode($data)
  288.     {
  289.         $rewritePath = function ($data) {
  290.             if (!is_array($data)) {
  291.                 return [];
  292.             }
  293.             foreach ($data as &$element) {
  294.                 if (array_key_exists('data'$element) && is_array($element['data']) && count($element['data']) > 0) {
  295.                     foreach ($element['data'] as &$metaData) {
  296.                         $metaData = new Element\Data\MarkerHotspotItem($metaData);
  297.                         if (in_array($metaData['type'], ['object''asset''document'])) {
  298.                             $el Element\Service::getElementByPath($metaData['type'], $metaData->getValue());
  299.                             $metaData['value'] = $el;
  300.                         }
  301.                     }
  302.                 }
  303.             }
  304.             return $data;
  305.         };
  306.         if (is_array($data)) {
  307.             if (array_key_exists('marker'$data) && is_array($data['marker']) && count($data['marker']) > 0) {
  308.                 $data['marker'] = $rewritePath($data['marker']);
  309.             }
  310.             if (array_key_exists('hotspots'$data) && is_array($data['hotspots']) && count($data['hotspots']) > 0) {
  311.                 $data['hotspots'] = $rewritePath($data['hotspots']);
  312.             }
  313.             $this->id $data['id'] ?? null;
  314.             $this->alt $data['alt'] ?? null;
  315.             $this->cropPercent $data['cropPercent'] ?? null;
  316.             $this->cropWidth $data['cropWidth'] ?? null;
  317.             $this->cropHeight $data['cropHeight'] ?? null;
  318.             $this->cropTop $data['cropTop'] ?? null;
  319.             $this->cropLeft $data['cropLeft'] ?? null;
  320.             $this->marker $data['marker'] ?? null;
  321.             $this->hotspots $data['hotspots'] ?? null;
  322.         }
  323.         return $this;
  324.     }
  325.     /**
  326.      * @return string
  327.      */
  328.     public function getText()
  329.     {
  330.         return $this->alt;
  331.     }
  332.     /**
  333.      * @param string $text
  334.      */
  335.     public function setText($text)
  336.     {
  337.         $this->alt $text;
  338.     }
  339.     /**
  340.      * @return string
  341.      */
  342.     public function getAlt()
  343.     {
  344.         return $this->getText();
  345.     }
  346.     /**
  347.      * @return string
  348.      */
  349.     public function getSrc()
  350.     {
  351.         $image $this->getImage();
  352.         if ($image instanceof Asset) {
  353.             return $image->getFullPath();
  354.         }
  355.         return '';
  356.     }
  357.     /**
  358.      * @return Asset\Image|null
  359.      */
  360.     public function getImage()
  361.     {
  362.         if (!$this->image) {
  363.             $this->image Asset\Image::getById($this->getId());
  364.         }
  365.         return $this->image;
  366.     }
  367.     /**
  368.      * @param Asset\Image|null $image
  369.      *
  370.      * @return Model\Document\Editable\Image
  371.      */
  372.     public function setImage($image)
  373.     {
  374.         $this->image $image;
  375.         if ($image instanceof Asset) {
  376.             $this->setId($image->getId());
  377.         }
  378.         return $this;
  379.     }
  380.     /**
  381.      * @param int $id
  382.      *
  383.      * @return Model\Document\Editable\Image
  384.      */
  385.     public function setId($id)
  386.     {
  387.         $this->id $id;
  388.         return $this;
  389.     }
  390.     /**
  391.      * @return int
  392.      */
  393.     public function getId()
  394.     {
  395.         return (int) $this->id;
  396.     }
  397.     /**
  398.      * @param string|array|Asset\Image\Thumbnail\Config $conf
  399.      * @param bool $deferred
  400.      *
  401.      * @return Asset\Image\Thumbnail|string
  402.      */
  403.     public function getThumbnail($conf$deferred true)
  404.     {
  405.         $image $this->getImage();
  406.         if ($image instanceof Asset) {
  407.             $thumbConfig $image->getThumbnailConfig($conf);
  408.             if ($thumbConfig && $this->cropPercent) {
  409.                 $this->applyCustomCropping($thumbConfig);
  410.                 $hash md5(Serialize::serialize($thumbConfig->getItems()));
  411.                 $thumbConfig->setName($thumbConfig->getName() . '_auto_' $hash);
  412.             }
  413.             return $image->getThumbnail($thumbConfig$deferred);
  414.         }
  415.         return '';
  416.     }
  417.     /**
  418.      * @param Asset\Image\Thumbnail\Config $thumbConfig
  419.      */
  420.     private function applyCustomCropping($thumbConfig)
  421.     {
  422.         $cropConfig = [
  423.             'width' => $this->cropWidth,
  424.             'height' => $this->cropHeight,
  425.             'y' => $this->cropTop,
  426.             'x' => $this->cropLeft,
  427.         ];
  428.         $thumbConfig->addItemAt(0'cropPercent'$cropConfig);
  429.         // also crop media query specific configs
  430.         if ($thumbConfig->hasMedias()) {
  431.             foreach ($thumbConfig->getMedias() as $mediaName => $mediaItems) {
  432.                 $thumbConfig->addItemAt(0'cropPercent'$cropConfig$mediaName);
  433.             }
  434.         }
  435.     }
  436.     /**
  437.      * {@inheritdoc}
  438.      */
  439.     public function isEmpty()
  440.     {
  441.         $image $this->getImage();
  442.         if ($image instanceof Asset\Image) {
  443.             return false;
  444.         }
  445.         return true;
  446.     }
  447.     /**
  448.      * {@inheritdoc}
  449.      */
  450.     public function getCacheTags(Model\Document\PageSnippet $ownerDocument, array $tags = []): array
  451.     {
  452.         $image $this->getImage();
  453.         if ($image instanceof Asset) {
  454.             if (!array_key_exists($image->getCacheTag(), $tags)) {
  455.                 $tags $image->getCacheTags($tags);
  456.             }
  457.         }
  458.         $getMetaDataCacheTags = function ($data$tags) {
  459.             if (!is_array($data)) {
  460.                 return $tags;
  461.             }
  462.             foreach ($data as $element) {
  463.                 if (array_key_exists('data'$element) && is_array($element['data']) && count($element['data']) > 0) {
  464.                     foreach ($element['data'] as $metaData) {
  465.                         if ($metaData['value'] instanceof Element\ElementInterface) {
  466.                             if (!array_key_exists($metaData['value']->getCacheTag(), $tags)) {
  467.                                 $tags $metaData['value']->getCacheTags($tags);
  468.                             }
  469.                         }
  470.                     }
  471.                 }
  472.             }
  473.             return $tags;
  474.         };
  475.         $tags $getMetaDataCacheTags($this->marker$tags);
  476.         $tags $getMetaDataCacheTags($this->hotspots$tags);
  477.         return $tags;
  478.     }
  479.     /**
  480.      * {@inheritdoc}
  481.      */
  482.     public function resolveDependencies()
  483.     {
  484.         $dependencies = [];
  485.         $image $this->getImage();
  486.         if ($image instanceof Asset\Image) {
  487.             $key 'asset_' $image->getId();
  488.             $dependencies[$key] = [
  489.                 'id' => $image->getId(),
  490.                 'type' => 'asset',
  491.             ];
  492.         }
  493.         $getMetaDataDependencies = function ($data$dependencies) {
  494.             if (!is_array($data)) {
  495.                 return $dependencies;
  496.             }
  497.             foreach ($data as $element) {
  498.                 if (array_key_exists('data'$element) && is_array($element['data']) && count($element['data']) > 0) {
  499.                     foreach ($element['data'] as $metaData) {
  500.                         if ($metaData['value'] instanceof Element\ElementInterface) {
  501.                             $dependencies[$metaData['type'] . '_' $metaData['value']->getId()] = [
  502.                                 'id' => $metaData['value']->getId(),
  503.                                 'type' => $metaData['type'],
  504.                             ];
  505.                         }
  506.                     }
  507.                 }
  508.             }
  509.             return $dependencies;
  510.         };
  511.         $dependencies $getMetaDataDependencies($this->marker$dependencies);
  512.         $dependencies $getMetaDataDependencies($this->hotspots$dependencies);
  513.         return $dependencies;
  514.     }
  515.     /**
  516.      * @param float $cropHeight
  517.      *
  518.      * @return $this
  519.      */
  520.     public function setCropHeight($cropHeight)
  521.     {
  522.         $this->cropHeight $cropHeight;
  523.         return $this;
  524.     }
  525.     /**
  526.      * @return float
  527.      */
  528.     public function getCropHeight()
  529.     {
  530.         return $this->cropHeight;
  531.     }
  532.     /**
  533.      * @param float $cropLeft
  534.      *
  535.      * @return $this
  536.      */
  537.     public function setCropLeft($cropLeft)
  538.     {
  539.         $this->cropLeft $cropLeft;
  540.         return $this;
  541.     }
  542.     /**
  543.      * @return float
  544.      */
  545.     public function getCropLeft()
  546.     {
  547.         return $this->cropLeft;
  548.     }
  549.     /**
  550.      * @param bool $cropPercent
  551.      *
  552.      * @return $this
  553.      */
  554.     public function setCropPercent($cropPercent)
  555.     {
  556.         $this->cropPercent $cropPercent;
  557.         return $this;
  558.     }
  559.     /**
  560.      * @return bool
  561.      */
  562.     public function getCropPercent()
  563.     {
  564.         return $this->cropPercent;
  565.     }
  566.     /**
  567.      * @param float $cropTop
  568.      *
  569.      * @return $this
  570.      */
  571.     public function setCropTop($cropTop)
  572.     {
  573.         $this->cropTop $cropTop;
  574.         return $this;
  575.     }
  576.     /**
  577.      * @return float
  578.      */
  579.     public function getCropTop()
  580.     {
  581.         return $this->cropTop;
  582.     }
  583.     /**
  584.      * @param float $cropWidth
  585.      *
  586.      * @return $this
  587.      */
  588.     public function setCropWidth($cropWidth)
  589.     {
  590.         $this->cropWidth $cropWidth;
  591.         return $this;
  592.     }
  593.     /**
  594.      * @return float
  595.      */
  596.     public function getCropWidth()
  597.     {
  598.         return $this->cropWidth;
  599.     }
  600.     /**
  601.      * @param array $hotspots
  602.      */
  603.     public function setHotspots($hotspots)
  604.     {
  605.         $this->hotspots $hotspots;
  606.     }
  607.     /**
  608.      * @return array
  609.      */
  610.     public function getHotspots()
  611.     {
  612.         return $this->hotspots;
  613.     }
  614.     /**
  615.      * @param array $marker
  616.      */
  617.     public function setMarker($marker)
  618.     {
  619.         $this->marker $marker;
  620.     }
  621.     /**
  622.      * @return array
  623.      */
  624.     public function getMarker()
  625.     {
  626.         return $this->marker;
  627.     }
  628.     /**
  629.      * { @inheritdoc }
  630.      */
  631.     public function rewriteIds($idMapping/** : void */
  632.     {
  633.         if (array_key_exists('asset'$idMapping) && array_key_exists($this->getId(), $idMapping['asset'])) {
  634.             $this->setId($idMapping['asset'][$this->getId()]);
  635.             // reset marker & hotspot information
  636.             $this->setHotspots([]);
  637.             $this->setMarker([]);
  638.             $this->setCropPercent(false);
  639.             $this->setImage(null);
  640.         }
  641.     }
  642.     public function __sleep()
  643.     {
  644.         $finalVars = [];
  645.         $parentVars parent::__sleep();
  646.         $blockedVars = ['image'];
  647.         foreach ($parentVars as $key) {
  648.             if (!in_array($key$blockedVars)) {
  649.                 $finalVars[] = $key;
  650.             }
  651.         }
  652.         return $finalVars;
  653.     }
  654. }