Converter.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Webapi\Model\Config;
  7. /**
  8. * Converter of webapi.xml content into array format.
  9. */
  10. class Converter implements \Magento\Framework\Config\ConverterInterface
  11. {
  12. /**#@+
  13. * Array keys for config internal representation.
  14. */
  15. const KEY_SERVICE_CLASS = 'class';
  16. const KEY_URL = 'url';
  17. const KEY_SERVICE_METHOD = 'method';
  18. const KEY_SECURE = 'secure';
  19. const KEY_ROUTES = 'routes';
  20. const KEY_ACL_RESOURCES = 'resources';
  21. const KEY_SERVICE = 'service';
  22. const KEY_SERVICES = 'services';
  23. const KEY_FORCE = 'force';
  24. const KEY_VALUE = 'value';
  25. const KEY_DATA_PARAMETERS = 'parameters';
  26. const KEY_SOURCE = 'source';
  27. const KEY_METHOD = 'method';
  28. const KEY_METHODS = 'methods';
  29. const KEY_DESCRIPTION = 'description';
  30. /**#@-*/
  31. /**
  32. * {@inheritdoc}
  33. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  34. * @SuppressWarnings(PHPMD.NPathComplexity)
  35. */
  36. public function convert($source)
  37. {
  38. $result = [];
  39. /** @var \DOMNodeList $routes */
  40. $routes = $source->getElementsByTagName('route');
  41. /** @var \DOMElement $route */
  42. foreach ($routes as $route) {
  43. if ($route->nodeType != XML_ELEMENT_NODE) {
  44. continue;
  45. }
  46. /** @var \DOMElement $service */
  47. $service = $route->getElementsByTagName('service')->item(0);
  48. $serviceClass = $service->attributes->getNamedItem('class')->nodeValue;
  49. $serviceMethod = $service->attributes->getNamedItem('method')->nodeValue;
  50. $url = trim($route->attributes->getNamedItem('url')->nodeValue);
  51. $version = $this->convertVersion($url);
  52. $serviceClassData = [];
  53. if (isset($result[self::KEY_SERVICES][$serviceClass][$version])) {
  54. $serviceClassData = $result[self::KEY_SERVICES][$serviceClass][$version];
  55. }
  56. $resources = $route->getElementsByTagName('resource');
  57. $resourceReferences = [];
  58. $resourcePermissionSet = [];
  59. /** @var \DOMElement $resource */
  60. foreach ($resources as $resource) {
  61. if ($resource->nodeType != XML_ELEMENT_NODE) {
  62. continue;
  63. }
  64. $ref = $resource->attributes->getNamedItem('ref')->nodeValue;
  65. $resourceReferences[$ref] = true;
  66. // For SOAP
  67. $resourcePermissionSet[] = $ref;
  68. }
  69. if (!isset($serviceClassData[self::KEY_METHODS][$serviceMethod])) {
  70. $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_ACL_RESOURCES] = $resourcePermissionSet;
  71. } else {
  72. $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_ACL_RESOURCES] =
  73. array_unique(
  74. array_merge(
  75. $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_ACL_RESOURCES],
  76. $resourcePermissionSet
  77. )
  78. );
  79. }
  80. $method = $route->attributes->getNamedItem('method')->nodeValue;
  81. $secureNode = $route->attributes->getNamedItem('secure');
  82. $secure = $secureNode ? (bool)trim($secureNode->nodeValue) : false;
  83. $data = $this->convertMethodParameters($route->getElementsByTagName('parameter'));
  84. // We could handle merging here by checking if the route already exists
  85. $result[self::KEY_ROUTES][$url][$method] = [
  86. self::KEY_SECURE => $secure,
  87. self::KEY_SERVICE => [
  88. self::KEY_SERVICE_CLASS => $serviceClass,
  89. self::KEY_SERVICE_METHOD => $serviceMethod,
  90. ],
  91. self::KEY_ACL_RESOURCES => $resourceReferences,
  92. self::KEY_DATA_PARAMETERS => $data,
  93. ];
  94. $serviceSecure = false;
  95. if (isset($serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_SECURE])) {
  96. $serviceSecure = $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_SECURE];
  97. }
  98. $serviceClassData[self::KEY_METHODS][$serviceMethod][self::KEY_SECURE] = $serviceSecure || $secure;
  99. $result[self::KEY_SERVICES][$serviceClass][$version] = $serviceClassData;
  100. }
  101. return $result;
  102. }
  103. /**
  104. * Parses the method parameters into a string array.
  105. *
  106. * @param \DOMNodeList $parameters
  107. * @return array
  108. * @SuppressWarnings(PHPMD.NPathComplexity)
  109. */
  110. protected function convertMethodParameters($parameters)
  111. {
  112. $data = [];
  113. /** @var \DOMElement $parameter */
  114. foreach ($parameters as $parameter) {
  115. if ($parameter->nodeType != XML_ELEMENT_NODE) {
  116. continue;
  117. }
  118. $name = $parameter->attributes->getNamedItem('name')->nodeValue;
  119. $forceNode = $parameter->attributes->getNamedItem('force');
  120. $force = $forceNode ? (bool)$forceNode->nodeValue : false;
  121. $value = $parameter->nodeValue;
  122. $data[$name] = [
  123. self::KEY_FORCE => $force,
  124. self::KEY_VALUE => ($value === 'null') ? null : $value,
  125. ];
  126. $sourceNode = $parameter->attributes->getNamedItem('source');
  127. if ($sourceNode) {
  128. $data[$name][self::KEY_SOURCE] = $sourceNode->nodeValue;
  129. }
  130. $methodNode = $parameter->attributes->getNamedItem('method');
  131. if ($methodNode) {
  132. $data[$name][self::KEY_METHOD] = $methodNode->nodeValue;
  133. }
  134. }
  135. return $data;
  136. }
  137. /**
  138. * Derive the version from the provided URL.
  139. * Assumes the version is the first portion of the URL. For example, '/V1/customers'
  140. *
  141. * @param string $url
  142. * @return string
  143. */
  144. protected function convertVersion($url)
  145. {
  146. return substr($url, 1, strpos($url, '/', 1)-1);
  147. }
  148. }