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