Parser.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Xml;
  7. class Parser
  8. {
  9. /**
  10. * @var \DOMDocument|null
  11. */
  12. protected $_dom = null;
  13. /**
  14. * @var \DOMDocument
  15. */
  16. protected $_currentDom;
  17. /**
  18. * @var array
  19. */
  20. protected $_content = [];
  21. /**
  22. * @var boolean
  23. */
  24. protected $errorHandlerIsActive = false;
  25. /**
  26. *
  27. */
  28. public function __construct()
  29. {
  30. $this->_dom = new \DOMDocument();
  31. $this->_currentDom = $this->_dom;
  32. return $this;
  33. }
  34. /**
  35. * Initializes error handler
  36. *
  37. * @return void
  38. */
  39. public function initErrorHandler()
  40. {
  41. $this->errorHandlerIsActive = true;
  42. }
  43. /**
  44. * @return \DOMDocument|null
  45. */
  46. public function getDom()
  47. {
  48. return $this->_dom;
  49. }
  50. /**
  51. * @return \DOMDocument
  52. */
  53. protected function _getCurrentDom()
  54. {
  55. return $this->_currentDom;
  56. }
  57. /**
  58. * @param \DOMDocument $node
  59. * @return $this
  60. */
  61. protected function _setCurrentDom($node)
  62. {
  63. $this->_currentDom = $node;
  64. return $this;
  65. }
  66. /**
  67. * @return array
  68. */
  69. public function xmlToArray()
  70. {
  71. $this->_content = $this->_xmlToArray();
  72. return $this->_content;
  73. }
  74. /**
  75. * @param bool $currentNode
  76. * @return array
  77. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  78. * @SuppressWarnings(PHPMD.NPathComplexity)
  79. */
  80. protected function _xmlToArray($currentNode = false)
  81. {
  82. if (!$currentNode) {
  83. $currentNode = $this->getDom();
  84. }
  85. $content = '';
  86. foreach ($currentNode->childNodes as $node) {
  87. switch ($node->nodeType) {
  88. case XML_ELEMENT_NODE:
  89. $content = $content ?: [];
  90. $value = null;
  91. if ($node->hasChildNodes()) {
  92. $value = $this->_xmlToArray($node);
  93. }
  94. $attributes = [];
  95. if ($node->hasAttributes()) {
  96. foreach ($node->attributes as $attribute) {
  97. $attributes += [$attribute->name => $attribute->value];
  98. }
  99. $value = ['_value' => $value, '_attribute' => $attributes];
  100. }
  101. if (isset($content[$node->nodeName])) {
  102. if ((is_string($content[$node->nodeName]) || !isset($content[$node->nodeName][0]))
  103. || (is_array($value) && !is_array($content[$node->nodeName][0]))
  104. ) {
  105. $oldValue = $content[$node->nodeName];
  106. $content[$node->nodeName] = [];
  107. $content[$node->nodeName][] = $oldValue;
  108. }
  109. $content[$node->nodeName][] = $value;
  110. } else {
  111. $content[$node->nodeName] = $value;
  112. }
  113. break;
  114. case XML_CDATA_SECTION_NODE:
  115. $content = $node->nodeValue;
  116. break;
  117. case XML_TEXT_NODE:
  118. if (trim($node->nodeValue) !== '') {
  119. $content = $node->nodeValue;
  120. }
  121. break;
  122. }
  123. }
  124. return $content;
  125. }
  126. /**
  127. * @param string $file
  128. * @return $this
  129. */
  130. public function load($file)
  131. {
  132. $this->getDom()->load($file);
  133. return $this;
  134. }
  135. /**
  136. * @param string $string
  137. * @return $this
  138. * @throws \Magento\Framework\Exception\LocalizedException
  139. */
  140. public function loadXML($string)
  141. {
  142. if ($this->errorHandlerIsActive) {
  143. set_error_handler([$this, 'errorHandler']);
  144. }
  145. try {
  146. $this->getDom()->loadXML($string);
  147. } catch (\Magento\Framework\Exception\LocalizedException $e) {
  148. restore_error_handler();
  149. throw new \Magento\Framework\Exception\LocalizedException(
  150. new \Magento\Framework\Phrase($e->getMessage()),
  151. $e
  152. );
  153. }
  154. if ($this->errorHandlerIsActive) {
  155. restore_error_handler();
  156. }
  157. return $this;
  158. }
  159. /**
  160. * Custom XML lib error handler
  161. *
  162. * @param int $errorNo
  163. * @param string $errorStr
  164. * @param string $errorFile
  165. * @param int $errorLine
  166. * @throws \Magento\Framework\Exception\LocalizedException
  167. * @return void
  168. */
  169. public function errorHandler($errorNo, $errorStr, $errorFile, $errorLine)
  170. {
  171. if ($errorNo != 0) {
  172. $message = "{$errorStr} in {$errorFile} on line {$errorLine}";
  173. throw new \Magento\Framework\Exception\LocalizedException(new \Magento\Framework\Phrase($message));
  174. }
  175. }
  176. }