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

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