Config.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\WebapiAsync\Model;
  8. use Magento\Webapi\Model\Cache\Type\Webapi as WebapiCache;
  9. use Magento\Webapi\Model\Config as WebapiConfig;
  10. use Magento\Framework\App\ObjectManager;
  11. use Magento\Framework\Serialize\SerializerInterface;
  12. use Magento\Framework\Exception\LocalizedException;
  13. use Magento\Webapi\Model\Config\Converter;
  14. /**
  15. * Class for accessing to Webapi_Async configuration.
  16. */
  17. class Config implements \Magento\AsynchronousOperations\Model\ConfigInterface
  18. {
  19. /**
  20. * @var \Magento\Webapi\Model\Cache\Type\Webapi
  21. */
  22. private $cache;
  23. /**
  24. * @var \Magento\Webapi\Model\Config
  25. */
  26. private $webApiConfig;
  27. /**
  28. * @var \Magento\Framework\Serialize\SerializerInterface
  29. */
  30. private $serializer;
  31. /**
  32. * @var array
  33. */
  34. private $asyncServices;
  35. /**
  36. * Initialize dependencies.
  37. *
  38. * @param \Magento\Webapi\Model\Cache\Type\Webapi $cache
  39. * @param \Magento\Webapi\Model\Config $webApiConfig
  40. * @param \Magento\Framework\Serialize\SerializerInterface|null $serializer
  41. */
  42. public function __construct(
  43. WebapiCache $cache,
  44. WebapiConfig $webApiConfig,
  45. SerializerInterface $serializer = null
  46. ) {
  47. $this->cache = $cache;
  48. $this->webApiConfig = $webApiConfig;
  49. $this->serializer = $serializer ? : ObjectManager::getInstance()->get(SerializerInterface::class);
  50. }
  51. /**
  52. * @inheritdoc
  53. */
  54. public function getServices()
  55. {
  56. if (null === $this->asyncServices) {
  57. $services = $this->cache->load(self::CACHE_ID);
  58. if ($services && is_string($services)) {
  59. $this->asyncServices = $this->serializer->unserialize($services);
  60. } else {
  61. $this->asyncServices = $this->generateTopicsDataFromWebapiConfig();
  62. $this->cache->save($this->serializer->serialize($this->asyncServices), self::CACHE_ID);
  63. }
  64. }
  65. return $this->asyncServices;
  66. }
  67. /**
  68. * @inheritdoc
  69. */
  70. public function getTopicName($routeUrl, $httpMethod)
  71. {
  72. $services = $this->getServices();
  73. $lookupKey = $this->generateLookupKeyByRouteData(
  74. $routeUrl,
  75. $httpMethod
  76. );
  77. if (array_key_exists($lookupKey, $services) === false) {
  78. throw new LocalizedException(
  79. __('WebapiAsync config for "%lookupKey" does not exist.', ['lookupKey' => $lookupKey])
  80. );
  81. }
  82. return $services[$lookupKey][self::SERVICE_PARAM_KEY_TOPIC];
  83. }
  84. /**
  85. * Generate topic data for all defined services
  86. *
  87. * Topic data is indexed by a lookup key that is derived from route data
  88. *
  89. * @return array
  90. */
  91. private function generateTopicsDataFromWebapiConfig()
  92. {
  93. $webApiConfig = $this->webApiConfig->getServices();
  94. $services = [];
  95. foreach ($webApiConfig[Converter::KEY_ROUTES] as $routeUrl => $routeData) {
  96. foreach ($routeData as $httpMethod => $httpMethodData) {
  97. if ($httpMethod !== \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET) {
  98. $serviceInterface = $httpMethodData[Converter::KEY_SERVICE][Converter::KEY_SERVICE_CLASS];
  99. $serviceMethod = $httpMethodData[Converter::KEY_SERVICE][Converter::KEY_SERVICE_METHOD];
  100. $lookupKey = $this->generateLookupKeyByRouteData(
  101. $routeUrl,
  102. $httpMethod
  103. );
  104. $topicName = $this->generateTopicNameFromService(
  105. $serviceInterface,
  106. $serviceMethod,
  107. $httpMethod
  108. );
  109. $services[$lookupKey] = [
  110. self::SERVICE_PARAM_KEY_INTERFACE => $serviceInterface,
  111. self::SERVICE_PARAM_KEY_METHOD => $serviceMethod,
  112. self::SERVICE_PARAM_KEY_TOPIC => $topicName,
  113. ];
  114. }
  115. }
  116. }
  117. return $services;
  118. }
  119. /**
  120. * Generate lookup key name based on route and method
  121. *
  122. * Perform the following conversion:
  123. * self::TOPIC_PREFIX + /V1/products + POST => async.V1.products.POST
  124. *
  125. * @param string $routeUrl
  126. * @param string $httpMethod
  127. * @return string
  128. */
  129. private function generateLookupKeyByRouteData($routeUrl, $httpMethod)
  130. {
  131. return self::TOPIC_PREFIX . $this->generateKey($routeUrl, $httpMethod, '/', false);
  132. }
  133. /**
  134. * Generate topic name based on service type and method name.
  135. *
  136. * Perform the following conversion:
  137. * self::TOPIC_PREFIX + Magento\Catalog\Api\ProductRepositoryInterface + save + POST
  138. * => async.magento.catalog.api.productrepositoryinterface.save.POST
  139. *
  140. * @param string $serviceInterface
  141. * @param string $serviceMethod
  142. * @param string $httpMethod
  143. * @return string
  144. */
  145. private function generateTopicNameFromService($serviceInterface, $serviceMethod, $httpMethod)
  146. {
  147. $typeName = strtolower(sprintf('%s.%s', $serviceInterface, $serviceMethod));
  148. return strtolower(self::TOPIC_PREFIX . $this->generateKey($typeName, $httpMethod, '\\', false));
  149. }
  150. /**
  151. * Join and simplify input type and method into a string that can be used as an array key
  152. *
  153. * @param string $typeName
  154. * @param string $methodName
  155. * @param string $delimiter
  156. * @param bool $lcfirst
  157. * @return string
  158. */
  159. private function generateKey($typeName, $methodName, $delimiter = '\\', $lcfirst = true)
  160. {
  161. $parts = explode($delimiter, ltrim($typeName, $delimiter));
  162. foreach ($parts as &$part) {
  163. $part = ltrim($part, ':');
  164. if ($lcfirst === true) {
  165. $part = lcfirst($part);
  166. }
  167. }
  168. return implode('.', $parts) . '.' . $methodName;
  169. }
  170. }