/src/Magento/FunctionalTestingFramework/Config/Converter.php

https://github.com/magento/magento2-functional-testing-framework · PHP · 218 lines · 116 code · 17 blank · 85 comment · 20 complexity · 56ba0dfcc886a16d94490454cf86d97f MD5 · raw file

  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\FunctionalTestingFramework\Config;
  7. use Magento\FunctionalTestingFramework\ObjectManager\Config\Mapper\ArgumentParser;
  8. use Magento\FunctionalTestingFramework\Data\Argument\InterpreterInterface;
  9. /**
  10. * Converter for configuration data.
  11. */
  12. class Converter implements \Magento\FunctionalTestingFramework\Config\ConverterInterface
  13. {
  14. /**
  15. * Unique identifier of node.
  16. */
  17. const NAME_ATTRIBUTE = 'name';
  18. /**
  19. * Argument parser.
  20. *
  21. * @var ArgumentParser
  22. */
  23. protected $argumentParser;
  24. /**
  25. * Argument interpreter.
  26. *
  27. * @var InterpreterInterface
  28. */
  29. protected $argumentInterpreter;
  30. /**
  31. * Argument node name.
  32. *
  33. * @var string
  34. */
  35. protected $argumentNodeName;
  36. /**
  37. * Id attributes.
  38. *
  39. * @var string[]
  40. */
  41. protected $idAttributes;
  42. /**
  43. * Constructor for Converter object.
  44. *
  45. * @param ArgumentParser $argumentParser
  46. * @param InterpreterInterface $argumentInterpreter
  47. * @param string $argumentNodeName
  48. * @param array $idAttributes
  49. */
  50. public function __construct(
  51. ArgumentParser $argumentParser,
  52. InterpreterInterface $argumentInterpreter,
  53. $argumentNodeName,
  54. array $idAttributes = []
  55. ) {
  56. $this->argumentParser = $argumentParser;
  57. $this->argumentInterpreter = $argumentInterpreter;
  58. $this->argumentNodeName = $argumentNodeName;
  59. $this->idAttributes = $idAttributes;
  60. }
  61. /**
  62. * Convert XML to array.
  63. *
  64. * @param \DOMDocument $source
  65. * @return array
  66. */
  67. public function convert($source)
  68. {
  69. return $this->convertXml($source->documentElement->childNodes);
  70. }
  71. /**
  72. * Convert XML node to array or string recursive.
  73. *
  74. * @param \DOMNodeList|array $elements
  75. * @return array
  76. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  77. * @TODO ported magento code - to be refactored later
  78. */
  79. protected function convertXml($elements)
  80. {
  81. $result = [];
  82. foreach ($elements as $element) {
  83. if ($element instanceof \DOMElement) {
  84. if ($element->getAttribute('remove') === 'true') {
  85. // Remove element
  86. continue;
  87. }
  88. if ($element->hasAttribute('xsi:type')) {
  89. if ($element->hasAttribute('path')) {
  90. $elementData = $this->getAttributes($element);
  91. $elementData['value'] = $this->argumentInterpreter->evaluate(
  92. $this->argumentParser->parse($element)
  93. );
  94. unset($elementData['xsi:type'], $elementData['item']);
  95. } else {
  96. $elementData = $this->argumentInterpreter->evaluate(
  97. $this->argumentParser->parse($element)
  98. );
  99. }
  100. } else {
  101. $elementData = array_merge(
  102. $this->getAttributes($element),
  103. $this->getChildNodes($element)
  104. );
  105. }
  106. $key = $this->getElementKey($element);
  107. if ($key) {
  108. $result[$element->nodeName][$key] = $elementData;
  109. } elseif (!empty($elementData)) {
  110. $result[$element->nodeName][] = $elementData;
  111. }
  112. } elseif ($element->nodeType === XML_TEXT_NODE && trim($element->nodeValue) !== '') {
  113. return ['value' => $element->nodeValue];
  114. }
  115. }
  116. return $result;
  117. }
  118. /**
  119. * Get key for DOM element
  120. *
  121. * @param \DOMElement $element
  122. * @return boolean|string
  123. */
  124. protected function getElementKey(\DOMElement $element)
  125. {
  126. if (isset($this->idAttributes[$element->nodeName])) {
  127. if ($element->hasAttribute($this->idAttributes[$element->nodeName])) {
  128. return $element->getAttribute($this->idAttributes[$element->nodeName]);
  129. }
  130. }
  131. if ($element->hasAttribute(self::NAME_ATTRIBUTE)) {
  132. return $element->getAttribute(self::NAME_ATTRIBUTE);
  133. }
  134. return false;
  135. }
  136. /**
  137. * Verify attribute is main key for element.
  138. *
  139. * @param \DOMElement $element
  140. * @param \DOMAttr $attribute
  141. * @return boolean
  142. */
  143. protected function isKeyAttribute(\DOMElement $element, \DOMAttr $attribute)
  144. {
  145. if (isset($this->idAttributes[$element->nodeName])) {
  146. return $attribute->name === $this->idAttributes[$element->nodeName];
  147. } else {
  148. return $attribute->name === self::NAME_ATTRIBUTE;
  149. }
  150. }
  151. /**
  152. * Get node attributes.
  153. *
  154. * @param \DOMElement $element
  155. * @return array
  156. */
  157. protected function getAttributes(\DOMElement $element)
  158. {
  159. $attributes = [];
  160. if ($element->hasAttributes()) {
  161. /** @var \DomAttr $attribute */
  162. foreach ($element->attributes as $attribute) {
  163. if (trim($attribute->nodeValue) !== '' && !$this->isKeyAttribute($element, $attribute)) {
  164. $attributes[$attribute->nodeName] = $this->castNumeric($attribute->nodeValue);
  165. }
  166. }
  167. }
  168. return $attributes;
  169. }
  170. /**
  171. * Get child nodes data.
  172. *
  173. * @param \DOMElement $element
  174. * @return array
  175. */
  176. protected function getChildNodes(\DOMElement $element)
  177. {
  178. $children = [];
  179. if ($element->hasChildNodes()) {
  180. $children = $this->convertXml($element->childNodes);
  181. }
  182. return $children;
  183. }
  184. /**
  185. * Cast nodeValue to int or double.
  186. *
  187. * @param string $nodeValue
  188. * @return float|integer
  189. */
  190. protected function castNumeric($nodeValue)
  191. {
  192. if (is_numeric($nodeValue)) {
  193. if (preg_match('/^\d+$/', $nodeValue)) {
  194. $nodeValue = (int) $nodeValue;
  195. } else {
  196. $nodeValue = (double) $nodeValue;
  197. }
  198. }
  199. return $nodeValue;
  200. }
  201. }