Skip to content

Commit d617351

Browse files
authored
Merge pull request #4366 from magento-qwerty/MAGETWO-99673
[Qwerty] MAGETWO-99673: Implement deferred
2 parents 8ecf903 + 3900280 commit d617351

File tree

59 files changed

+6335
-1639
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+6335
-1639
lines changed

app/code/Magento/Dhl/Model/Carrier.php

Lines changed: 169 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
namespace Magento\Dhl\Model;
88

99
use Magento\Catalog\Model\Product\Type;
10+
use Magento\Framework\App\ObjectManager;
1011
use Magento\Framework\App\ProductMetadataInterface;
12+
use Magento\Framework\Async\CallbackDeferred;
13+
use Magento\Framework\Async\ProxyDeferredFactory;
14+
use Magento\Framework\HTTP\AsyncClient\HttpResponseDeferredInterface;
15+
use Magento\Framework\HTTP\AsyncClient\Request;
16+
use Magento\Framework\HTTP\AsyncClientInterface;
1117
use Magento\Framework\Module\Dir;
1218
use Magento\Sales\Exception\DocumentValidationException;
1319
use Magento\Sales\Model\Order\Shipment;
@@ -197,6 +203,8 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
197203

198204
/**
199205
* @var \Magento\Framework\HTTP\ZendClientFactory
206+
* @deprecated Use asynchronous client.
207+
* @see $httpClient
200208
*/
201209
protected $_httpClientFactory;
202210

@@ -219,6 +227,16 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
219227
*/
220228
private $productMetadata;
221229

