/** * 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; }
/** * Get all attributes for current dom element * * @param \Magento\Framework\View\Layout\Element $element * @return array */ protected function getAttributes($element) { $attributes = []; foreach ($element->attributes() as $attrName => $attrValue) { $attributes[$attrName] = (string) $attrValue; } return $attributes; }
/** * Get ui component attributes * * @param Layout\Element $element * @return array */ protected function getAttributes(Layout\Element $element) { $attributes = []; foreach ($this->attributes as $attributeName) { $attributes[$attributeName] = (string) $element->getAttribute($attributeName); } return $attributes; }
/** * Schedule attributes to the page config structure * * @param Layout\Reader\Context $readerContext * @param Layout\Element $element * @return $this */ protected function setBodyAttributeToStructure(Layout\Reader\Context $readerContext, Layout\Element $element) { if ($element->getAttribute('name') == PageConfig::BODY_ATTRIBUTE_CLASS) { $readerContext->getPageConfigStructure()->setBodyClass($element->getAttribute('value')); } else { $readerContext->getPageConfigStructure()->setElementAttribute(PageConfig::ELEMENT_TYPE_BODY, $element->getAttribute('name'), $element->getAttribute('value')); } return $this; }
/** * Validate node's declared position in hierarchy and add errors to the specified array if found * * @param \SimpleXMLElement $node * @param \Magento\Framework\View\Layout\Element $xml * @param array &$errors */ protected function _collectHierarchyErrors($node, $xml, &$errors) { $name = $node->getName(); $refName = $node->getAttribute('type') == $node->getAttribute('parent'); if ($refName) { $refNode = $xml->xpath("/layouts/{$refName}"); if (!$refNode) { $errors[$name][] = "Node '{$refName}', referenced in hierarchy, does not exist"; } } }
/** * Schedule structural changes for move directive * * @param \Magento\Framework\View\Layout\ScheduledStructure $scheduledStructure * @param \Magento\Framework\View\Layout\Element $currentElement * @throws \Magento\Framework\Exception\LocalizedException * @return $this */ protected function scheduleMove(Layout\ScheduledStructure $scheduledStructure, Layout\Element $currentElement) { $elementName = (string) $currentElement->getAttribute('element'); $destination = (string) $currentElement->getAttribute('destination'); $alias = (string) $currentElement->getAttribute('as') ?: ''; if ($elementName && $destination) { list($siblingName, $isAfter) = $this->beforeAfterToSibling($currentElement); $scheduledStructure->setElementToMove($elementName, [$destination, $siblingName, $isAfter, $alias]); } else { throw new \Magento\Framework\Exception\LocalizedException(new \Magento\Framework\Phrase('Element name and destination must be specified.')); } return $this; }
/** * Validate node's declared position in hierarchy and add errors to the specified array if found * * @param \SimpleXMLElement $node * @param \Magento\Framework\View\Layout\Element $xml * @param array &$errors */ protected function _collectHierarchyErrors($node, $xml, &$errors) { $name = $node->getName(); $refName = $node->getAttribute('type') == $node->getAttribute('parent'); if ($refName) { $refNode = $xml->xpath("/layouts/{$refName}"); if (!$refNode) { if ($refName == 'checkout_cart_configure' || $refName == 'checkout_cart_configurefailed') { $this->markTestIncomplete('MAGETWO-9182'); } $errors[$name][] = "Node '{$refName}', referenced in hierarchy, does not exist"; } } }
public function testPrepare() { /** * @TODO: Need to use ObjectManager instead 'new'. * On this moment we have next bug MAGETWO-4274 which blocker for this key. */ $this->_model = new \Magento\Framework\View\Layout\Element(__DIR__ . '/_files/_layout_update.xml', 0, true); list($blockNode) = $this->_model->xpath('//block[@name="head"]'); list($actionNode) = $this->_model->xpath('//action[@method="setTitle"]'); $this->assertEmpty($blockNode->attributes()->parent); $this->assertEmpty($actionNode->attributes()->block); $this->_model->prepare(); $this->assertEquals('root', (string) $blockNode->attributes()->parent); $this->assertEquals('Magento\\Backend\\Block\\Page\\Head', (string) $blockNode->attributes()->class); $this->assertEquals('head', (string) $actionNode->attributes()->block); }
public function testInterpret() { $readerContextMock = $this->getMockBuilder('Magento\\Framework\\View\\Layout\\Reader\\Context')->disableOriginalConstructor()->getMock(); $structureMock = $this->getMockBuilder('Magento\\Framework\\View\\Page\\Config\\Structure')->disableOriginalConstructor()->getMock(); $readerContextMock->expects($this->once())->method('getPageConfigStructure')->willReturn($structureMock); $xml = file_get_contents(__DIR__ . '/../_files/template_head.xml'); $element = new Element($xml); $structureMock->expects($this->at(0))->method('setTitle')->with('Test title')->willReturnSelf(); $structureMock->expects($this->at(1))->method('setMetaData')->with('meta_name', 'meta_content')->willReturnSelf(); $structureMock->expects($this->at(2))->method('addAssets')->with('path/file.css', ['src' => 'path/file.css', 'media' => 'all', 'content_type' => 'css'])->willReturnSelf(); $structureMock->expects($this->at(3))->method('addAssets')->with('path/file.js', ['src' => 'path/file.js', 'defer' => 'defer', 'content_type' => 'js'])->willReturnSelf(); $structureMock->expects($this->at(4))->method('addAssets')->with('http://url.com', ['src' => 'http://url.com', 'src_type' => 'url'])->willReturnSelf(); $structureMock->expects($this->at(5))->method('removeAssets')->with('path/remove/file.css')->willReturnSelf(); $structureMock->expects($this->at(6))->method('setElementAttribute')->with(Config::ELEMENT_TYPE_HEAD, 'head_attribute_name', 'head_attribute_value')->willReturnSelf(); $this->assertEquals($this->model, $this->model->interpret($readerContextMock, $element->children()[0])); }
/** * Merge Container attributes * * @param \Magento\Framework\View\Layout\ScheduledStructure $scheduledStructure * @param \Magento\Framework\View\Layout\Element $currentElement * @return void */ protected function mergeContainerAttributes(Layout\ScheduledStructure $scheduledStructure, Layout\Element $currentElement) { $containerName = $currentElement->getAttribute('name'); $elementData = $scheduledStructure->getStructureElementData($containerName); if (isset($elementData['attributes'])) { $keys = array_keys($elementData['attributes']); foreach ($keys as $key) { if (isset($currentElement[$key])) { $elementData['attributes'][$key] = (string) $currentElement[$key]; } } } else { $elementData['attributes'] = [self::CONTAINER_OPT_HTML_TAG => (string) $currentElement[self::CONTAINER_OPT_HTML_TAG], self::CONTAINER_OPT_HTML_ID => (string) $currentElement[self::CONTAINER_OPT_HTML_ID], self::CONTAINER_OPT_HTML_CLASS => (string) $currentElement[self::CONTAINER_OPT_HTML_CLASS], self::CONTAINER_OPT_LABEL => (string) $currentElement[self::CONTAINER_OPT_LABEL]]; } $scheduledStructure->setStructureElementData($containerName, $elementData); }
/** * Set metadata * * @param \Magento\Framework\View\Page\Config\Structure $pageConfigStructure * @param \Magento\Framework\View\Layout\Element $node * @return void */ private function setMetadata($pageConfigStructure, $node) { if (!$node->getAttribute('name') && $node->getAttribute('property')) { $metadataName = $node->getAttribute('property'); } else { $metadataName = $node->getAttribute('name'); } $pageConfigStructure->setMetaData($metadataName, $node->getAttribute('content')); }
/** * {@inheritdoc} * * @param Context $readerContext * @param Layout\Element $currentElement * @param Layout\Element $parentElement * @return $this */ public function interpret(Context $readerContext, Layout\Element $currentElement) { $scheduledStructure = $readerContext->getScheduledStructure(); $scheduledStructure->setElementToRemoveList((string) $currentElement->getAttribute('name')); return $this; }
/** * Handling reference of container * * If attribute remove="true" then add the element to list remove, * else merge container attributes * * @param Layout\ScheduledStructure $scheduledStructure * @param Layout\Element $currentElement * @return void */ protected function containerReference(Layout\ScheduledStructure $scheduledStructure, Layout\Element $currentElement) { $containerName = $currentElement->getAttribute('name'); $containerRemove = filter_var($currentElement->getAttribute('remove'), FILTER_VALIDATE_BOOLEAN); if ($containerRemove) { $scheduledStructure->setElementToRemoveList($containerName); } else { $this->mergeContainerAttributes($scheduledStructure, $currentElement); } }
/** * Run action defined in layout update * * @param \Magento\Framework\View\Layout\Element $node * @param \Magento\Framework\View\Layout\Element $parent * @return void */ protected function _generateAction($node, $parent) { $configPath = $node->getAttribute('ifconfig'); if ($configPath && !$this->_scopeConfig->isSetFlag($configPath, $this->scopeType, $this->scopeResolver->getScope())) { return; } $method = $node->getAttribute('method'); $parentName = $node->getAttribute('block'); if (empty($parentName)) { $parentName = $parent->getElementName(); } $profilerKey = 'BLOCK_ACTION:' . $parentName . '>' . $method; \Magento\Framework\Profiler::start($profilerKey); $block = $this->getBlock($parentName); if (!empty($block)) { $args = $this->_parseArguments($node); $args = $this->_evaluateArguments($args); call_user_func_array(array($block, $method), $args); } \Magento\Framework\Profiler::stop($profilerKey); }
/** * @param \Magento\Framework\View\Layout\Element $currentElement * @param string $destination * @param string $siblingName * @param bool $isAfter * @param string $alias * @param \Magento\Framework\View\Layout\Element $parentElement * * @dataProvider processDataProvider */ public function testProcess($currentElement, $destination, $siblingName, $isAfter, $alias, $parentElement) { $this->scheduledStructureMock->expects($this->any())->method('setElementToMove')->with((string) $currentElement->getAttribute('element'), [$destination, $siblingName, $isAfter, $alias]); $this->move->interpret($this->contextMock, $currentElement, $parentElement); }