Skip to content

Commit 5d35a7b

Browse files
committed
Merge pull request #670 from magento-folks/totals-collector
[Folks] Collect totals logic optimization
2 parents c3ae167 + 02bbbc0 commit 5d35a7b

File tree

99 files changed

+3398
-2068
lines changed

Some content is hidden

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

99 files changed

+3398
-2068
lines changed

app/code/Magento/Checkout/Block/Cart/AbstractCart.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,11 @@ public function getTotals()
149149
public function getTotalsCache()
150150
{
151151
if (empty($this->_totals)) {
152-
$this->_totals = $this->getQuote()->getTotals();
152+
if ($this->getQuote()->isVirtual()) {
153+
$this->_totals = $this->getQuote()->getBillingAddress()->getTotals();
154+
} else {
155+
$this->_totals = $this->getQuote()->getShippingAddress()->getTotals();
156+
}
153157
}
154158
return $this->_totals;
155159
}

app/code/Magento/Checkout/Model/DefaultConfigProvider.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,11 @@ private function getTotalsData()
562562
$totalSegmentsData = [];
563563
/** @var \Magento\Quote\Model\Cart\TotalSegment $totalSegment */
564564
foreach ($totals->getTotalSegments() as $totalSegment) {
565-
$totalSegmentsData[] = $totalSegment->toArray();
565+
$totalSegmentArray = $totalSegment->toArray();
566+
if (is_object($totalSegment->getExtensionAttributes())) {
567+
$totalSegmentArray['extension_attributes'] = $totalSegment->getExtensionAttributes()->__toArray();
568+
}
569+
$totalSegmentsData[] = $totalSegmentArray;
566570
}
567571
$totals->setItems($items);
568572
$totals->setTotalSegments($totalSegmentsData);

app/code/Magento/Checkout/Model/ShippingInformationManagement.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInf
6262
*/
6363
protected $scopeConfig;
6464

