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.      * {@inheritdoc}
  232.      */
  233.     public function blockStart($showControls true$return false$additionalClass '')
  234.     {
  235.         $attr $this->getBlockAttributes();
  236.         $outerAttributes = [
  237.             'key' => $this->indices[$this->current] ?? null,
  238.         ];
  239.         $oAttr HtmlUtils::assembleAttributeString($outerAttributes);
  240.         $class 'pimcore_block_entry';
  241.         if (!empty($additionalClass)) {
  242.             $class sprintf('%s %s'$class$additionalClass);
  243.         }
  244.         $html '<div class="' $class '" ' $oAttr ' ' $attr '>';
  245.         if ($showControls) {
  246.             $html .= $this->blockControls(true);
  247.         }
  248.         if ($return) {
  249.             return $html;
  250.         }
  251.         $this->outputEditmode($html);
  252.     }
  253.     /**
  254.      * Custom position of button controls between blockStart -> blockEnd
  255.      *
  256.      * @param bool $return
  257.      */
  258.     public function blockControls($return false)
  259.     {
  260.         $attr $this->getBlockAttributes();
  261.         $html = <<<EOT
  262. <div class="pimcore_block_buttons" $attr>
  263.     <div class="pimcore_block_amount" $attr></div>
  264.     <div class="pimcore_block_plus" $attr></div>
  265.     <div class="pimcore_block_minus" $attr></div>
  266.     <div class="pimcore_block_up" $attr></div>
  267.     <div class="pimcore_block_down" $attr></div>
  268.     <div class="pimcore_block_clear" $attr></div>
  269. </div>
  270. EOT;
  271.         $this->current++;
  272.         if ($return) {
  273.             return $html;
  274.         }
  275.         $this->outputEditmode($html);
  276.     }
  277.     /**
  278.      * {@inheritdoc}
  279.      */
  280.     public function blockEnd($return false)
  281.     {
  282.         // close outer element
  283.         $html '</div>';
  284.         if ($return) {
  285.             return $html;
  286.         }
  287.         $this->outputEditmode($html);
  288.     }
  289.     /**
  290.      * {@inheritdoc}
  291.      */
  292.     public function setConfig($config)
  293.     {
  294.         if (empty($config['limit'])) {
  295.             $config['limit'] = 1000000;
  296.         }
  297.         $this->config $config;
  298.         if (($this->config['manual'] ?? false) === true) {
  299.             $this->config['reload'] = true;
  300.         }
  301.         return $this;
  302.     }
  303.     /**
  304.      * {@inheritdoc}
  305.      */
  306.     public function getCount()
  307.     {
  308.         return count($this->indices);
  309.     }
  310.     /**
  311.      * {@inheritdoc}
  312.      */
  313.     public function getCurrent()
  314.     {
  315.         return $this->current 1;
  316.     }
  317.     /**
  318.      * {@inheritdoc}
  319.      */
  320.     public function getCurrentIndex()
  321.     {
  322.         return $this->indices[$this->getCurrent()] ?? 0;
  323.     }
  324.     /**
  325.      * @return array
  326.      */
  327.     public function getIndices()
  328.     {
  329.         return $this->indices;
  330.     }
  331.     /**
  332.      * If object was serialized, set the counter back to 0
  333.      */
  334.     public function __wakeup()
  335.     {
  336.         $this->current 0;
  337.     }
  338.     /**
  339.      * {@inheritdoc}
  340.      */
  341.     public function isEmpty()
  342.     {
  343.         return !(bool) count($this->indices);
  344.     }
  345.     /**
  346.      * @return Block\Item[]
  347.      */
  348.     public function getElements()
  349.     {
  350.         $document $this->getDocument();
  351.         // https://github.com/pimcore/pimcore/issues/6629
  352.         if (!$document instanceof Model\Document\PageSnippet) {
  353.             return [];
  354.         }
  355.         $parentBlockNames $this->getParentBlockNames();
  356.         $parentBlockNames[] = $this->getName();
  357.         $list = [];
  358.         foreach ($this->getData() as $index) {
  359.             $list[] = new Block\Item($document$parentBlockNames, (int)$index);
  360.         }
  361.         return $list;
  362.     }
  363.     /**
  364.      * @return string
  365.      */
  366.     private function getBlockAttributes(): string
  367.     {
  368.         $attributes = [
  369.             'data-name' => $this->getName(),
  370.             'data-real-name' => $this->getRealName(),
  371.         ];
  372.         return HtmlUtils::assembleAttributeString($attributes);
  373.     }
  374.     /**
  375.      * @return bool
  376.      */
  377.     private function isIgnoreEditmodeIndices(): bool
  378.     {
  379.         $requestStack \Pimcore::getContainer()->get('request_stack');
  380.         $request $requestStack->getCurrentRequest();
  381.         if ($request === null) {
  382.             return false;
  383.         }
  384.         return $request->get(self::ATTRIBUTE_IGNORE_EDITMODE_INDICESfalse);
  385.     }
  386. }