vendor/pimcore/pimcore/models/Document/Tag/Areablock.php line 31

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\Tag;
  18. use Pimcore\Document\Tag\Block\BlockName;
  19. use Pimcore\Document\Tag\TagHandlerInterface;
  20. use Pimcore\Logger;
  21. use Pimcore\Model;
  22. use Pimcore\Model\Document;
  23. use Pimcore\Tool;
  24. use Pimcore\Tool\HtmlUtils;
  25. /**
  26.  * @method \Pimcore\Model\Document\Tag\Dao getDao()
  27.  */
  28. class Areablock extends Model\Document\Tag implements BlockInterface
  29. {
  30.     /**
  31.      * Contains an array of indices, which represent the order of the elements in the block
  32.      *
  33.      * @var array
  34.      */
  35.     public $indices = [];
  36.     /**
  37.      * Current step of the block while iteration
  38.      *
  39.      * @var int
  40.      */
  41.     public $current 0;
  42.     /**
  43.      * @var array
  44.      */
  45.     public $currentIndex;
  46.     /**
  47.      * @var bool
  48.      */
  49.     protected $blockStarted;
  50.     /**
  51.      * @see Document\Tag\TagInterface::getType
  52.      *
  53.      * @return string
  54.      */
  55.     public function getType()
  56.     {
  57.         return 'areablock';
  58.     }
  59.     /**
  60.      * @see Document\Tag\TagInterface::getData
  61.      *
  62.      * @return mixed
  63.      */
  64.     public function getData()
  65.     {
  66.         return $this->indices;
  67.     }
  68.     /**
  69.      * @see Document\Tag\TagInterface::admin
  70.      */
  71.     public function admin()
  72.     {
  73.         $this->frontend();
  74.     }
  75.     /**
  76.      * @see Document\Tag\TagInterface::frontend
  77.      */
  78.     public function frontend()
  79.     {
  80.         if (!is_array($this->indices)) {
  81.             $this->indices = [];
  82.         }
  83.         reset($this->indices);
  84.         while ($this->loop());
  85.     }
  86.     /**
  87.      * @param int $index
  88.      */
  89.     public function renderIndex($index)
  90.     {
  91.         $this->start();
  92.         $this->currentIndex $this->indices[$index];
  93.         $this->current $index;
  94.         $this->blockConstruct();
  95.         $this->blockStart();
  96.         $this->content();
  97.         $this->blockDestruct();
  98.         $this->blockEnd();
  99.         $this->end();
  100.     }
  101.     public function loop()
  102.     {
  103.         $disabled false;
  104.         $options $this->getOptions();
  105.         $manual false;
  106.         if (is_array($options) && array_key_exists('manual'$options) && $options['manual'] == true) {
  107.             $manual true;
  108.         }
  109.         if ($this->current 0) {
  110.             if (!$manual && $this->blockStarted) {
  111.                 $this->blockDestruct();
  112.                 $this->blockEnd();
  113.                 $this->blockStarted false;
  114.             }
  115.         } else {
  116.             if (!$manual) {
  117.                 $this->start();
  118.             }
  119.         }
  120.         if ($this->current count($this->indices) && $this->current $this->options['limit']) {
  121.             $index current($this->indices);
  122.             next($this->indices);
  123.             $this->currentIndex $index;
  124.             if (!empty($options['allowed']) && !in_array($index['type'], $options['allowed'])) {
  125.                 $disabled true;
  126.             }
  127.             if (!$this->getTagHandler()->isBrickEnabled($this$index['type']) && $options['dontCheckEnabled'] != true) {
  128.                 $disabled true;
  129.             }
  130.             $this->blockStarted false;
  131.             if (!$manual && !$disabled) {
  132.                 $this->blockConstruct();
  133.                 $this->blockStart();
  134.                 $this->blockStarted true;
  135.                 $this->content();
  136.             } elseif (!$manual) {
  137.                 $this->current++;
  138.             }
  139.             return true;
  140.         } else {
  141.             if (!$manual) {
  142.                 $this->end();
  143.             }
  144.             return false;
  145.         }
  146.     }
  147.     public function content()
  148.     {
  149.         // create info object and assign it to the view
  150.         $info = new Area\Info();
  151.         try {
  152.             $info->setId($this->currentIndex['type']);
  153.             $info->setTag($this);
  154.             $info->setIndex($this->current);
  155.         } catch (\Exception $e) {
  156.             Logger::err($e);
  157.         }
  158.         $params = [];
  159.         $options $this->getOptions();
  160.         if (isset($options['params']) && is_array($options['params']) && array_key_exists($this->currentIndex['type'], $options['params'])) {
  161.             if (is_array($options['params'][$this->currentIndex['type']])) {
  162.                 $params $options['params'][$this->currentIndex['type']];
  163.             }
  164.         }
  165.         if (isset($options['globalParams'])) {
  166.             $params array_merge($options['globalParams'], (array)$params);
  167.         }
  168.         $info->setParams($params);
  169.         if ($this->editmode || !isset($this->currentIndex['hidden']) || !$this->currentIndex['hidden']) {
  170.             $this->getTagHandler()->renderAreaFrontend($info);
  171.         }
  172.         $this->current++;
  173.     }
  174.     /**
  175.      * @return TagHandlerInterface
  176.      */
  177.     private function getTagHandler()
  178.     {
  179.         // TODO inject area handler via DI when tags are built through container
  180.         return \Pimcore::getContainer()->get('pimcore.document.tag.handler');
  181.     }
  182.     /**
  183.      * @see Document\Tag\TagInterface::setDataFromResource
  184.      *
  185.      * @param mixed $data
  186.      *
  187.      * @return $this
  188.      */
  189.     public function setDataFromResource($data)
  190.     {
  191.         $this->indices Tool\Serialize::unserialize($data);
  192.         if (!is_array($this->indices)) {
  193.             $this->indices = [];
  194.         }
  195.         return $this;
  196.     }
  197.     /**
  198.      * @see Document\Tag\TagInterface::setDataFromEditmode
  199.      *
  200.      * @param mixed $data
  201.      *
  202.      * @return $this
  203.      */
  204.     public function setDataFromEditmode($data)
  205.     {
  206.         $this->indices $data;
  207.         return $this;
  208.     }
  209.     /**
  210.      * Called before the block is rendered
  211.      */
  212.     public function blockConstruct()
  213.     {
  214.         // set the current block suffix for the child elements (0, 1, 3, ...)
  215.         // this will be removed in blockDestruct
  216.         $this->getBlockState()->pushIndex($this->indices[$this->current]['key']);
  217.     }
  218.     /**
  219.      * Called when the block was rendered
  220.      */
  221.     public function blockDestruct()
  222.     {
  223.         $this->getBlockState()->popIndex();
  224.     }
  225.     /**
  226.      * @return array
  227.      */
  228.     protected function getToolBarDefaultConfig()
  229.     {
  230.         return [
  231.             'areablock_toolbar' => [
  232.                 'width' => 172,
  233.                 'buttonWidth' => 168,
  234.                 'buttonMaxCharacters' => 20
  235.             ]
  236.         ];
  237.     }
  238.     /**
  239.      * @inheritDoc
  240.      */
  241.     protected function getEditmodeOptions(): array
  242.     {
  243.         $configOptions array_merge($this->getToolBarDefaultConfig(), $this->getOptions());
  244.         $options parent::getEditmodeOptions();
  245.         $options array_merge($options, [
  246.             'options' => $configOptions
  247.         ]);
  248.         return $options;
  249.     }
  250.     /**
  251.      * @inheritDoc
  252.      */
  253.     protected function getEditmodeElementAttributes(array $options): array
  254.     {
  255.         $attributes parent::getEditmodeElementAttributes($options);
  256.         $attributes array_merge($attributes, [
  257.             'name' => $this->getName(),
  258.             'type' => $this->getType()
  259.         ]);
  260.         return $attributes;
  261.     }
  262.     /**
  263.      * Is executed at the beginning of the loop and setup some general settings
  264.      *
  265.      * @return $this
  266.      */
  267.     public function start()
  268.     {
  269.         reset($this->indices);
  270.         $options $this->getEditmodeOptions();
  271.         $this->outputEditmodeOptions($options);
  272.         // set name suffix for the whole block element, this will be added to all child elements of the block
  273.         $this->getBlockState()->pushBlock(BlockName::createFromTag($this));
  274.         $attributes $this->getEditmodeElementAttributes($options);
  275.         $attributeString HtmlUtils::assembleAttributeString($attributes);
  276.         $this->outputEditmode('<div ' $attributeString '>');
  277.         return $this;
  278.     }
  279.     /**
  280.      * Is executed at the end of the loop and removes the settings set in start()
  281.      */
  282.     public function end()
  283.     {
  284.         $this->current 0;
  285.         // remove the current block which was set by $this->start()
  286.         $this->getBlockState()->popBlock();
  287.         $this->outputEditmode('</div>');
  288.     }
  289.     /**
  290.      * Is called evertime a new iteration starts (new entry of the block while looping)
  291.      */
  292.     public function blockStart()
  293.     {
  294.         $attributes = [
  295.             'data-name' => $this->getName(),
  296.             'data-real-name' => $this->getRealName(),
  297.         ];
  298.         $hidden 'false';
  299.         if (isset($this->indices[$this->current]['hidden']) && $this->indices[$this->current]['hidden']) {
  300.             $hidden 'true';
  301.         }
  302.         $outerAttributes = [
  303.             'key' => $this->indices[$this->current]['key'],
  304.             'type' => $this->indices[$this->current]['type'],
  305.             'data-hidden' => $hidden
  306.         ];
  307.         $attr HtmlUtils::assembleAttributeString($attributes);
  308.         $oAttr HtmlUtils::assembleAttributeString($outerAttributes);
  309.         // outer element
  310.         $this->outputEditmode('<div class="pimcore_area_entry pimcore_block_entry" ' $oAttr ' ' $attr '>');
  311.         $this->outputEditmode('<div class="pimcore_area_buttons" ' $attr '>');
  312.         $this->outputEditmode('<div class="pimcore_area_buttons_inner">');
  313.         $this->outputEditmode('<div class="pimcore_block_plus_up" ' $attr '></div>');
  314.         $this->outputEditmode('<div class="pimcore_block_plus" ' $attr '></div>');
  315.         $this->outputEditmode('<div class="pimcore_block_minus" ' $attr '></div>');
  316.         $this->outputEditmode('<div class="pimcore_block_up" ' $attr '></div>');
  317.         $this->outputEditmode('<div class="pimcore_block_down" ' $attr '></div>');
  318.         $this->outputEditmode('<div class="pimcore_block_type" ' $attr '></div>');
  319.         $this->outputEditmode('<div class="pimcore_block_options" ' $attr '></div>');
  320.         $this->outputEditmode('<div class="pimcore_block_visibility" ' $attr '></div>');
  321.         $this->outputEditmode('<div class="pimcore_block_label" ' $attr '></div>');
  322.         $this->outputEditmode('<div class="pimcore_block_clear" ' $attr '></div>');
  323.         $this->outputEditmode('</div>'); // .pimcore_area_buttons_inner
  324.         $this->outputEditmode('</div>'); // .pimcore_area_buttons
  325.     }
  326.     /**
  327.      * Is called evertime a new iteration ends (new entry of the block while looping)
  328.      */
  329.     public function blockEnd()
  330.     {
  331.         // close outer element
  332.         $this->outputEditmode('</div>');
  333.     }
  334.     /**
  335.      * @param array $options
  336.      *
  337.      * @return $this
  338.      */
  339.     public function setOptions($options)
  340.     {
  341.         // we need to set this here otherwise custom areaDir's won't work
  342.         $this->options $options;
  343.         if ($this->getView()) {
  344.             $translator = \Pimcore::getContainer()->get('translator');
  345.             if (!isset($options['allowed']) || !is_array($options['allowed'])) {
  346.                 $options['allowed'] = [];
  347.             }
  348.             $availableAreas $this->getTagHandler()->getAvailableAreablockAreas($this$options);
  349.             $availableAreas $this->sortAvailableAreas($availableAreas$options);
  350.             $options['types'] = $availableAreas;
  351.             if (isset($options['group']) && is_array($options['group'])) {
  352.                 $groupingareas = [];
  353.                 foreach ($availableAreas as $area) {
  354.                     $groupingareas[$area['type']] = $area['type'];
  355.                 }
  356.                 $groups = [];
  357.                 foreach ($options['group'] as $name => $areas) {
  358.                     $n $name;
  359.                     if ($this->editmode) {
  360.                         $n $translator->trans($name, [], 'admin');
  361.                     }
  362.                     $groups[$n] = $areas;
  363.                     foreach ($areas as $area) {
  364.                         unset($groupingareas[$area]);
  365.                     }
  366.                 }
  367.                 if (count($groupingareas) > 0) {
  368.                     $uncatAreas = [];
  369.                     foreach ($groupingareas as $area) {
  370.                         $uncatAreas[] = $area;
  371.                     }
  372.                     $n 'Uncategorized';
  373.                     if ($this->editmode) {
  374.                         $n $translator->trans($n, [], 'admin');
  375.                     }
  376.                     $groups[$n] = $uncatAreas;
  377.                 }
  378.                 $options['group'] = $groups;
  379.             }
  380.             if (empty($options['limit'])) {
  381.                 $options['limit'] = 1000000;
  382.             }
  383.             $this->options $options;
  384.         }
  385.         return $this;
  386.     }
  387.     /**
  388.      * Sorts areas by index (sorting option) first, then by name
  389.      *
  390.      * @param array $areas
  391.      * @param array $options
  392.      *
  393.      * @return array
  394.      */
  395.     protected function sortAvailableAreas(array $areas, array $options)
  396.     {
  397.         if (isset($options['sorting']) && is_array($options['sorting']) && count($options['sorting'])) {
  398.             $sorting $options['sorting'];
  399.         } else {
  400.             if (isset($options['allowed']) && is_array($options['allowed']) && count($options['allowed'])) {
  401.                 $sorting $options['allowed'];
  402.             } else {
  403.                 $sorting = [];
  404.             }
  405.         }
  406.         $result = [
  407.             'name' => [],
  408.             'index' => []
  409.         ];
  410.         foreach ($areas as $area) {
  411.             $sortIndex false;
  412.             if (!empty($sorting)) {
  413.                 $sortIndex array_search($area['type'], $sorting);
  414.             }
  415.             $sortKey 'name'// allowed and sorting is not set || areaName is not in allowed
  416.             if (false !== $sortIndex) {
  417.                 $sortKey 'index';
  418.                 $area['sortIndex'] = $sortIndex;
  419.             }
  420.             $result[$sortKey][] = $area;
  421.         }
  422.         // sort with translated names
  423.         if (count($result['name'])) {
  424.             usort($result['name'], function ($a$b) {
  425.                 if ($a['name'] == $b['name']) {
  426.                     return 0;
  427.                 }
  428.                 return ($a['name'] < $b['name']) ? -1;
  429.             });
  430.         }
  431.         // sort by allowed brick config order
  432.         if (count($result['index'])) {
  433.             usort($result['index'], function ($a$b) {
  434.                 return $a['sortIndex'] - $b['sortIndex'];
  435.             });
  436.         }
  437.         $result array_merge($result['index'], $result['name']);
  438.         return $result;
  439.     }
  440.     /**
  441.      * Return the amount of block elements
  442.      *
  443.      * @return int
  444.      */
  445.     public function getCount()
  446.     {
  447.         return count($this->indices);
  448.     }
  449.     /**
  450.      * Return current iteration step
  451.      *
  452.      * @return int
  453.      */
  454.     public function getCurrent()
  455.     {
  456.         return $this->current 1;
  457.     }
  458.     /**
  459.      * Return current index
  460.      *
  461.      * @return int
  462.      */
  463.     public function getCurrentIndex()
  464.     {
  465.         return $this->indices[$this->getCurrent()]['key'];
  466.     }
  467.     /**
  468.      * If object was serialized, set the counter back to 0
  469.      */
  470.     public function __wakeup()
  471.     {
  472.         $this->current 0;
  473.         reset($this->indices);
  474.     }
  475.     /**
  476.      * @return bool
  477.      */
  478.     public function isEmpty()
  479.     {
  480.         return !(bool) count($this->indices);
  481.     }
  482.     /**
  483.      * @deprecated
  484.      *
  485.      * @param Model\Webservice\Data\Document\Element $wsElement
  486.      * @param Model\Document\PageSnippet $document
  487.      * @param array $params
  488.      * @param Model\Webservice\IdMapperInterface|null $idMapper
  489.      *
  490.      * @throws \Exception
  491.      */
  492.     public function getFromWebserviceImport($wsElement$document null$params = [], $idMapper null)
  493.     {
  494.         $data $this->sanitizeWebserviceData($wsElement->value);
  495.         if (($data->indices === null || is_array($data->indices)) && ($data->current == null || is_numeric($data->current))
  496.             && ($data->currentIndex == null || is_numeric($data->currentIndex))) {
  497.             $indices $data->indices;
  498.             $indices json_decode(json_encode($indices), true);
  499.             $this->indices $indices;
  500.             $this->current $data->current;
  501.             $this->currentIndex $data->currentIndex;
  502.         } else {
  503.             throw new \Exception('cannot get  values from web service import - invalid data');
  504.         }
  505.     }
  506.     /**
  507.      * @param string $name
  508.      *
  509.      * @return Areablock\Item[]
  510.      */
  511.     public function getElement(string $name)
  512.     {
  513.         $document $this->getDocument();
  514.         $parentBlockNames $this->getParentBlockNames();
  515.         $parentBlockNames[] = $this->getName();
  516.         $list = [];
  517.         foreach ($this->getData() as $index => $item) {
  518.             if ($item['type'] === $name) {
  519.                 $list[$index] = new Areablock\Item($document$parentBlockNames, (int)$item['key']);
  520.             }
  521.         }
  522.         return $list;
  523.     }
  524. }