230+
/**
231+
* @var AsyncClientInterface
232+
*/
233+
private $httpClient;
234+
235+
/**
236+
* @var ProxyDeferredFactory
237+
*/
238+
private $proxyDeferredFactory;
239+
222240
/**
223241
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
224242
* @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
@@ -247,6 +265,8 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
247265
* @param array $data
248266
* @param \Magento\Dhl\Model\Validator\XmlValidator|null $xmlValidator
249267
* @param ProductMetadataInterface|null $productMetadata
268+
* @param AsyncClientInterface|null $httpClient
269+
* @param ProxyDeferredFactory|null $proxyDeferredFactory
250270
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
251271
*/
252272
public function __construct(
@@ -276,7 +296,9 @@ public function __construct(
276296
\Magento\Framework\HTTP\ZendClientFactory $httpClientFactory,
277297
array $data = [],
278298
\Magento\Dhl\Model\Validator\XmlValidator $xmlValidator = null,
279-
ProductMetadataInterface $productMetadata = null
299+
ProductMetadataInterface $productMetadata = null,
300+
?AsyncClientInterface $httpClient = null,
301+
?ProxyDeferredFactory $proxyDeferredFactory = null
280302
) {
281303
$this->readFactory = $readFactory;
282304
$this->_carrierHelper = $carrierHelper;
@@ -308,10 +330,11 @@ public function __construct(
308330
if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_DOC) {
309331
$this->_freeMethod = 'free_method_doc';
310332
}
311-
$this->xmlValidator = $xmlValidator
312-
?: \Magento\Framework\App\ObjectManager::getInstance()->get(XmlValidator::class);
313-
$this->productMetadata = $productMetadata
314-
?: \Magento\Framework\App\ObjectManager::getInstance()->get(ProductMetadataInterface::class);
333+
$this->xmlValidator = $xmlValidator ?? ObjectManager::getInstance()->get(XmlValidator::class);
334+
$this->productMetadata = $productMetadata ?? ObjectManager::getInstance()->get(ProductMetadataInterface::class);
335+
$this->httpClient = $httpClient ?? ObjectManager::getInstance()->get(AsyncClientInterface::class);
336+
$this->proxyDeferredFactory = $proxyDeferredFactory
337+
?? ObjectManager::getInstance()->get(ProxyDeferredFactory::class);
315338
}
316339

317340
/**
@@ -348,7 +371,6 @@ public function collectRates(RateRequest $request)
348371

349372
$requestDhl = clone $request;
350373
$this->setStore($requestDhl->getStoreId());
351-
352374
$origCompanyName = $this->_getDefaultValue(
353375
$requestDhl->getOrigCompanyName(),
354376
\Magento\Store\Model\Information::XML_PATH_STORE_INFO_NAME
@@ -357,18 +379,27 @@ public function collectRates(RateRequest $request)
357379
$origState = $this->_getDefaultValue($requestDhl->getOrigState(), Shipment::XML_PATH_STORE_REGION_ID);
358380
$origCity = $this->_getDefaultValue($requestDhl->getOrigCity(), Shipment::XML_PATH_STORE_CITY);
359381
$origPostcode = $this->_getDefaultValue($requestDhl->getOrigPostcode(), Shipment::XML_PATH_STORE_ZIP);
360-
361382
$requestDhl->setOrigCompanyName($origCompanyName)
362383
->setCountryId($origCountryId)
363384
->setOrigState($origState)
364385
->setOrigCity($origCity)
365386
->setOrigPostal($origPostcode);
366387
$this->setRequest($requestDhl);
367-
368-
$this->_result = $this->_getQuotes();
369-
$this->_updateFreeMethodQuote($request);
370-
371-
return $this->_result;
388+
//Loading quotes
389+
//Saving $result to use proper result with the callback
390+
$this->_result = $result = $this->_getQuotes();
391+
//After quotes are loaded parsing the response.
392+
return $this->proxyDeferredFactory->createFor(
393+
Result::class,
394+
new CallbackDeferred(
395+
function () use ($request, $result) {
396+
$this->_result = $result;
397+
$this->_updateFreeMethodQuote($request);
398+
399+
return $this->_result;
400+
}
401+
)
402+
);
372403
}
373404

374405
/**
@@ -715,6 +746,7 @@ protected function _getWeight($weight, $maxWeight = false, $configWeightUnit = f
715746
* @return array
716747
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
717748
* @SuppressWarnings(PHPMD.NPathComplexity)
749+
* phpcs:disable Generic.Metrics.NestingLevel
718750
*/
719751
protected function _getAllItems()
720752
{
@@ -799,6 +831,7 @@ protected function _getAllItems()
799831

800832
return $fullItems;
801833
}
834+
//phpcs:enable
802835

803836
/**
804837
* Make pieces
@@ -931,56 +964,126 @@ protected function _addDimension($nodePiece)
931964
}
932965

933966
/**
934-
* Get shipping quotes
967+
* Process response received from DHL's API for quotes.
935968
*
936-
* @return \Magento\Framework\Model\AbstractModel|Result
969+
* @param array $responsesData
970+
* @return Error|Result
937971
*/
938-
protected function _getQuotes()
972+
private function processQuotesResponses(array $responsesData)
939973
{
940-
$responseBody = '';
941-
try {
942-
for ($offset = 0; $offset <= self::UNAVAILABLE_DATE_LOOK_FORWARD; $offset++) {
943-
$debugPoint = [];
944-
945-
$requestXml = $this->_buildQuotesRequestXml();
946-
$date = date(self::REQUEST_DATE_FORMAT, strtotime($this->_getShipDate() . " +{$offset} days"));
947-
$this->_setQuotesRequestXmlDate($requestXml, $date);
948-
949-
$request = $requestXml->asXML();
950-
$debugPoint['request'] = $this->filterDebugData($request);
951-
$responseBody = $this->_getCachedQuotes($request);
952-
$debugPoint['from_cache'] = $responseBody === null;
953-
954-
if ($debugPoint['from_cache']) {
955-
$responseBody = $this->_getQuotesFromServer($request);
956-
}
957-
958-
$debugPoint['response'] = $this->filterDebugData($responseBody);
959-
960-
$bodyXml = $this->_xmlElFactory->create(['data' => $responseBody]);
974+
usort(
975+
$responsesData,
976+
function (array $a, array $b): int {
977+
return $a['date'] <=> $b['date'];
978+
}
979+
);
980+
/** @var string $lastResponse */
981+
$lastResponse = '';
982+
//Processing different dates
983+
foreach ($responsesData as $responseData) {
984+
$debugPoint = [];
985+
$debugPoint['request'] = $this->filterDebugData($responseData['request']);
986+
$debugPoint['response'] = $this->filterDebugData($responseData['body']);
987+
$debugPoint['from_cache'] = $responseData['from_cache'];
988+
$unavailable = false;
989+
try {
990+
//Getting availability
991+
$bodyXml = $this->_xmlElFactory->create(['data' => $responseData['body']]);
961992
$code = $bodyXml->xpath('//GetQuoteResponse/Note/Condition/ConditionCode');
962993
if (isset($code[0]) && (int)$code[0] == self::CONDITION_CODE_SERVICE_DATE_UNAVAILABLE) {
963-
$debugPoint['info'] = sprintf(__("DHL service is not available at %s date"), $date);
964-
} else {
965-
$this->_debug($debugPoint);
966-
break;
994+
$debugPoint['info'] = sprintf(
995+
__("DHL service is not available at %s date"),
996+
$responseData['date']
997+
);
998+
$unavailable = true;
967999
}
968-
969-
$this->_setCachedQuotes($request, $responseBody);
1000+
} catch (\Throwable $exception) {
1001+
//Failed to read response
1002+
$unavailable = true;
1003+
$this->_errors[$exception->getCode()] = $exception->getMessage();
1004+
}
1005+
if ($unavailable) {
1006+
//Cannot get rates.
9701007
$this->_debug($debugPoint);
1008+
break;
9711009
}
972-
} catch (\Exception $e) {
973-
$this->_errors[$e->getCode()] = $e->getMessage();
1010+
//Caching rates
1011+
$this->_setCachedQuotes($responseData['request'], $responseData['body']);
1012+
$this->_debug($debugPoint);
1013+
//Will only process rates available for the latest date possible.
1014+
$lastResponse = $responseData['body'];
9741015
}
9751016

976-
return $this->_parseResponse($responseBody);
1017+
return $this->_parseResponse($lastResponse);
1018+
}
1019+
1020+
/**
1021+
* Get shipping quotes
1022+
*
1023+
* @return \Magento\Framework\Model\AbstractModel|Result
1024+
*/
1025+
protected function _getQuotes()
1026+
{
1027+
$responseBodies = [];
1028+
/** @var HttpResponseDeferredInterface[][] $deferredResponses */
1029+
$deferredResponses = [];
1030+
$requestXml = $this->_buildQuotesRequestXml();
1031+
for ($offset = 0; $offset <= self::UNAVAILABLE_DATE_LOOK_FORWARD; $offset++) {
1032+
$date = date(self::REQUEST_DATE_FORMAT, strtotime($this->_getShipDate() . " +{$offset} days"));
1033+
$this->_setQuotesRequestXmlDate($requestXml, $date);
1034+
$request = $requestXml->asXML();
1035+
$responseBody = $this->_getCachedQuotes($request);
1036+
1037+
if ($responseBody === null) {
1038+
$deferredResponses[] = [
1039+
'deferred' => $this->httpClient->request(
1040+
new Request(
1041+
(string)$this->getConfigData('gateway_url'),
1042+
Request::METHOD_POST,
1043+
['Content-Type' => 'application/xml'],
1044+
utf8_encode($request)
1045+
)
1046+
),
1047+
'date' => $date,
1048+
'request' => $request
1049+
];
1050+
} else {
1051+
$responseBodies[] = [
1052+
'body' => $responseBody,
1053+
'date' => $date,
1054+
'request' => $request,
1055+
'from_cache' => true
1056+
];
1057+
}
1058+
}
1059+
1060+
return $this->proxyDeferredFactory->createFor(
1061+
Result::class,
1062+
new CallbackDeferred(
1063+
function () use ($deferredResponses, $responseBodies) {
1064+
//Loading rates not found in cache
1065+
foreach ($deferredResponses as $deferredResponseData) {
1066+
$responseBodies[] = [
1067+
'body' => $deferredResponseData['deferred']->get()->getBody(),
1068+
'date' => $deferredResponseData['date'],
1069+
'request' => $deferredResponseData['request'],
1070+
'from_cache' => false
1071+
];
1072+
}
1073+
1074+
return $this->processQuotesResponses($responseBodies);
1075+
}
1076+
)
1077+
);
9771078
}
9781079

9791080
/**
9801081
* Get shipping quotes from DHL service
9811082
*
9821083
* @param string $request
9831084
* @return string
1085+
* @deprecated Use asynchronous client.
1086+
* @see _getQuotes()
9841087
*/
9851088
protected function _getQuotesFromServer($request)
9861089
{
@@ -1568,21 +1671,23 @@ protected function _doRequest()
15681671
$xml->addChild('LabelImageFormat', 'PDF', '');
15691672

15701673
$request = $xml->asXML();
1571-
if (!$request && !(mb_detect_encoding($request) == 'UTF-8')) {
1674+
if ($request && !(mb_detect_encoding($request) == 'UTF-8')) {
15721675
$request = utf8_encode($request);
15731676
}
15741677

15751678
$responseBody = $this->_getCachedQuotes($request);
15761679
if ($responseBody === null) {
15771680
$debugData = ['request' => $this->filterDebugData($request)];
15781681
try {
1579-
/** @var \Magento\Framework\HTTP\ZendClient $client */
1580-
$client = $this->_httpClientFactory->create();
1581-
$client->setUri((string)$this->getConfigData('gateway_url'));
1582-
$client->setConfig(['maxredirects' => 0, 'timeout' => 30]);
1583-
$client->setRawData($request);
1584-
$responseBody = $client->request(\Magento\Framework\HTTP\ZendClient::POST)->getBody();
1585-
$responseBody = utf8_decode($responseBody);
1682+
$response = $this->httpClient->request(
1683+
new Request(
1684+
(string)$this->getConfigData('gateway_url'),
1685+
Request::METHOD_POST,
1686+
['Content-Type' => 'application/xml'],
1687+
$request
1688+
)
1689+
);
1690+
$responseBody = utf8_decode($response->get()->getBody());
15861691
$debugData['result'] = $this->filterDebugData($responseBody);
15871692
$this->_setCachedQuotes($request, $responseBody);
15881693
} catch (\Exception $e) {
@@ -1743,12 +1848,15 @@ protected function _getXMLTracking($trackings)
17431848
if ($responseBody === null) {
17441849
$debugData = ['request' => $this->filterDebugData($request)];
17451850
try {
1746-
/** @var \Magento\Framework\HTTP\ZendClient $client */
1747-
$client = $this->_httpClientFactory->create();
1748-
$client->setUri((string)$this->getConfigData('gateway_url'));
1749-
$client->setConfig(['maxredirects' => 0, 'timeout' => 30]);
1750-
$client->setRawData($request);
1751-
$responseBody = $client->request(\Magento\Framework\HTTP\ZendClient::POST)->getBody();
1851+
$response = $this->httpClient->request(
1852+
new Request(
1853+
(string)$this->getConfigData('gateway_url'),
1854+
Request::METHOD_POST,
1855+
['Content-Type' => 'application/xml'],
1856+
$request
1857+
)
1858+
);
1859+
$responseBody = $response->get()->getBody();
17521860
$debugData['result'] = $this->filterDebugData($responseBody);
17531861
$this->_setCachedQuotes($request, $responseBody);
17541862
} catch (\Exception $e) {
@@ -1850,6 +1958,7 @@ protected function _parseXmlTrackingResponse($trackings, $response)
18501958
$result->append($error);
18511959
}
18521960
}
1961+
$this->_errors = [];
18531962

18541963
$this->_result = $result;
18551964
}
@@ -1944,6 +2053,7 @@ protected function _prepareShippingLabelContent(\SimpleXMLElement $xml)
19442053
}
19452054
$result->setTrackingNumber((string)$xml->AirwayBillNumber);
19462055
$labelContent = (string)$xml->LabelImage->OutputImage;
2056+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
19472057
$result->setShippingLabelContent(base64_decode($labelContent));
19482058
} catch (\Exception $e) {
19492059
throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()));

0 commit comments

Comments
 (0)