Skip to content

Quote is loaded without totals #39201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: 2.4-develop
Choose a base branch
from
28 changes: 12 additions & 16 deletions app/code/Magento/Checkout/Model/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,17 +279,16 @@ public function getQuote()
*/
if ($quote->getQuoteCurrencyCode() != $this->_storeManager->getStore()->getCurrentCurrencyCode()) {
$quote->setStore($this->_storeManager->getStore());
}

if ($this->getQuoteId() && !$quote->getTotalsCollectedFlag()) {
$this->quoteRepository->save($quote->collectTotals());
/*
* We mast to create new quote object, because collectTotals()
* can to create links with other objects.
* We must create a new quote object, because collectTotals()
* can create links with other objects.
*/
$quote = $this->quoteRepository->get($this->getQuoteId());
}

if ($quote->getTotalsCollectedFlag() === false) {
$quote->collectTotals();
}
} catch (NoSuchEntityException $e) {
$this->setQuoteId(null);
}
Expand Down Expand Up @@ -399,13 +398,9 @@ public function loadCustomerQuote()
$quote = $this->getQuote();
$quote->setCustomerIsGuest(0);
$this->quoteRepository->save(
$customerQuote->merge($quote)->collectTotals()
);
$newQuote = $this->quoteRepository->get($customerQuote->getId());
$this->quoteRepository->save(
$newQuote->collectTotals()
$customerQuote->merge($quote)->setTotalsCollectedFlag(false)->collectTotals()
);
$customerQuote = $newQuote;
$customerQuote = $this->quoteRepository->get($customerQuote->getId());
}

$this->setQuoteId($customerQuote->getId());
Expand All @@ -415,13 +410,14 @@ public function loadCustomerQuote()
}
$this->_quote = $customerQuote;
} else {
$this->getQuote()->getBillingAddress();
$this->getQuote()->getShippingAddress();
$this->getQuote()->setCustomer($this->_customerSession->getCustomerDataObject())
$quote = $this->getQuote();
$quote->getBillingAddress();
$quote->getShippingAddress();
$quote->setCustomer($this->_customerSession->getCustomerDataObject())
->setCustomerIsGuest(0)
->setTotalsCollectedFlag(false)
->collectTotals();
$this->quoteRepository->save($this->getQuote());
$this->quoteRepository->save($quote);
}
return $this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2018 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

Expand Down Expand Up @@ -51,7 +51,7 @@ protected function tearDown(): void
* @param $observerEnabled
* @return void
*/
public function testLoadQuoteSuccessfully($triggerRecollect, $observerEnabled): void
public function testLoadQuote($triggerRecollect, $observerEnabled): void
{
$originalQuote = $this->generateQuote($triggerRecollect);
$quoteId = $originalQuote->getId();
Expand All @@ -64,6 +64,8 @@ public function testLoadQuoteSuccessfully($triggerRecollect, $observerEnabled):
);

if ($observerEnabled) {
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Infinite loop detected, review the trace for the looping path');
$this->config->enableObserver();
}

Expand All @@ -73,8 +75,19 @@ public function testLoadQuoteSuccessfully($triggerRecollect, $observerEnabled):
$session->setQuoteId($quoteId);

$quote = $session->getQuote();
$this->assertEquals($quoteId, $quote->getId(), "The loaded quote should have the same ID as the initial quote");
$this->assertEquals(0, $quote->getTriggerRecollect(), "trigger_recollect should be unset after a quote reload");

if (!$observerEnabled) {
$this->assertEquals(
$quoteId,
$quote->getId(),
'The loaded quote should have the same ID as the initial quote'
);
$this->assertEquals(
0,
$quote->getTriggerRecollect(),
'trigger_recollect should be unset after a quote reload'
);
}
}

/**
Expand All @@ -86,36 +99,10 @@ public static function getLoadQuoteParametersProvider()
[0, false],
[0, true],
[1, false],
//[1, true], this combination of trigger recollect and third party code causes the loop, tested separately
[1, true],
];
}

/**
*
* @return void
*/
public function testLoadQuoteWithTriggerRecollectInfiniteLoop(): void
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Infinite loop detected, review the trace for the looping path');

$originalQuote = $this->generateQuote();
$quoteId = $originalQuote->getId();

$this->assertGreaterThan(0, $quoteId, "The quote should have a database id");
$this->assertEquals(1, $originalQuote->getTriggerRecollect(), "The quote has trigger_recollect set");

// Enable an observer which gets the quote from the session
// The observer hooks into part of the collect totals process for an easy demonstration of the loop.
$this->config->enableObserver();

/** @var $session \Magento\Checkout\Model\Session */
$this->objectManager->removeSharedInstance(\Magento\Checkout\Model\Session::class);
$session = $this->objectManager->get(\Magento\Checkout\Model\Session::class);
$session->setQuoteId($quoteId);
$session->getQuote();
}

/**
* Generate a quote with trigger_recollect and save it in the database.
*
Expand Down