65+
/**
66+
* @var \Magento\Quote\Model\Quote\TotalsCollector
67+
*/
68+
protected $totalsCollector;
69+
6570
/**
6671
* @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement
6772
* @param \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory
@@ -71,6 +76,7 @@ class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInf
7176
* @param Logger $logger
7277
* @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository
7378
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
79+
* @param \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector
7480
* @codeCoverageIgnore
7581
*/
7682
public function __construct(
@@ -81,7 +87,8 @@ public function __construct(
8187
QuoteAddressValidator $addressValidator,
8288
Logger $logger,
8389
\Magento\Customer\Api\AddressRepositoryInterface $addressRepository,
84-
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
90+
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
91+
\Magento\Quote\Model\Quote\TotalsCollector $totalsCollector
8592
) {
8693
$this->paymentMethodManagement = $paymentMethodManagement;
8794
$this->paymentDetailsFactory = $paymentDetailsFactory;
@@ -91,6 +98,7 @@ public function __construct(
9198
$this->logger = $logger;
9299
$this->addressRepository = $addressRepository;
93100
$this->scopeConfig = $scopeConfig;
101+
$this->totalsCollector = $totalsCollector;
94102
}
95103

96104
/**
@@ -132,9 +140,7 @@ public function saveAddressInformation(
132140
$address->setShippingMethod($carrierCode . '_' . $methodCode);
133141

134142
try {
135-
/** TODO: refactor this code. Eliminate save operation */
136-
$address->save();
137-
$address->collectTotals();
143+
$this->totalsCollector->collectAddressTotals($quote, $address);
138144
} catch (\Exception $e) {
139145
$this->logger->critical($e);
140146
throw new InputException(__('Unable to save address. Please, check input data.'));

app/code/Magento/Checkout/Model/Type/Onepage.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ class Onepage
165165
*/
166166
protected $dataObjectHelper;
167167

168+
/**
169+
* @var \Magento\Quote\Model\Quote\TotalsCollector
170+
*/
171+
protected $totalsCollector;
172+
168173
/**
169174
* @param \Magento\Framework\Event\ManagerInterface $eventManager
170175
* @param \Magento\Checkout\Helper\Data $helper
@@ -192,6 +197,7 @@ class Onepage
192197
* @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
193198
* @param \Magento\Quote\Model\QuoteManagement $quoteManagement
194199
* @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
200+
* @param \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector
195201
* @codeCoverageIgnore
196202
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
197203
*/
@@ -221,7 +227,8 @@ public function __construct(
221227
\Magento\Quote\Model\QuoteRepository $quoteRepository,
222228
\Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
223229
\Magento\Quote\Model\QuoteManagement $quoteManagement,
224-
\Magento\Framework\Api\DataObjectHelper $dataObjectHelper
230+
\Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
231+
\Magento\Quote\Model\Quote\TotalsCollector $totalsCollector
225232
) {
226233
$this->_eventManager = $eventManager;
227234
$this->_customerUrl = $customerUrl;
@@ -249,6 +256,7 @@ public function __construct(
249256
$this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
250257
$this->quoteManagement = $quoteManagement;
251258
$this->dataObjectHelper = $dataObjectHelper;
259+
$this->totalsCollector = $totalsCollector;
252260
}
253261

254262
/**
@@ -490,8 +498,8 @@ public function saveBilling($data, $customerAddressId)
490498
->setSameAsBilling(1)
491499
->setSaveInAddressBook(0)
492500
->setShippingMethod($shippingMethod)
493-
->setCollectShippingRates(true)
494-
->collectTotals();
501+
->setCollectShippingRates(true);
502+
$this->totalsCollector->collectAddressTotals($this->getQuote(), $shipping);
495503

496504
if (!$this->isCheckoutMethodRegister()) {
497505
$shipping->save();
@@ -690,7 +698,8 @@ public function saveShipping($data, $customerAddressId)
690698
return ['error' => 1, 'message' => $validateRes];
691699
}
692700

693-
$address->collectTotals()->save();
701+
$this->totalsCollector->collectAddressTotals($this->getQuote(), $address);
702+
$address->save();
694703

695704
$this->getCheckout()->setStepData('shipping', 'complete', true)->setStepData('shipping_method', 'allow', true);
696705

app/code/Magento/Checkout/Test/Unit/Block/Cart/AbstractCartTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,38 @@ public function testGetItemRendererThrowsExceptionForNonexistentRenderer()
109109

110110
$block->getItemRenderer('some-type');
111111
}
112+
113+
/**
114+
* @param array $expectedResult
115+
* @param bool $isVirtual
116+
* @dataProvider getTotalsCacheDataProvider
117+
*/
118+
public function testGetTotalsCache($expectedResult, $isVirtual)
119+
{
120+
$totals = $isVirtual ? ['billing_totals'] : ['shipping_totals'];
121+
$addressMock = $this->getMock('Magento\Quote\Model\Quote\Address', [], [], '', false);
122+
$checkoutSessionMock = $this->getMock('Magento\Checkout\Model\Session', [], [], '', false);
123+
$quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
124+
$checkoutSessionMock->expects($this->once())->method('getQuote')->willReturn($quoteMock);
125+
126+
$quoteMock->expects($this->once())->method('isVirtual')->willReturn($isVirtual);
127+
$quoteMock->expects($this->any())->method('getShippingAddress')->willReturn($addressMock);
128+
$quoteMock->expects($this->any())->method('getBillingAddress')->willReturn($addressMock);
129+
$addressMock->expects($this->once())->method('getTotals')->willReturn($totals);
130+
131+
/** @var \Magento\Checkout\Block\Cart\AbstractCart $model */
132+
$model = $this->_objectManager->getObject(
133+
'Magento\Checkout\Block\Cart\AbstractCart',
134+
['checkoutSession' => $checkoutSessionMock]
135+
);
136+
$this->assertEquals($expectedResult, $model->getTotalsCache());
137+
}
138+
139+
public function getTotalsCacheDataProvider()
140+
{
141+
return [
142+
[['billing_totals'], true],
143+
[['shipping_totals'], false]
144+
];
145+
}
112146
}

app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase
5757
*/
5858
protected $quoteMock;
5959

60+
/**
61+
* @var \PHPUnit_Framework_MockObject_MockObject
62+
*/
63+
protected $totalsCollectorMock;
64+
6065
/**
6166
* @var \Magento\Checkout\Model\ShippingInformationManagement
6267
*/
@@ -80,7 +85,8 @@ protected function setUp()
8085
$this->loggerMock = $this->getMock('\Psr\Log\LoggerInterface');
8186
$this->addressRepositoryMock = $this->getMock('\Magento\Customer\Api\AddressRepositoryInterface');
8287
$this->scopeConfigMock = $this->getMock('\Magento\Framework\App\Config\ScopeConfigInterface');
83-
88+
$this->totalsCollectorMock =
89+
$this->getMock('Magento\Quote\Model\Quote\TotalsCollector', [], [], '', false);
8490
$this->model = $objectManager->getObject(
8591
'\Magento\Checkout\Model\ShippingInformationManagement',
8692
[
@@ -91,7 +97,8 @@ protected function setUp()
9197
'addressValidator' => $this->addressValidatorMock,
9298
'logger' => $this->loggerMock,
9399
'addressRepository' => $this->addressRepositoryMock,
94-
'scopeConfig' => $this->scopeConfigMock
100+
'scopeConfig' => $this->scopeConfigMock,
101+
'totalsCollector' => $this->totalsCollectorMock
95102
]
96103
);
97104

@@ -109,7 +116,6 @@ protected function setUp()
109116
'getCountryId',
110117
'importCustomerAddressData',
111118
'save',
112-
'collectTotals',
113119
'getShippingRateByCode',
114120
'getShippingMethod'
115121
],
@@ -294,8 +300,10 @@ public function testSaveAddressInformationThrowExceptionWhileAddressSaving()
294300
->with(true)
295301
->willReturnSelf();
296302
$this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(1);
297-
$this->shippingAddressMock->expects($this->once())->method('save')->willThrowException($exception);
298-
303+
$this->totalsCollectorMock
304+
->expects($this->once())
305+
->method('collectAddressTotals')
306+
->willThrowException($exception);
299307
$this->addressValidatorMock->expects($this->once())
300308
->method('validate')
301309
->with($this->shippingAddressMock)
@@ -386,8 +394,10 @@ public function testSaveAddressInformationIfCarrierCodeIsInvalid()
386394
->with(true)
387395
->willReturnSelf();
388396
$this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(1);
389-
$this->shippingAddressMock->expects($this->once())->method('save')->willReturnSelf();
390-
$this->shippingAddressMock->expects($this->once())->method('collectTotals')->willReturnSelf();
397+
$this->totalsCollectorMock
398+
->expects($this->once())
399+
->method('collectAddressTotals')
400+
->with($this->quoteMock, $this->shippingAddressMock);
391401
$this->shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod);
392402
$this->shippingAddressMock->expects($this->once())
393403
->method('getShippingRateByCode')
@@ -464,8 +474,10 @@ public function testSaveAddressInformationIfMinimumAmountIsNotValid()
464474
->with(true)
465475
->willReturnSelf();
466476
$this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(1);
467-
$this->shippingAddressMock->expects($this->once())->method('save')->willReturnSelf();
468-
$this->shippingAddressMock->expects($this->once())->method('collectTotals')->willReturnSelf();
477+
$this->totalsCollectorMock
478+
->expects($this->once())
479+
->method('collectAddressTotals')
480+
->with($this->quoteMock, $this->shippingAddressMock);
469481
$this->shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod);
470482
$this->shippingAddressMock->expects($this->once())
471483
->method('getShippingRateByCode')
@@ -506,7 +518,6 @@ public function testSaveAddressInformationIfCanNotSaveQuote()
506518
->method('save')
507519
->with($this->quoteMock)
508520
->willThrowException($exception);
509-
510521
$addressInformationMock = $this->getMock('\Magento\Checkout\Api\Data\ShippingInformationInterface');
511522
$addressInformationMock->expects($this->once())
512523
->method('getShippingAddress')
@@ -550,8 +561,11 @@ public function testSaveAddressInformationIfCanNotSaveQuote()
550561
->with(true)
551562
->willReturnSelf();
552563
$this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(1);
553-
$this->shippingAddressMock->expects($this->exactly(2))->method('save')->willReturnSelf();
554-
$this->shippingAddressMock->expects($this->once())->method('collectTotals')->willReturnSelf();
564+
$this->shippingAddressMock->expects($this->once())->method('save')->willReturnSelf();
565+
$this->totalsCollectorMock
566+
->expects($this->once())
567+
->method('collectAddressTotals')
568+
->with($this->quoteMock, $this->shippingAddressMock);
555569
$this->shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod);
556570
$this->shippingAddressMock->expects($this->once())
557571
->method('getShippingRateByCode')
@@ -626,8 +640,10 @@ public function testSaveAddressInformation()
626640
->with(true)
627641
->willReturnSelf();
628642
$this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(1);
629-
$this->shippingAddressMock->expects($this->exactly(2))->method('save')->willReturnSelf();
630-
$this->shippingAddressMock->expects($this->once())->method('collectTotals')->willReturnSelf();
643+
$this->totalsCollectorMock
644+
->expects($this->once())
645+
->method('collectAddressTotals')
646+
->with($this->quoteMock, $this->shippingAddressMock);
631647
$this->shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod);
632648
$this->shippingAddressMock->expects($this->once())
633649
->method('getShippingRateByCode')

