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

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