<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Config\Model\Config\Structure; /** * @api * @since 100.0.2 */ class Converter implements \Magento\Framework\Config\ConverterInterface { /** * @var \Magento\Config\Model\Config\Structure\Mapper\Factory */ protected $_mapperFactory; /** * Mapper type list * * @var string[] */ protected $_mapperList = [ \Magento\Config\Model\Config\Structure\Mapper\Factory::MAPPER_EXTENDS, \Magento\Config\Model\Config\Structure\Mapper\Factory::MAPPER_PATH, \Magento\Config\Model\Config\Structure\Mapper\Factory::MAPPER_DEPENDENCIES, \Magento\Config\Model\Config\Structure\Mapper\Factory::MAPPER_ATTRIBUTE_INHERITANCE, \Magento\Config\Model\Config\Structure\Mapper\Factory::MAPPER_IGNORE, \Magento\Config\Model\Config\Structure\Mapper\Factory::MAPPER_SORTING, ]; /** * Map of single=>plural sub-node names per node * * E.G. first element makes all 'tab' nodes be renamed to 'tabs' in system node. * * @var array */ protected $_nameMap = [ 'system' => ['tab' => 'tabs', 'section' => 'sections'], 'section' => ['group' => 'children'], 'group' => ['field' => 'children', 'group' => 'children'], 'depends' => ['field' => 'fields'], ]; /** * @param \Magento\Config\Model\Config\Structure\Mapper\Factory $mapperFactory */ public function __construct(\Magento\Config\Model\Config\Structure\Mapper\Factory $mapperFactory) { $this->_mapperFactory = $mapperFactory; } /** * Convert dom document * * @param \DOMNode $source * @return array */ public function convert($source) { $result = $this->_convertDOMDocument($source); foreach ($this->_mapperList as $type) { /** @var $mapper MapperInterface */ $mapper = $this->_mapperFactory->create($type); $result = $mapper->map($result); } return $result; } /** * Retrieve \DOMDocument as array * * @param \DOMNode $root * @return array|null * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _convertDOMDocument(\DOMNode $root) { $result = $this->_processAttributes($root); $children = $root->childNodes; $processedSubLists = []; for ($i = 0; $i < $children->length; $i++) { $child = $children->item($i); $childName = $child->nodeName; $convertedChild = []; switch ($child->nodeType) { case XML_COMMENT_NODE: continue 2; break; case XML_TEXT_NODE: if ($children->length && trim($child->nodeValue, "\n ") === '') { continue 2; } $childName = 'value'; $convertedChild = $child->nodeValue; break; case XML_CDATA_SECTION_NODE: $childName = 'value'; $convertedChild = $child->nodeValue; break; default: /** @var $child \DOMElement */ if ($childName == 'attribute') { $childName = $child->getAttribute('type'); } $convertedChild = $this->_convertDOMDocument($child); break; } if (array_key_exists( $root->nodeName, $this->_nameMap ) && array_key_exists( $child->nodeName, $this->_nameMap[$root->nodeName] ) ) { $childName = $this->_nameMap[$root->nodeName][$child->nodeName]; $processedSubLists[] = $childName; $convertedChild['_elementType'] = $child->nodeName; } if (in_array($childName, $processedSubLists)) { $result = $this->_addProcessedNode($convertedChild, $result, $childName); } elseif (array_key_exists($childName, $result)) { $result[$childName] = [$result[$childName], $convertedChild]; $processedSubLists[] = $childName; } else { $result[$childName] = $convertedChild; } } if (count($result) == 1 && array_key_exists('value', $result)) { $result = $result['value']; } if ($result == []) { $result = null; } return $result; } /** * Add converted child with processed name * * @param array $convertedChild * @param array $result * @param string $childName * @return array */ protected function _addProcessedNode($convertedChild, $result, $childName) { if (is_array($convertedChild) && array_key_exists('id', $convertedChild)) { $result[$childName][$convertedChild['id']] = $convertedChild; } else { $result[$childName][] = $convertedChild; } return $result; } /** * Process element attributes * * @param \DOMNode $root * @return array */ protected function _processAttributes(\DOMNode $root) { $result = []; if ($root->hasAttributes()) { $attributes = $root->attributes; foreach ($attributes as $attribute) { if ($root->nodeName == 'attribute' && $attribute->name == 'type') { continue; } $result[$attribute->name] = $attribute->value; } return $result; } return $result; } }