vendor/pimcore/pimcore/models/Document/Editable/Block.php line 25

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\Document\Editable\Block\BlockName;
  16. use Pimcore\Model;
  17. use Pimcore\Tool\HtmlUtils;
  18. /**
  19.  * @method \Pimcore\Model\Document\Editable\Dao getDao()
  20.  */
  21. class Block extends Model\Document\Editable implements BlockInterface
  22. {
  23.     /**
  24.      * @internal
  25.      */
  26.     const ATTRIBUTE_IGNORE_EDITMODE_INDICES '_block_ignore_extra_editmode_indices';
  27.     /**
  28.      * Contains an array of indices, which represent the order of the elements in the block
  29.      *
  30.      * @internal
  31.      *
  32.      * @var array
  33.      */
  34.     protected $indices = [];
  35.     /**
  36.      * Current step of the block while iteration
  37.      *
  38.      * @internal
  39.      *
  40.      * @var int
  41.      */
  42.     protected $current 0;
  43.     /**
  44.      * {@inheritdoc}
  45.      */
  46.     public function getType()
  47.     {
  48.         return 'block';
  49.     }
  50.     /**
  51.      * {@inheritdoc}
  52.      */
  53.     public function getData()
  54.     {
  55.         return $this->indices;
  56.     }
  57.     /**
  58.      * {@inheritdoc}
  59.      */
  60.     public function admin()
  61.     {
  62.         // nothing to do
  63.         return '';
  64.     }
  65.     /**
  66.      * {@inheritdoc}
  67.      */
  68.     public function frontend()
  69.     {
  70.         // nothing to do
  71.         return '';
  72.     }
  73.     /**
  74.      * {@inheritdoc}
  75.      */
  76.     public function setDataFromResource($data)
  77.     {
  78.         $this->indices \Pimcore\Tool\Serialize::unserialize($data);
  79.         return $this;
  80.     }
  81.     /**
  82.      * {@inheritdoc}
  83.      */
  84.     public function setDataFromEditmode($data)
  85.     {
  86.         $this->indices $data;
  87.         return $this;
  88.     }
  89.     /**
  90.      * @internal
  91.      *
  92.      * @return $this
  93.      */
  94.     protected function setDefault()
  95.     {
  96.         if (empty($this->indices) && isset($this->config['default']) && $this->config['default']) {
  97.             for ($i 0$i < (int)$this->config['default']; $i++) {
  98.                 $this->indices[$i] = $i 1;
  99.             }
  100.         }
  101.         return $this;
  102.     }
  103.     /**
  104.      * {@inheritdoc}
  105.      */
  106.     public function getIterator()
  107.     {
  108.         while ($this->loop()) {
  109.             yield $this->getCurrentIndex();
  110.         }
  111.         if ($this->getEditmode() && !$this->isIgnoreEditmodeIndices()) {
  112.             // yeah, I know the following is f******* crazy :D
  113.             $this->current 0;
  114.             $indicesBackup $this->indices;
  115.             $this->indices[0] = 1000000;
  116.             $this->getBlockState()->pushBlock(BlockName::createFromEditable($this));
  117.             $this->blockConstruct();
  118.             $blockStartHtml $this->blockStart(truetrue);
  119.             ob_start();
  120.             $editableDefCollector $this->getEditableDefinitionCollector();
  121.             $editableDefCollector->stashPush();
  122.             yield $this->getCurrentIndex() + 1;
  123.             $blockEndHtml $this->blockEnd(true);
  124.             $this->blockDestruct();
  125.             $blockState $this->getBlockState();
  126.             if ($blockState->hasBlocks()) {
  127.                 $blockState->popBlock();
  128.             }
  129.             $templateEditableDefinitions $editableDefCollector->getDefinitions();
  130.             $editableDefCollector->stashPull();
  131.             $this->config['template'] = [
  132.                 'html' => $blockStartHtml ob_get_clean() . $blockEndHtml,
  133.                 'editables' => $templateEditableDefinitions,
  134.             ];
  135.             $editableDefCollector->add($this);
  136.             $this->indices $indicesBackup;
  137.         }
  138.     }
  139.     /**
  140.      * @internal
  141.      *
  142.      * @return bool
  143.      */
  144.     public function loop()
  145.     {
  146.         $manual false;
  147.         if (($this->config['manual'] ?? false) == true) {
  148.             $manual true;
  149.         }
  150.         $this->setDefault();
  151.         if ($this->current 0) {
  152.             if (!$manual) {
  153.                 $this->blockDestruct();
  154.                 $this->blockEnd();
  155.             }
  156.         } else {
  157.             if (!$manual) {
  158.                 $this->start();
  159.             }
  160.         }
  161.         if ($this->current count($this->indices) && $this->current $this->config['limit']) {
  162.             if (!$manual) {
  163.                 $this->blockConstruct();
  164.                 $this->blockStart();
  165.             }
  166.             return true;
  167.         } else {
  168.             if (!$manual) {
  169.                 $this->end();
  170.             }
  171.             return false;
  172.         }
  173.     }
  174.     /**
  175.      * {@inheritdoc}
  176.      */
  177.     protected function getEditmodeElementAttributes(): array
  178.     {
  179.         $attributes parent::getEditmodeElementAttributes();
  180.         $attributes array_merge($attributes, [
  181.             'name' => $this->getName(),
  182.             'type' => $this->getType(),
  183.         ]);
  184.         return $attributes;
  185.     }
  186.     /**
  187.      * {@inheritdoc}
  188.      */
  189.     public function start()
  190.     {
  191.         // set name suffix for the whole block element, this will be added to all child elements of the block
  192.         $this->getBlockState()->pushBlock(BlockName::createFromEditable($this));
  193.         $attributes $this->getEditmodeElementAttributes();
  194.         $attributeString HtmlUtils::assembleAttributeString($attributes);
  195.         $this->outputEditmode('<div ' $attributeString '>');
  196.         return $this;
  197.     }
  198.     /**
  199.      * {@inheritdoc}
  200.      */
  201.     public function end()
  202.     {
  203.         $this->current 0;
  204.         // remove the current block which was set by $this->start()
  205.         $blockState $this->getBlockState();
  206.         if ($blockState->hasBlocks()) {
  207.             $blockState->popBlock();
  208.         }
  209.         $this->outputEditmode('</div>');
  210.     }
  211.     /**
  212.      * {@inheritdoc}
  213.      */
  214.     public function blockConstruct()
  215.     {
  216.         // set the current block suffix for the child elements (0, 1, 3, ...)
  217.         // this will be removed in blockDestruct
  218.         $this->getBlockState()->pushIndex($this->indices[$this->current] ?? 0);
  219.     }
  220.     /**
  221.      * {@inheritdoc}
  222.      */
  223.     public function blockDestruct()
  224.     {
  225.         $blockState $this->getBlockState();
  226.         if ($blockState->hasIndexes()) {
  227.             $blockState->popIndex();
  228.         }
  229.     }
  230.     /**
  231.      * @param bool $showControls
  232.      * @param bool $return
  233.      * @param string $additionalClass
  234.      */
  235.     public function blockStart($showControls true$return false$additionalClass '')
  236.     {
  237.         $attr $this->getBlockAttributes();
  238.         $outerAttributes = [
  239.             'key' => $this->indices[$this->current] ?? null,
  240.         ];
  241.         $oAttr HtmlUtils::assembleAttributeString($outerAttributes);
  242.         $class 'pimcore_block_entry';
  243.         if (!empty($additionalClass)) {
  244.             $class sprintf('%s %s'$class$additionalClass);
  245.         }
  246.         $html '<div class="' $class '" ' $oAttr ' ' $attr '>';
  247.         if ($showControls) {
  248.             $html .= $this->blockControls(true);
  249.         }
  250.         if ($return) {
  251.             return $html;
  252.         }
  253.         $this->outputEditmode($html);
  254.     }
  255.     /**
  256.      * Custom position of button controls between blockStart -> blockEnd
  257.      *
  258.      * @param bool $return
  259.      */
  260.     public function blockControls($return false)
  261.     {
  262.         $attr $this->getBlockAttributes();
  263.         $html = <<<EOT
  264. <div class="pimcore_block_buttons" $attr>
  265.     <div class="pimcore_block_amount" $attr></div>
  266.     <div class="pimcore_block_plus" $attr></div>
  267.     <div class="pimcore_block_minus" $attr></div>
  268.     <div class="pimcore_block_up" $attr></div>
  269.     <div class="pimcore_block_down" $attr></div>
  270.     <div class="pimcore_block_clear" $attr></div>
  271. </div>
  272. EOT;
  273.         $this->current++;
  274.         if ($return) {
  275.             return $html;
  276.         }
  277.         $this->outputEditmode($html);
  278.     }
  279.     /**
  280.      * @param bool $return
  281.      */
  282.     public function blockEnd($return false)
  283.     {
  284.         // close outer element
  285.         $html '</div>';
  286.         if ($return) {
  287.             return $html;
  288.         }
  289.         $this->outputEditmode($html);
  290.     }
  291.     /**
  292.      * {@inheritdoc}
  293.      */
  294.     public function setConfig($config)
  295.     {
  296.         if (empty($config['limit'])) {
  297.             $config['limit'] = 1000000;
  298.         }
  299.         $this->config $config;
  300.         if (($this->config['manual'] ?? false) === true) {
  301.             $this->config['reload'] = true;
  302.         }
  303.         return $this;
  304.     }
  305.     /**
  306.      * {@inheritdoc}
  307.      */
  308.     public function getCount()
  309.     {
  310.         return count($this->indices);
  311.     }
  312.     /**
  313.      * {@inheritdoc}
  314.      */
  315.     public function getCurrent()
  316.     {
  317.         return $this->current 1;
  318.     }
  319.     /**
  320.      * {@inheritdoc}
  321.      */
  322.     public function getCurrentIndex()
  323.     {
  324.         return $this->indices[$this->getCurrent()] ?? 0;
  325.     }
  326.     /**
  327.      * @return array
  328.      */
  329.     public function getIndices()
  330.     {
  331.         return $this->indices;
  332.     }
  333.     /**
  334.      * If object was serialized, set the counter back to 0
  335.      */
  336.     public function __wakeup()
  337.     {
  338.         $this->current 0;
  339.     }
  340.     /**
  341.      * {@inheritdoc}
  342.      */
  343.     public function isEmpty()
  344.     {
  345.         return !(bool) count($this->indices);
  346.     }
  347.     /**
  348.      * @return Block\Item[]
  349.      */
  350.     public function getElements()
  351.     {
  352.         $document $this->getDocument();
  353.         // https://github.com/pimcore/pimcore/issues/6629
  354.         if (!$document instanceof Model\Document\PageSnippet) {
  355.             return [];
  356.         }
  357.         $parentBlockNames $this->getParentBlockNames();
  358.         $parentBlockNames[] = $this->getName();
  359.         $list = [];
  360.         foreach ($this->getData() as $index) {
  361.             $list[] = new Block\Item($document$parentBlockNames, (int)$index);
  362.         }
  363.         return $list;
  364.     }
  365.     /**
  366.      * @return string
  367.      */
  368.     private function getBlockAttributes(): string
  369.     {
  370.         $attributes = [
  371.             'data-name' => $this->getName(),
  372.             'data-real-name' => $this->getRealName(),
  373.         ];
  374.         return HtmlUtils::assembleAttributeString($attributes);
  375.     }
  376.     /**
  377.      * @return bool
  378.      */
  379.     private function isIgnoreEditmodeIndices(): bool
  380.     {
  381.         $requestStack \Pimcore::getContainer()->get('request_stack');
  382.         $request $requestStack->getCurrentRequest();
  383.         if ($request === null) {
  384.             return false;
  385.         }
  386.         return $request->get(self::ATTRIBUTE_IGNORE_EDITMODE_INDICESfalse);
  387.     }
  388. }