ShippingExperienceMapper.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. /**
  3. * Refer to LICENSE.txt distributed with the Temando Shipping module for notice of license
  4. */
  5. namespace Temando\Shipping\Rest\EntityMapper;
  6. use Magento\Backend\Model\Session\Quote as BackendSession;
  7. use Magento\Framework\Exception\LocalizedException;
  8. use Magento\Framework\Exception\NotFoundException;
  9. use Magento\Framework\Locale\ResolverInterface;
  10. use Magento\Framework\Session\SessionManagerInterface;
  11. use Magento\Store\Model\StoreManagerInterface;
  12. use Psr\Log\LoggerInterface;
  13. use Temando\Shipping\Api\Data\Order\ShippingExperienceInterface;
  14. use Temando\Shipping\Api\Data\Order\ShippingExperienceInterfaceFactory;
  15. use Temando\Shipping\Rest\Response\DataObject\OrderQualification;
  16. use Temando\Shipping\Rest\Response\Fields\Generic\MonetaryValue;
  17. use Temando\Shipping\Rest\Response\Fields\OrderQualification\Description;
  18. /**
  19. * Map API data to application data object
  20. *
  21. * @package Temando\Shipping\Rest
  22. * @author Christoph Aßmann <christoph.assmann@netresearch.de>
  23. * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  24. * @link https://www.temando.com/
  25. */
  26. class ShippingExperienceMapper
  27. {
  28. /**
  29. * @var SessionManagerInterface|BackendSession
  30. */
  31. private $session;
  32. /**
  33. * @var StoreManagerInterface
  34. */
  35. private $storeManager;
  36. /**
  37. * @var ResolverInterface
  38. */
  39. private $localeResolver;
  40. /**
  41. * @var ShippingExperienceInterfaceFactory
  42. */
  43. private $shippingExperienceFactory;
  44. /**
  45. * @var LoggerInterface
  46. */
  47. private $logger;
  48. /**
  49. * ShippingExperienceMapper constructor.
  50. * @param SessionManagerInterface $session
  51. * @param StoreManagerInterface $storeManager
  52. * @param ResolverInterface $localeResolver
  53. * @param ShippingExperienceInterfaceFactory $shippingExperienceFactory
  54. * @param LoggerInterface $logger
  55. */
  56. public function __construct(
  57. SessionManagerInterface $session,
  58. StoreManagerInterface $storeManager,
  59. ResolverInterface $localeResolver,
  60. ShippingExperienceInterfaceFactory $shippingExperienceFactory,
  61. LoggerInterface $logger
  62. ) {
  63. $this->session = $session;
  64. $this->storeManager = $storeManager;
  65. $this->localeResolver = $localeResolver;
  66. $this->shippingExperienceFactory = $shippingExperienceFactory;
  67. $this->logger = $logger;
  68. }
  69. /**
  70. * Extract those shipping costs which match the current store's base currency.
  71. *
  72. * - For admin orders, the store scope cannot be accessed through store manager. Use backend session.
  73. * - For store front orders, the store scope must not be accessed through checkout session. Use store manager.
  74. *
  75. * @link https://wp.me/p7M4FY-g6
  76. * @link https://github.com/magento/magento2/pull/18678
  77. *
  78. * @param MonetaryValue[] $cost
  79. *
  80. * @return float
  81. * @throws LocalizedException
  82. */
  83. private function extractShippingCost(array $cost)
  84. {
  85. if ($this->session instanceof BackendSession) {
  86. $currentStore = $this->session->getStore();
  87. } else {
  88. $currentStore = $this->storeManager->getStore();
  89. }
  90. $baseCurrency = $currentStore->getBaseCurrencyCode();
  91. $warningTemplate = "%1 is not a valid shipping method currency. Use %2 when configuring rates.";
  92. $applicableCosts = array_filter($cost, function (MonetaryValue $item) use ($baseCurrency, $warningTemplate) {
  93. if ($item->getCurrency() !== $baseCurrency) {
  94. $message = __($warningTemplate, $item->getCurrency(), $baseCurrency);
  95. $this->logger->warning($message->render());
  96. return false;
  97. }
  98. return true;
  99. });
  100. if (empty($applicableCosts)) {
  101. throw new NotFoundException(__('No applicable shipping cost found.'));
  102. }
  103. // return first available cost
  104. $item = current($applicableCosts);
  105. return $item->getAmount();
  106. }
  107. /**
  108. * @param Description[] $descriptions
  109. * @return string
  110. */
  111. private function getLocalizedDescription(array $descriptions)
  112. {
  113. $descriptionFilter = function ($descriptions, $locale) {
  114. /** @var Description $description */
  115. foreach ($descriptions as $description) {
  116. if ($description->getLocale() === $locale) {
  117. return $description;
  118. }
  119. }
  120. return null;
  121. };
  122. // try locale exact match first
  123. $locale = $this->localeResolver->getLocale();
  124. $fallbacks = [$locale, substr($locale, 0, 2), 'en'];
  125. do {
  126. $lang = array_shift($fallbacks);
  127. $localizedDescription = $descriptionFilter($descriptions, $lang);
  128. } while (!empty($fallbacks) && !$localizedDescription);
  129. return ($localizedDescription ? $localizedDescription->getText() : '');
  130. }
  131. /**
  132. * @param OrderQualification $apiQualification
  133. * @return ShippingExperienceInterface
  134. * @throws LocalizedException
  135. */
  136. public function map(OrderQualification $apiQualification)
  137. {
  138. $cost = $this->extractShippingCost($apiQualification->getAttributes()->getCost());
  139. $description = $this->getLocalizedDescription($apiQualification->getAttributes()->getDescription());
  140. $experienceId = current($apiQualification->getExperienceIds());
  141. $shippingExperience = $this->shippingExperienceFactory->create([
  142. ShippingExperienceInterface::LABEL => $description,
  143. ShippingExperienceInterface::CODE => $experienceId,
  144. ShippingExperienceInterface::COST => $cost,
  145. ]);
  146. return $shippingExperience;
  147. }
  148. }