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