Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Dom.php
Go to the documentation of this file.
1 <?php
7 
12 
16 class Dom extends ConfigDom
17 {
23  private $idAttributes = [];
24 
28  private $domXPath;
29 
35  private $schemaFile;
36 
40  private $schemaLocator;
41 
52  public function __construct(
53  $xml,
54  ValidationStateInterface $validationState,
55  SchemaLocatorInterface $schemaLocator,
56  array $idAttributes = [],
57  $typeAttributeName = null,
58  $errorFormat = ConfigDom::ERROR_FORMAT_DEFAULT
59  ) {
60  $this->idAttributes = array_values($idAttributes);
61  $this->schemaFile = $schemaLocator->getPerFileSchema() && $validationState->isValidationRequired()
62  ? $schemaLocator->getPerFileSchema() : null;
63 
64  parent::__construct($xml, $validationState, $idAttributes, $typeAttributeName, $this->schemaFile, $errorFormat);
65  $this->schemaLocator = $schemaLocator;
66  }
67 
74  public function merge($xml)
75  {
76  $dom = $this->_initDom($xml);
77  $this->domXPath = new \DOMXPath($this->getDom());
78  $this->nestedMerge($this->getDom()->documentElement, $dom->childNodes);
79  }
80 
88  private function nestedMerge(\DOMNode $contextNode, \DOMNodeList $insertedNodes)
89  {
90  foreach ($insertedNodes as $insertedItem) {
91  switch ($insertedItem->nodeType) {
92  case XML_COMMENT_NODE:
93  break;
94  case XML_TEXT_NODE:
95  case XML_CDATA_SECTION_NODE:
96  if (trim($insertedItem->textContent) !== '') {
97  $importNode = $this->getDom()->importNode($insertedItem, true);
98  $contextNode->insertBefore($importNode);
99  }
100  break;
101  default:
102  $insertedXPath = $this->createXPath($insertedItem);
103  $rootMatchList = $this->domXPath->query($insertedXPath);
104 
105  $jLength = $rootMatchList->length;
106  if ($jLength > 0) {
107  $this->processMatchedNodes($rootMatchList, $insertedItem);
108  } else {
109  $this->appendNode($insertedItem, $contextNode);
110  }
111 
112  break;
113  }
114  }
115  }
116 
124  private function processMatchedNodes(\DOMNodeList $rootMatchList, \DOMElement $insertedItem)
125  {
126  foreach ($rootMatchList as $rootItem) {
127  if ($this->_isTextNode($insertedItem) && $this->_isTextNode($rootItem)) {
128  $rootItem->nodeValue = $insertedItem->nodeValue;
129  } else {
130  $this->nestedMerge($rootItem, $insertedItem->childNodes);
131  $this->_mergeAttributes($rootItem, $insertedItem);
132  }
133  }
134  }
135 
142  private function createXPath(\DOMNode $node)
143  {
144  $parentXPath = '';
145  $currentXPath = $node->getNodePath();
146  if ($node->parentNode !== null && !$node->isSameNode($node->parentNode)) {
147  $parentXPath = $this->createXPath($node->parentNode);
148  $pathParts = explode('/', $currentXPath);
149  $currentXPath = '/' . end($pathParts);
150  }
151  $attributesXPath = '';
152  if ($node->hasAttributes()) {
153  $attributes = [];
154  foreach ($node->attributes as $name => $attribute) {
155  if (in_array($name, $this->idAttributes)) {
156  $attributes[] = sprintf('@%s="%s"', $name, $attribute->value);
157  break;
158  }
159  }
160  if (!empty($attributes)) {
161  if (substr($currentXPath, -1) === ']') {
162  $currentXPath = substr($currentXPath, 0, strrpos($currentXPath, '['));
163  }
164  $attributesXPath = '[' . implode(' and ', $attributes) . ']';
165  }
166  }
167  return '/' . trim($parentXPath . $currentXPath . $attributesXPath, '/');
168  }
169 
177  private function appendNode(\DOMNode $insertedNode, \DOMNode $contextNode)
178  {
179  $importNode = $this->getDom()->importNode($insertedNode, true);
180  if (in_array($importNode->localName, [Converter::ARGUMENT_KEY, Converter::SETTINGS_KEY])) {
181  $this->appendNodeToContext($contextNode, $importNode);
182  } else {
183  $contextNode->appendChild($importNode);
184  }
185  }
186 
194  private function appendNodeToContext(\DOMNode $contextNode, \DOMNode $importNode)
195  {
196  if (!$contextNode->hasChildNodes()) {
197  $contextNode->appendChild($importNode);
198  return;
199  }
200  $childContextNode = null;
202  foreach ($contextNode->childNodes as $child) {
203  if ($child->nodeType != XML_ELEMENT_NODE) {
204  continue;
205  }
206  switch ($child->localName) {
208  $childContextNode = $child->nextSibling;
209  break;
210  case Converter::SETTINGS_KEY:
211  $childContextNode = $child;
212  break;
213  default:
214  if (!$childContextNode) {
215  $childContextNode = $child;
216  }
217  break;
218  }
219  }
220 
221  $contextNode->insertBefore($importNode, $childContextNode);
222  }
223 }
__construct( $xml, ValidationStateInterface $validationState, SchemaLocatorInterface $schemaLocator, array $idAttributes=[], $typeAttributeName=null, $errorFormat=ConfigDom::ERROR_FORMAT_DEFAULT)
Definition: Dom.php:52
$attributes
Definition: matrix.phtml:13
_mergeAttributes($baseNode, $mergeNode)
Definition: Dom.php:231
if(!isset($_GET['name'])) $name
Definition: log.php:14