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

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