![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/vendor/magento/framework/View/Layout/ScheduledStructure/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\View\Layout\ScheduledStructure; use Magento\Framework\View\Layout; use Magento\Framework\App\State; class Helper { /** * Scheduled structure array indexes */ public const SCHEDULED_STRUCTURE_INDEX_TYPE = 0; public const SCHEDULED_STRUCTURE_INDEX_ALIAS = 1; public const SCHEDULED_STRUCTURE_INDEX_PARENT_NAME = 2; public const SCHEDULED_STRUCTURE_INDEX_SIBLING_NAME = 3; public const SCHEDULED_STRUCTURE_INDEX_IS_AFTER = 4; /** * @var int */ protected $counter = 0; /** * @var \Psr\Log\LoggerInterface */ protected $logger; /** * @var State */ protected $state; /** * @param \Psr\Log\LoggerInterface $logger * @param State $state */ public function __construct( \Psr\Log\LoggerInterface $logger, State $state ) { $this->logger = $logger; $this->state = $state; } /** * Generate anonymous element name for structure * * @param string $class * @return string */ protected function _generateAnonymousName($class) { $position = strpos($class, '\\Block\\'); $key = $position !== false ? substr($class, $position + 7) : $class; $key = strtolower(trim($key, '_')); return $key . $this->counter++; } /** * Populate queue for generating structural elements * * @param Layout\ScheduledStructure $scheduledStructure * @param \Magento\Framework\View\Layout\Element $currentNode * @param \Magento\Framework\View\Layout\Element $parentNode * @return string * @see scheduleElement() where the scheduledStructure is used */ public function scheduleStructure( Layout\ScheduledStructure $scheduledStructure, Layout\Element $currentNode, Layout\Element $parentNode ) { // if it hasn't a name it must be generated if (!(string)$currentNode->getAttribute('name')) { $name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block'); $currentNode->setAttribute('name', $name); } $path = $name = (string)$currentNode->getAttribute('name'); // Prepare scheduled element with default parameters [type, alias, parentName, siblingName, isAfter] $row = [ self::SCHEDULED_STRUCTURE_INDEX_TYPE => $currentNode->getName(), self::SCHEDULED_STRUCTURE_INDEX_ALIAS => '', self::SCHEDULED_STRUCTURE_INDEX_PARENT_NAME => '', self::SCHEDULED_STRUCTURE_INDEX_SIBLING_NAME => null, self::SCHEDULED_STRUCTURE_INDEX_IS_AFTER => true, ]; $parentName = $parentNode->getElementName(); //if this element has a parent element, there must be reset [alias, parentName, siblingName, isAfter] if ($parentName) { $row[self::SCHEDULED_STRUCTURE_INDEX_ALIAS] = (string)$currentNode->getAttribute('as'); $row[self::SCHEDULED_STRUCTURE_INDEX_PARENT_NAME] = $parentName; list($row[self::SCHEDULED_STRUCTURE_INDEX_SIBLING_NAME], $row[self::SCHEDULED_STRUCTURE_INDEX_IS_AFTER]) = $this->_beforeAfterToSibling($currentNode); // materialized path for referencing nodes in the plain array of _scheduledStructure if ($scheduledStructure->hasPath($parentName)) { $path = $scheduledStructure->getPath($parentName) . '/' . $path; } } $this->_overrideElementWorkaround($scheduledStructure, $name, $path); $scheduledStructure->setPathElement($name, $path); $scheduledStructure->setStructureElement($name, $row); return $name; } /** * Destroy previous element with same name and all its children, if new element overrides it * * This is a workaround to handle situation, when an element emerges with name of element that already exists. * In this case we destroy entire structure of the former element and replace with the new one. * * @param Layout\ScheduledStructure $scheduledStructure * @param string $name * @param string $path * @return void */ protected function _overrideElementWorkaround(Layout\ScheduledStructure $scheduledStructure, $name, $path) { if ($scheduledStructure->hasStructureElement($name)) { $scheduledStructure->setStructureElementData($name, []); foreach ($scheduledStructure->getPaths() as $potentialChild => $childPath) { if (0 === strpos($childPath ?? '', "{$path}/")) { $scheduledStructure->unsetPathElement($potentialChild); $scheduledStructure->unsetStructureElement($potentialChild); } } } } /** * Analyze "before" and "after" information in the node and return sibling name and whether "after" or "before" * * @param \Magento\Framework\View\Layout\Element $node * @return array */ protected function _beforeAfterToSibling($node) { $result = [null, true]; if (isset($node['after'])) { $result[0] = (string)$node['after']; } elseif (isset($node['before'])) { $result[0] = (string)$node['before']; $result[1] = false; } return $result; } /** * Process queue of structural elements and actually add them to structure, and schedule elements for generation * * The catch is to populate parents first, if they are not in the structure yet. * Since layout updates could come in arbitrary order, a case is possible where an element is declared in reference, * while referenced element itself is not declared yet. * * @param \Magento\Framework\View\Layout\ScheduledStructure $scheduledStructure * @param Layout\Data\Structure $structure * @param string $key in _scheduledStructure represent element name * @return void * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function scheduleElement( Layout\ScheduledStructure $scheduledStructure, Layout\Data\Structure $structure, $key ) { $row = $scheduledStructure->getStructureElement($key); $data = $scheduledStructure->getStructureElementData($key); // if we have reference container to not existed element if (!isset($row[self::SCHEDULED_STRUCTURE_INDEX_TYPE])) { $this->logger->critical("Broken reference: missing declaration of the element '{$key}'."); $scheduledStructure->unsetPathElement($key); $scheduledStructure->unsetStructureElement($key); return; } list($type, $alias, $parentName, $siblingName, $isAfter) = $row; $name = $this->_createStructuralElement($structure, $key, $type, $parentName . $alias); if ($parentName) { // recursively populate parent first if ($scheduledStructure->hasStructureElement($parentName)) { $this->scheduleElement($scheduledStructure, $structure, $parentName); } if ($structure->hasElement($parentName)) { try { $structure->setAsChild($name, $parentName, $alias); } catch (\Exception $e) { $this->logger->critical($e); } } else { $scheduledStructure->setElementToBrokenParentList($key); if ($this->state->getMode() === State::MODE_DEVELOPER) { $this->logger->info( "Broken reference: the '{$name}' element cannot be added as child to '{$parentName}', " . 'because the latter doesn\'t exist' ); } } } // Move from scheduledStructure to scheduledElement $scheduledStructure->unsetStructureElement($key); $scheduledStructure->setElement($name, [$type, $data]); /** * Some elements provide info "after" or "before" which sibling they are supposed to go * Add element into list of sorting */ if ($siblingName) { $scheduledStructure->setElementToSortList($parentName, $name, $siblingName, $isAfter); } } /** * Register an element in structure * * Will assign an "anonymous" name to the element, if provided with an empty name * * @param Layout\Data\Structure $structure * @param string $name * @param string $type * @param string $class * @return string */ protected function _createStructuralElement(Layout\Data\Structure $structure, $name, $type, $class) { if (empty($name)) { $name = $this->_generateAnonymousName($class); } $structure->createElement($name, ['type' => $type]); return $name; } }