app/code/Magento/Checkout/Test/Unit/Model/Type/OnepageTest.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ class OnepageTest extends \PHPUnit_Framework_TestCase
9898
/** @var \Magento\Framework\Api\ExtensibleDataObjectConverter|\PHPUnit_Framework_MockObject_MockObject */
9999
protected $extensibleDataObjectConverterMock;
100100

101+
/** @var \PHPUnit_Framework_MockObject_MockObject */
102+
protected $totalsCollectorMock;
103+
101104
/**
102105
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
103106
*/
@@ -195,6 +198,7 @@ protected function setUp()
195198
->method('toFlatArray')
196199
->will($this->returnValue([]));
197200
$this->objectManagerHelper = new ObjectManagerHelper($this);
201+
$this->totalsCollectorMock = $this->getMock('Magento\Quote\Model\Quote\TotalsCollector', [], [], '', false);
198202
$this->onepage = $this->objectManagerHelper->getObject(
199203
'Magento\Checkout\Model\Type\Onepage',
200204
[
@@ -222,7 +226,8 @@ protected function setUp()
222226
'customerRepository' => $this->customerRepositoryMock,
223227
'extensibleDataObjectConverter' => $this->extensibleDataObjectConverterMock,
224228
'quoteRepository' => $this->quoteRepositoryMock,
225-
'quoteManagement' => $this->quoteManagementMock
229+
'quoteManagement' => $this->quoteManagementMock,
230+
'totalsCollector' => $this->totalsCollectorMock
226231
]
227232
);
228233
}
@@ -492,8 +497,17 @@ public function testSaveBilling(
492497
->method('setCollectShippingRates')
493498
->will($this->returnSelf());
494499

495-
$shippingAddressMock->expects($useForShipping ? $this->once() : $this->never())
496-
->method('collectTotals');
500+
if ($useForShipping === \Magento\Checkout\Model\Type\Onepage::USE_FOR_SHIPPING) {
501+
$this->totalsCollectorMock
502+
->expects($this->once())
503+
->method('collectAddressTotals')
504+
->with($quoteMock, $shippingAddressMock);
505+
} else {
506+
$this->totalsCollectorMock
507+
->expects($this->never())
508+
->method('collectAddressTotals')
509+
->with($quoteMock, $shippingAddressMock);
510+
}
497511

498512
$quoteMock->expects($this->any())->method('setPasswordHash')->with($passwordHash);
499513
$quoteMock->expects($this->any())->method('getCheckoutMethod')->will($this->returnValue($checkoutMethod));

app/code/Magento/Msrp/Block/Total.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,31 @@
1010
*/
1111
class Total extends \Magento\Framework\View\Element\Template
1212
{
13-
/** @var \Magento\Msrp\Model\Config */
13+
/**
14+
* @var \Magento\Msrp\Model\Config
15+
*/
1416
protected $config;
1517

18+
/**
19+
* @var \Magento\Msrp\Model\Quote\Msrp
20+
*/
21+
protected $msrp;
22+
1623
/**
1724
* @param \Magento\Framework\View\Element\Template\Context $context
1825
* @param \Magento\Msrp\Model\Config $config
26+
* @param \Magento\Msrp\Model\Quote\Msrp $msrp
1927
* @param array $data
2028
*/
2129
public function __construct(
2230
\Magento\Framework\View\Element\Template\Context $context,
2331
\Magento\Msrp\Model\Config $config,
32+
\Magento\Msrp\Model\Quote\Msrp $msrp,
2433
array $data = []
2534
) {
2635
parent::__construct($context, $data);
2736
$this->config = $config;
37+
$this->msrp = $msrp;
2838
}
2939

3040
/**
@@ -35,10 +45,10 @@ protected function _toHtml()
3545
/** @var \Magento\Checkout\Block\Cart\AbstractCart $originalBlock */
3646
$originalBlock = $this->getLayout()->getBlock($this->getOriginalBlockName());
3747
$quote = $originalBlock->getQuote();
38-
if (!$quote->hasCanApplyMsrp() && $this->config->isEnabled()) {
48+
if (!$this->msrp->getCanApplyMsrp($quote->getId()) && $this->config->isEnabled()) {
3949
$quote->collectTotals();
4050
}
41-
if ($quote->getCanApplyMsrp()) {
51+
if ($this->msrp->getCanApplyMsrp($quote->getId())) {
4252
$originalBlock->setTemplate('');
4353
return parent::_toHtml();
4454
} else {

0 commit comments

Comments
 (0)