GetDistance.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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\InventoryDistanceBasedSourceSelection\Model\DistanceProvider\GoogleMap;
  8. use Magento\Framework\App\Config\ScopeConfigInterface;
  9. use Magento\Framework\Exception\LocalizedException;
  10. use Magento\Framework\HTTP\ClientInterface;
  11. use Magento\Framework\Serialize\Serializer\Json;
  12. use Magento\InventoryDistanceBasedSourceSelection\Model\Convert\LatLngToQueryString;
  13. use Magento\InventoryDistanceBasedSourceSelectionApi\Api\Data\LatLngInterface;
  14. use Magento\InventoryDistanceBasedSourceSelectionApi\Api\GetDistanceInterface;
  15. /**
  16. * @inheritdoc
  17. */
  18. class GetDistance implements GetDistanceInterface
  19. {
  20. private const GOOGLE_ENDPOINT = 'https://maps.googleapis.com/maps/api/distancematrix/json';
  21. private const XML_PATH_MODE = 'cataloginventory/source_selection_distance_based_google/mode';
  22. private const XML_PATH_VALUE = 'cataloginventory/source_selection_distance_based_google/value';
  23. private const ZERO_RESULT_RESPONSE = 'ZERO_RESULTS';
  24. /**
  25. * @var array
  26. */
  27. private $distanceCache = [];
  28. /**
  29. * @var ClientInterface
  30. */
  31. private $client;
  32. /**
  33. * @var ScopeConfigInterface
  34. */
  35. private $scopeConfig;
  36. /**
  37. * @var Json
  38. */
  39. private $json;
  40. /**
  41. * @var GetApiKey
  42. */
  43. private $getApiKey;
  44. /**
  45. * @var LatLngToQueryString
  46. */
  47. private $latLngToQueryString;
  48. /**
  49. * GetLatLngFromAddress constructor.
  50. *
  51. * @param ClientInterface $client
  52. * @param ScopeConfigInterface $scopeConfig
  53. * @param Json $json
  54. * @param GetApiKey $getApiKey
  55. * @param LatLngToQueryString $latLngToQueryString
  56. */
  57. public function __construct(
  58. ClientInterface $client,
  59. ScopeConfigInterface $scopeConfig,
  60. Json $json,
  61. GetApiKey $getApiKey,
  62. LatLngToQueryString $latLngToQueryString
  63. ) {
  64. $this->client = $client;
  65. $this->json = $json;
  66. $this->getApiKey = $getApiKey;
  67. $this->scopeConfig = $scopeConfig;
  68. $this->latLngToQueryString = $latLngToQueryString;
  69. }
  70. /**
  71. * @inheritdoc
  72. * @throws LocalizedException
  73. */
  74. public function execute(LatLngInterface $source, LatLngInterface $destination): float
  75. {
  76. $sourceString = $this->latLngToQueryString->execute($source);
  77. $destinationString = $this->latLngToQueryString->execute($destination);
  78. $key = $sourceString . '|' . $destinationString;
  79. if (!isset($this->distanceCache[$key])) {
  80. $queryString = http_build_query([
  81. 'key' => $this->getApiKey->execute(),
  82. 'origins' => $sourceString,
  83. 'destinations' => $destinationString,
  84. 'mode' => $this->scopeConfig->getValue(self::XML_PATH_MODE),
  85. ]);
  86. $this->client->get(self::GOOGLE_ENDPOINT . '?' . $queryString);
  87. if ($this->client->getStatus() !== 200) {
  88. throw new LocalizedException(__('Unable to connect google API for distance matrix'));
  89. }
  90. $res = $this->json->unserialize($this->client->getBody());
  91. if ($res['status'] !== 'OK'
  92. || $res['rows'][0]['elements'][0]['status'] === self::ZERO_RESULT_RESPONSE
  93. ) {
  94. throw new LocalizedException(
  95. __(
  96. 'Unable to get distance between %1 and %2',
  97. $sourceString,
  98. $destinationString
  99. )
  100. );
  101. }
  102. $element = $res['rows'][0]['elements'][0];
  103. if ($this->scopeConfig->getValue(self::XML_PATH_VALUE) === 'time') {
  104. $this->distanceCache[$key] = (float)$element['duration']['value'];
  105. } else {
  106. $this->distanceCache[$key] = (float)$element['distance']['value'];
  107. }
  108. }
  109. return $this->distanceCache[$key];
  110. }
  111. }