Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Element.php
Go to the documentation of this file.
1 <?php
8 
15 class Element extends \SimpleXMLElement
16 {
26  protected $_parent = null;
27 
35  public function setParent($element)
36  {
37  //$this->_parent = $element;
38  }
39 
48  public function getParent()
49  {
50  if (!empty($this->_parent)) {
51  $parent = $this->_parent;
52  } else {
53  $arr = $this->xpath('..');
54  if (!isset($arr[0])) {
55  throw new \InvalidArgumentException('Root node could not be unset.');
56  }
57  $parent = $arr[0];
58  }
59  return $parent;
60  }
61 
68  public function hasChildren()
69  {
70  if (!$this->children()) {
71  return false;
72  }
73 
74  // simplexml bug: @attributes is in children() but invisible in foreach
75  foreach ($this->children() as $k => $child) {
76  return true;
77  }
78  return false;
79  }
80 
87  public function getAttribute($name)
88  {
89  $attrs = $this->attributes();
90  return isset($attrs[$name]) ? (string)$attrs[$name] : null;
91  }
92 
103  public function descend($path)
104  {
105  # $node = $this->xpath($path);
106  # return $node[0];
107  if (is_array($path)) {
108  $pathArr = $path;
109  } else {
110  // Simple exploding by / does not suffice,
111  // as an attribute value may contain a / inside
112  // Note that there are three matches for different kinds of attribute values specification
113  if (strpos($path, "@") === false) {
114  $pathArr = explode('/', $path);
115  } else {
116  $regex = "#([^@/\\\"]+(?:@[^=/]+=(?:\\\"[^\\\"]*\\\"|[^/]*))?)/?#";
117  $pathArr = $pathMatches = [];
118  if (preg_match_all($regex, $path, $pathMatches)) {
119  $pathArr = $pathMatches[1];
120  }
121  }
122  }
123  $desc = $this;
124  foreach ($pathArr as $nodeName) {
125  if (strpos($nodeName, '@') !== false) {
126  $a = explode('@', $nodeName);
127  $b = explode('=', $a[1]);
128  $nodeName = $a[0];
129  $attributeName = $b[0];
130  $attributeValue = $b[1];
131  //
132  // Does a very simplistic trimming of attribute value.
133  //
134  $attributeValue = trim($attributeValue, '"');
135  $found = false;
136  foreach ($desc->{$nodeName} as $subdesc) {
137  if ((string)$subdesc[$attributeName] === $attributeValue) {
138  $found = true;
139  $desc = $subdesc;
140  break;
141  }
142  }
143  if (!$found) {
144  $desc = false;
145  }
146  } else {
147  $desc = $desc->{$nodeName};
148  }
149  if (!$desc) {
150  return false;
151  }
152  }
153  return $desc;
154  }
155 
163  public function setAttribute($name, $value)
164  {
165  if (!isset($this->attributes()[$name])) {
166  $this->addAttribute($name, $value);
167  }
168 
169  $this->attributes()[$name] = $value;
170  }
171 
177  public function asArray()
178  {
179  return $this->_asArray();
180  }
181 
186  public function asCanonicalArray()
187  {
188  return $this->_asArray(true);
189  }
190 
197  protected function _asArray($isCanonical = false)
198  {
199  $result = [];
200  if (!$isCanonical) {
201  // add attributes
202  foreach ($this->attributes() as $attributeName => $attribute) {
203  if ($attribute) {
204  $result['@'][$attributeName] = (string)$attribute;
205  }
206  }
207  }
208  // add children values
209  if ($this->hasChildren()) {
210  foreach ($this->children() as $childName => $child) {
211  $result[$childName] = $child->_asArray($isCanonical);
212  }
213  } else {
214  if (empty($result)) {
215  // return as string, if nothing was found
216  $result = (string)$this;
217  } else {
218  // value has zero key element
219  $result[0] = (string)$this;
220  }
221  }
222  return $result;
223  }
224 
234  public function asNiceXml($filename = '', $level = 0)
235  {
236  if (is_numeric($level)) {
237  $pad = str_pad('', $level * 3, ' ', STR_PAD_LEFT);
238  $nl = "\n";
239  } else {
240  $pad = '';
241  $nl = '';
242  }
243 
244  $out = $pad . '<' . $this->getName();
245 
246  $attributes = $this->attributes();
247  if ($attributes) {
248  foreach ($attributes as $key => $value) {
249  $out .= ' ' . $key . '="' . str_replace('"', '\"', (string)$value) . '"';
250  }
251  }
252 
253  $attributes = $this->attributes('xsi', true);
254  if ($attributes) {
255  foreach ($attributes as $key => $value) {
256  $out .= ' xsi:' . $key . '="' . str_replace('"', '\"', (string)$value) . '"';
257  }
258  }
259 
260  if ($this->hasChildren()) {
261  $out .= '>';
262  $value = trim((string)$this);
263  if (strlen($value)) {
264  $out .= $this->xmlentities($value);
265  }
266  $out .= $nl;
267  foreach ($this->children() as $child) {
268  $out .= $child->asNiceXml('', is_numeric($level) ? $level + 1 : true);
269  }
270  $out .= $pad . '</' . $this->getName() . '>' . $nl;
271  } else {
272  $value = (string)$this;
273  if (strlen($value)) {
274  $out .= '>' . $this->xmlentities($value) . '</' . $this->getName() . '>' . $nl;
275  } else {
276  $out .= '/>' . $nl;
277  }
278  }
279 
280  if ((0 === $level || false === $level) && !empty($filename)) {
281  file_put_contents($filename, $out);
282  }
283 
284  return $out;
285  }
286 
293  public function innerXml($level = 0)
294  {
295  $out = '';
296  foreach ($this->children() as $child) {
297  $out .= $child->asNiceXml($level);
298  }
299  return $out;
300  }
301 
308  public function xmlentities($value = null)
309  {
310  if ($value === null) {
311  $value = $this;
312  }
313  $value = (string)$value;
314 
315  $value = str_replace(
316  ['&', '"', "'", '<', '>'],
317  ['&amp;', '&quot;', '&apos;', '&lt;', '&gt;'],
318  $value
319  );
320 
321  return $value;
322  }
323 
330  public function appendChild($source)
331  {
332  if ($source->count()) {
333  $child = $this->addChild($source->getName());
334  } else {
335  $child = $this->addChild($source->getName(), $this->xmlentities($source));
336  }
337  $child->setParent($this);
338 
339  $attributes = $source->attributes();
340  foreach ($attributes as $key => $value) {
341  $child->addAttribute($key, $this->xmlentities($value));
342  }
343 
344  foreach ($source->children() as $sourceChild) {
345  $child->appendChild($sourceChild);
346  }
347  return $this;
348  }
349 
360  public function extend($source, $overwrite = false)
361  {
362  if (!$source instanceof \Magento\Framework\Simplexml\Element) {
363  return $this;
364  }
365 
366  foreach ($source->children() as $child) {
367  $this->extendChild($child, $overwrite);
368  }
369 
370  return $this;
371  }
372 
382  public function extendChild($source, $overwrite = false)
383  {
384  // this will be our new target node
385  $targetChild = null;
386 
387  // name of the source node
388  $sourceName = $source->getName();
389 
390  // here we have children of our source node
391  $sourceChildren = $source->children();
392 
393  if (!$source->hasChildren()) {
394  // handle string node
395  if (isset($this->{$sourceName})) {
396  // if target already has children return without regard
397  if ($this->{$sourceName}->hasChildren()) {
398  return $this;
399  }
400  if ($overwrite) {
401  unset($this->{$sourceName});
402  } else {
403  return $this;
404  }
405  }
406 
407  $targetChild = $this->addChild($sourceName, $source->xmlentities());
408  $targetChild->setParent($this);
409  foreach ($source->attributes() as $key => $value) {
410  $targetChild->addAttribute($key, $this->xmlentities($value));
411  }
412  return $this;
413  }
414 
415  if (isset($this->{$sourceName})) {
416  $targetChild = $this->{$sourceName};
417  }
418 
419  if ($targetChild === null) {
420  // if child target is not found create new and descend
421  $targetChild = $this->addChild($sourceName);
422  $targetChild->setParent($this);
423  foreach ($source->attributes() as $key => $value) {
424  $targetChild->addAttribute($key, $this->xmlentities($value));
425  }
426  }
427 
428  // finally add our source node children to resulting new target node
429  foreach ($sourceChildren as $childKey => $childNode) {
430  $targetChild->extendChild($childNode, $overwrite);
431  }
432 
433  return $this;
434  }
435 
444  public function setNode($path, $value, $overwrite = true)
445  {
446  $arr1 = explode('/', $path);
447  $arr = [];
448  foreach ($arr1 as $v) {
449  if (!empty($v)) {
450  $arr[] = $v;
451  }
452  }
453  $last = sizeof($arr) - 1;
454  $node = $this;
455  foreach ($arr as $i => $nodeName) {
456  if ($last === $i) {
457  if (!isset($node->{$nodeName}) || $overwrite) {
458  $node->{$nodeName} = $value;
459  }
460  } else {
461  if (!isset($node->{$nodeName})) {
462  $node = $node->addChild($nodeName);
463  } else {
464  $node = $node->{$nodeName};
465  }
466  }
467  }
468  return $this;
469  }
470 
477  public function unsetSelf()
478  {
479  $uniqueId = uniqid();
480  $this['_unique_id'] = $uniqueId;
481  $children = $this->getParent()->xpath('*');
482  for ($i = count($children); $i > 0; $i--) {
483  if ($children[$i - 1][0]['_unique_id'] == $uniqueId) {
484  unset($children[$i - 1][0]);
485  return;
486  }
487  }
488  }
489 }
$source
Definition: source.php:23
$value
Definition: gender.phtml:16
$attributes
Definition: matrix.phtml:13
setNode($path, $value, $overwrite=true)
Definition: Element.php:444
$children
Definition: actions.phtml:11
_asArray($isCanonical=false)
Definition: Element.php:197
extend($source, $overwrite=false)
Definition: Element.php:360
$i
Definition: gallery.phtml:31
asNiceXml($filename='', $level=0)
Definition: Element.php:234
extendChild($source, $overwrite=false)
Definition: Element.php:382
if(!isset($_GET['name'])) $name
Definition: log.php:14
$element
Definition: element.phtml:12