vendor/isotope/isotope-core/system/modules/isotope/library/Isotope/Model/Gallery/Standard.php line 364

Open in your IDE?
  1. <?php
  2. /*
  3.  * Isotope eCommerce for Contao Open Source CMS
  4.  *
  5.  * Copyright (C) 2009 - 2019 terminal42 gmbh & Isotope eCommerce Workgroup
  6.  *
  7.  * @link       https://isotopeecommerce.org
  8.  * @license    https://opensource.org/licenses/lgpl-3.0.html
  9.  */
  10. namespace Isotope\Model\Gallery;
  11. use Contao\Environment;
  12. use Contao\File;
  13. use Contao\FilesModel;
  14. use Contao\Picture;
  15. use Contao\StringUtil;
  16. use Contao\System;
  17. use Haste\Image\Image;
  18. use Isotope\Interfaces\IsotopeGallery;
  19. use Isotope\Model\Gallery;
  20. use Isotope\Template;
  21. /**
  22.  * Standard implements a lightbox gallery
  23.  *
  24.  * @property string $lightbox_size
  25.  * @property string $lightbox_watermark_image
  26.  * @property string $lightbox_watermark_position
  27.  * @property string $lightbox_template
  28.  */
  29. class Standard extends Gallery implements IsotopeGallery
  30. {
  31.     /**
  32.      * Template
  33.      * @var string
  34.      */
  35.     protected $strTemplate 'iso_gallery_standard';
  36.     /**
  37.      * Attribute name
  38.      * @var string
  39.      */
  40.     protected $strName;
  41.     /**
  42.      * Files
  43.      * @var array
  44.      */
  45.     protected $arrFiles = array();
  46.     /**
  47.      * Images cache
  48.      * @var array
  49.      */
  50.     private $arrImages = array();
  51.     /**
  52.      * Override template if available in record
  53.      *
  54.      * @param array $arrData The data record
  55.      *
  56.      * @return $this The model object
  57.      */
  58.     public function setRow(array $arrData)
  59.     {
  60.         if ($arrData['customTpl'] != '' && 'FE' === TL_MODE) {
  61.             $this->strTemplate $arrData['customTpl'];
  62.         }
  63.         return parent::setRow($arrData);
  64.     }
  65.     /**
  66.      * Set gallery attribute name
  67.      *
  68.      * @param string $strName
  69.      */
  70.     public function setName($strName)
  71.     {
  72.         $this->strName $strName;
  73.     }
  74.     /**
  75.      * Get gallery attribute name
  76.      *
  77.      * @return string
  78.      */
  79.     public function getName()
  80.     {
  81.         return $this->strName;
  82.     }
  83.     /**
  84.      * Set gallery template
  85.      *
  86.      * @param string $strTemplate
  87.      */
  88.     public function setTemplate($strTemplate)
  89.     {
  90.         $this->strTemplate $strTemplate;
  91.     }
  92.     /**
  93.      * Get gallery template
  94.      *
  95.      * @return string
  96.      */
  97.     public function getTemplate()
  98.     {
  99.         return $this->strTemplate;
  100.     }
  101.     /**
  102.      * Set image files
  103.      *
  104.      * @param array $arrFiles
  105.      */
  106.     public function setFiles(array $arrFiles)
  107.     {
  108.         $this->arrFiles array_values($arrFiles);
  109.     }
  110.     /**
  111.      * Get image files
  112.      *
  113.      * @return array
  114.      */
  115.     public function getFiles()
  116.     {
  117.         return $this->arrFiles;
  118.     }
  119.     /**
  120.      * Get the number of images
  121.      *
  122.      * @return int
  123.      */
  124.     public function size()
  125.     {
  126.         return \count($this->arrFiles);
  127.     }
  128.     /**
  129.      * Returns whether the gallery object has an image do display or not
  130.      *
  131.      * @return bool
  132.      */
  133.     public function hasImages()
  134.     {
  135.         // Check files array here because we don't need to generate an image just to know if there are images
  136.         return \count($this->arrFiles) > 0;
  137.     }
  138.     /**
  139.      * Checks if a placeholder image is defined
  140.      *
  141.      * @return bool
  142.      */
  143.     protected function hasPlaceholderImage()
  144.     {
  145.         return ($this->placeholder && null !== FilesModel::findByPk($this->placeholder));
  146.     }
  147.     /**
  148.      * Generate main image and return it as HTML string
  149.      *
  150.      * @return string
  151.      */
  152.     public function generateMainImage()
  153.     {
  154.         $hasImages $this->hasImages();
  155.         if (!$hasImages && !$this->hasPlaceholderImage()) {
  156.             return '';
  157.         }
  158.         /** @var Template|object $objTemplate */
  159.         $objTemplate = new Template($this->strTemplate);
  160.         $this->addImageToTemplate(
  161.             $objTemplate,
  162.             'main',
  163.             ($hasImages $this->arrFiles[0] : $this->getPlaceholderImage()),
  164.             $hasImages
  165.         );
  166.         $objTemplate->javascript '';
  167.         if (Environment::get('isAjaxRequest')) {
  168.             $strScripts '';
  169.             $arrTemplates StringUtil::deserialize($this->lightbox_templatetrue);
  170.             if (!empty($arrTemplates)) {
  171.                 foreach ($arrTemplates as $strTemplate) {
  172.                     $objScript = new Template($strTemplate);
  173.                     $strScripts .= $objScript->parse();
  174.                 }
  175.             }
  176.             $objTemplate->javascript $strScripts;
  177.         }
  178.         return $objTemplate->parse();
  179.     }
  180.     /**
  181.      * Generate gallery and return it as HTML string
  182.      *
  183.      * @param int $intSkip
  184.      *
  185.      * @return string
  186.      */
  187.     public function generateGallery($intSkip 1)
  188.     {
  189.         // If we skip one or more images or no placeholder image is available there's no gallery
  190.         if (!$this->hasImages() && ($intSkip >= || !$this->hasPlaceholderImage())) {
  191.             return '';
  192.         }
  193.         $strGallery '';
  194.         $watermark  true;
  195.         $arrFiles   = \array_slice($this->arrFiles$intSkip);
  196.         // Add placeholder for the gallery
  197.         if (=== \count($arrFiles) && $intSkip 1) {
  198.             $arrFiles[] = $this->getPlaceholderImage();
  199.             $watermark  false;
  200.         }
  201.         foreach ($arrFiles as $arrFile) {
  202.             $objTemplate = new Template($this->strTemplate);
  203.             $this->addImageToTemplate($objTemplate'gallery'$arrFile$watermark);
  204.             $strGallery .= $objTemplate->parse();
  205.         }
  206.         return $strGallery;
  207.     }
  208.     /**
  209.      * If the class is echoed, return the main image
  210.      *
  211.      * @return string
  212.      */
  213.     public function __toString()
  214.     {
  215.         return $this->generateMainImage();
  216.     }
  217.     /**
  218.      * Generate template with given file
  219.      *
  220.      * @param Template|object $objTemplate
  221.      * @param string          $strType
  222.      * @param array           $arrFile
  223.      * @param bool            $blnWatermark
  224.      *
  225.      * @return string
  226.      */
  227.     protected function addImageToTemplate(Template $objTemplate$strType, array $arrFile$blnWatermark true)
  228.     {
  229.         $arrFile $this->getImageForType($strType$arrFile$blnWatermark);
  230.         $objTemplate->setData($this->arrData);
  231.         $objTemplate->type       $strType;
  232.         $objTemplate->name       $this->getName();
  233.         $objTemplate->product_id $this->product_id;
  234.         $objTemplate->file       $arrFile;
  235.         $objTemplate->src        $arrFile[$strType];
  236.         $objTemplate->size       $arrFile[$strType '_size'];
  237.         $objTemplate->alt        $arrFile['alt'];
  238.         $objTemplate->title      $arrFile['desc'];
  239.         $objTemplate->class      trim(($this->arrData['class'] ?? '') . ' ' . ($arrFile['class'] ?? ''));
  240.         // Add the missing data to the picture
  241.         $arrFile['picture']['alt']   = $objTemplate->alt;
  242.         $arrFile['picture']['title'] = $objTemplate->title;
  243.         $arrFile['picture']['class'] = $objTemplate->class;
  244.         $objTemplate->picture $arrFile['picture'];
  245.         switch ($this->anchor) {
  246.             case 'reader':
  247.                 $objTemplate->hasLink = ($this->href != '');
  248.                 $objTemplate->link    $this->href;
  249.                 break;
  250.             case 'lightbox':
  251.                 $arrFile $this->getImageForType('lightbox'$arrFile$blnWatermark);
  252.                 [$link$rel] = explode('|'$arrFile['link'], 2) + [nullnull];
  253.                 $attributes = ($rel ' data-lightbox="' $rel '"' ' target="_blank"');
  254.                 $objTemplate->hasLink    true;
  255.                 $objTemplate->link       $link ?: $arrFile['lightbox'];
  256.                 $objTemplate->attributes = ($link $attributes ' data-lightbox="product' $this->product_id '"');
  257.                 break;
  258.             default:
  259.                 $objTemplate->hasLink false;
  260.                 break;
  261.         }
  262.     }
  263.     /**
  264.      * Gets the placeholder image
  265.      *
  266.      * @return array
  267.      *
  268.      * @throws \UnderflowException If no placeholder image is found
  269.      */
  270.     protected function getPlaceholderImage()
  271.     {
  272.         $objPlaceholder FilesModel::findByPk($this->placeholder);
  273.         if (null === $objPlaceholder) {
  274.             throw new \UnderflowException('Placeholder image requested but not defined!');
  275.         }
  276.         return array('src' => $objPlaceholder->path);
  277.     }
  278.     /**
  279.      * Gets the image for a given file and given type and optionally adds a watermark to it
  280.      *
  281.      * @param   string $strType
  282.      * @param   array $arrFile
  283.      * @param   bool  $blnWatermark
  284.      *
  285.      * @return  array
  286.      * @throws  \InvalidArgumentException
  287.      */
  288.     protected function getImageForType($strType, array $arrFile$blnWatermark true)
  289.     {
  290.         // Check cache
  291.         $strCacheKey md5($strType '-' json_encode($arrFile) . '-' . (int) $blnWatermark);
  292.         if (isset($this->arrImages[$strCacheKey])) {
  293.             return $this->arrImages[$strCacheKey];
  294.         }
  295.         $strFile $arrFile['src'];
  296.         // File without path must be located in the isotope root folder
  297.         if (strpos($strFile'/') === false) {
  298.             $strFile 'isotope/' strtolower(substr($strFile01)) . '/' $strFile;
  299.         }
  300.         $objFile = new File($strFile);
  301.         if (!$objFile->exists()) {
  302.             return [];
  303.         }
  304.         $size StringUtil::deserialize($this->{$strType '_size'}, true);
  305.         try {
  306.             $strImage = \Contao\Image::create($strFile$size)->executeResize()->getResizedPath();
  307.             $picture Picture::create($strFile$size)->getTemplateData();
  308.         } catch (\Exception $e) {
  309.             System::log('Image "' $strFile '" could not be processed: ' $e->getMessage(), __METHOD__TL_ERROR);
  310.             $strImage '';
  311.             $picture = array('img'=>array('src'=>'''srcset'=>''), 'sources'=>array());
  312.         }
  313.         // Watermark
  314.         if ($blnWatermark
  315.             && $this->{$strType '_watermark_image'} != ''
  316.             && ($objWatermark FilesModel::findByUuid($this->{$strType '_watermark_image'})) !== null
  317.         ) {
  318.             if (method_exists(File::class, 'createIfDeferred')) {
  319.                 (new File(rawurldecode($strImage)))->createIfDeferred();
  320.             }
  321.             $strImage Image::addWatermark($strImage$objWatermark->path$this->{$strType '_watermark_position'});
  322.             // Apply watermark to the picture image source
  323.             if ($picture['img']['src']) {
  324.                 $picture['img']['src'] = Image::addWatermark($picture['img']['src'], $objWatermark->path$this->{$strType '_watermark_position'});
  325.             }
  326.             // Apply watermark to the picture sources
  327.             foreach ($picture['sources'] as $k => $v) {
  328.                 $picture['sources'][$k]['src'] = Image::addWatermark($v['src'], $objWatermark->path$this->{$strType '_watermark_position'});
  329.             }
  330.         }
  331.         $arrSize = (new File(rawurldecode($strImage)))->imageSize;
  332.         if (\is_array($arrSize) && $arrSize[3] !== '') {
  333.             $arrFile[$strType '_size']      = $arrSize[3];
  334.             $arrFile[$strType '_imageSize'] = $arrSize;
  335.         }
  336.         $arrFile['alt']     = StringUtil::specialchars($arrFile['alt'] ?? ''true);
  337.         $arrFile['desc']    = StringUtil::specialchars($arrFile['desc'] ?? ''true);
  338.         $arrFile['picture'] = $picture;
  339.         $arrFile[$strType] = TL_ASSETS_URL $strImage;
  340.         $this->arrImages[$strCacheKey] = $arrFile;
  341.         return $arrFile;
  342.     }
  343. }