vendor/pimcore/pimcore/lib/Templating/Renderer/IncludeRenderer.php line 125

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\Templating\Renderer;
  15. use Pimcore\Cache;
  16. use Pimcore\Model;
  17. use Pimcore\Model\Document\PageSnippet;
  18. use Pimcore\Model\Document\Targeting\TargetingDocumentInterface;
  19. use Pimcore\Model\Element;
  20. use Pimcore\Targeting\Document\DocumentTargetingConfigurator;
  21. use Pimcore\Tool\DeviceDetector;
  22. use Pimcore\Tool\DomCrawler;
  23. use Pimcore\Tool\Frontend;
  24. /**
  25.  * @internal
  26.  */
  27. class IncludeRenderer
  28. {
  29.     /**
  30.      * @var ActionRenderer
  31.      */
  32.     protected $actionRenderer;
  33.     /**
  34.      * @var DocumentTargetingConfigurator
  35.      */
  36.     private $targetingConfigurator;
  37.     public function __construct(
  38.         ActionRenderer $actionRenderer,
  39.         DocumentTargetingConfigurator $targetingConfigurator
  40.     ) {
  41.         $this->actionRenderer $actionRenderer;
  42.         $this->targetingConfigurator $targetingConfigurator;
  43.     }
  44.     /**
  45.      * Renders a document include
  46.      *
  47.      * @param mixed $include
  48.      * @param array $params
  49.      * @param bool $editmode
  50.      * @param bool $cacheEnabled
  51.      *
  52.      * @return string
  53.      */
  54.     public function render($include, array $params = [], $editmode false$cacheEnabled true)
  55.     {
  56.         if (!is_array($params)) {
  57.             $params = [];
  58.         }
  59.         $originalInclude $include;
  60.         // this is if $this->inc is called eg. with $this->relation() as argument
  61.         if (!$include instanceof PageSnippet && is_object($include) && method_exists($include'__toString')) {
  62.             $include = (string)$include;
  63.         }
  64.         if (is_numeric($include)) {
  65.             try {
  66.                 $include Model\Document::getById($include);
  67.             } catch (\Exception $e) {
  68.                 $include $originalInclude;
  69.             }
  70.         } elseif (is_string($include)) {
  71.             try {
  72.                 $include Model\Document::getByPath($include);
  73.             } catch (\Exception $e) {
  74.                 $include $originalInclude;
  75.             }
  76.         }
  77.         if ($include instanceof PageSnippet && $include->isPublished()) {
  78.             // apply best matching target group (if any)
  79.             $this->targetingConfigurator->configureTargetGroup($include);
  80.         }
  81.         // check if output-cache is enabled, if so, we're also using the cache here
  82.         $cacheKey null;
  83.         $cacheConfig false;
  84.         if ($cacheEnabled && !$editmode && $cacheConfig Frontend::isOutputCacheEnabled()) {
  85.             // cleanup params to avoid serializing Element\ElementInterface objects
  86.             $cacheParams $params;
  87.             $cacheParams['~~include-document'] = $originalInclude;
  88.             array_walk($cacheParams, function (&$value$key) {
  89.                 if ($value instanceof Element\ElementInterface) {
  90.                     $value $value->getId();
  91.                 } elseif (is_object($value) && method_exists($value'__toString')) {
  92.                     $value = (string)$value;
  93.                 }
  94.             });
  95.             // TODO is this enough for cache or should we disable caching completely?
  96.             if ($include instanceof TargetingDocumentInterface && $include->getUseTargetGroup()) {
  97.                 $cacheParams['target_group'] = $include->getUseTargetGroup();
  98.             }
  99.             $cacheKey 'tag_inc__' md5(serialize($cacheParams));
  100.             if ($content Cache::load($cacheKey)) {
  101.                 return $content;
  102.             }
  103.         }
  104.         $params array_merge($params, ['document' => $include]);
  105.         $content '';
  106.         if ($include instanceof PageSnippet && $include->isPublished()) {
  107.             $content $this->renderAction($include$params);
  108.             if ($editmode) {
  109.                 $content $this->modifyEditmodeContent($include$content);
  110.             }
  111.         }
  112.         // write contents to the cache, if output-cache is enabled & not in editmode
  113.         if ($cacheConfig && !$editmode && !DeviceDetector::getInstance()->wasUsed()) {
  114.             $cacheTags = ['output_inline'];
  115.             $cacheTags[] = $cacheConfig['lifetime'] ? 'output_lifetime' 'output';
  116.             Cache::save($content$cacheKey$cacheTags$cacheConfig['lifetime']);
  117.         }
  118.         return $content;
  119.     }
  120.     /**
  121.      * @param PageSnippet $include
  122.      * @param array $params
  123.      *
  124.      * @return string
  125.      */
  126.     protected function renderAction(PageSnippet $include$params)
  127.     {
  128.         return $this->actionRenderer->render($include$params);
  129.     }
  130.     /**
  131.      * in editmode, we need to parse the returned html from the document include
  132.      * add a class and the pimcore id / type so that it can be opened in editmode using the context menu
  133.      * if there's no first level HTML container => add one (wrapper)
  134.      *
  135.      * @param PageSnippet $include
  136.      * @param string $content
  137.      *
  138.      * @return string
  139.      */
  140.     protected function modifyEditmodeContent(PageSnippet $include$content)
  141.     {
  142.         $editmodeClass ' pimcore_editable pimcore_editable_inc ';
  143.         // this is if the content that is included does already contain markup/html
  144.         // this is needed by the editmode to highlight included documents
  145.         try {
  146.             $html = new DomCrawler($content);
  147.             $childs $html->filterXPath('//' DomCrawler::FRAGMENT_WRAPPER_TAG '/*'); // FRAGMENT_WRAPPER_TAG is added by DomCrawler for fragments
  148.             /** @var \DOMElement $child */
  149.             foreach ($childs as $child) {
  150.                 $child->setAttribute('class'$child->getAttribute('class') . $editmodeClass);
  151.                 $child->setAttribute('pimcore_type'$include->getType());
  152.                 $child->setAttribute('pimcore_id'$include->getId());
  153.             }
  154.             $content $html->html();
  155.             $html->clear();
  156.             unset($html);
  157.         } catch (\Exception $e) {
  158.             // add a div container if the include doesn't contain markup/html
  159.             $content '<div class="' $editmodeClass '" pimcore_id="' $include->getId() . '" pimcore_type="' $include->getType() . '">' $content '</div>';
  160.         }
  161.         return $content;
  162.     }
  163. }