Skip to content

Commit d35dd1c

Browse files
committed
MC-37351: Cart contents lost after switching to different store with different domain
- Add ability to extend store switch request data
1 parent 4ae0f74 commit d35dd1c

25 files changed

+1042
-158
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Checkout\Model\StoreSwitcher;
9+
10+
use Magento\Checkout\Model\Session as CheckoutSession;
11+
use Magento\Customer\Model\Session as CustomerSession;
12+
use Magento\Quote\Api\CartRepositoryInterface;
13+
use Magento\Store\Model\StoreSwitcher\ContextInterface;
14+
use Magento\Store\Model\StoreSwitcher\RedirectDataPostprocessorInterface;
15+
use Psr\Log\LoggerInterface;
16+
17+
/**
18+
* Process checkout data redirected from origin store
19+
*
20+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
21+
*/
22+
class RedirectDataPostprocessor implements RedirectDataPostprocessorInterface
23+
{
24+
/**
25+
* @var CartRepositoryInterface
26+
*/
27+
private $quoteRepository;
28+
29+
/**
30+
* @var CustomerSession
31+
*/
32+
private $customerSession;
33+
34+
/**
35+
* @var CheckoutSession
36+
*/
37+
private $checkoutSession;
38+
39+
/**
40+
* @var LoggerInterface
41+
*/
42+
private $logger;
43+
44+
/**
45+
* @param CartRepositoryInterface $quoteRepository
46+
* @param CustomerSession $customerSession
47+
* @param CheckoutSession $checkoutSession
48+
* @param LoggerInterface $logger
49+
*/
50+
public function __construct(
51+
CartRepositoryInterface $quoteRepository,
52+
CustomerSession $customerSession,
53+
CheckoutSession $checkoutSession,
54+
LoggerInterface $logger
55+
) {
56+
$this->quoteRepository = $quoteRepository;
57+
$this->customerSession = $customerSession;
58+
$this->checkoutSession = $checkoutSession;
59+
$this->logger = $logger;
60+
}
61+
62+
/**
63+
* @inheritDoc
64+
*/
65+
public function process(ContextInterface $context, array $data): void
66+
{
67+
if (!empty($data['quote_id'])
68+
&& $this->checkoutSession->getQuoteId() === null
69+
&& !$this->customerSession->isLoggedIn()
70+
) {
71+
try {
72+
$quote = $this->quoteRepository->get((int) $data['quote_id']);
73+
if ($quote
74+
&& $quote->getIsActive()
75+
&& in_array($context->getTargetStore()->getId(), $quote->getSharedStoreIds())
76+
) {
77+
$this->checkoutSession->setQuoteId($quote->getId());
78+
}
79+
} catch (\Throwable $e) {
80+
$this->logger->error($e);
81+
}
82+
}
83+
$quote = $this->checkoutSession->getQuote();
84+
if ($quote->getIsActive()) {
85+
// Update quote items so that product names are updated for current store view
86+
$quote->setStoreId($context->getTargetStore()->getId());
87+
$quote->getItemsCollection(false);
88+
$this->quoteRepository->save($quote);
89+
}
90+
}
91+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Checkout\Model\StoreSwitcher;
9+
10+
use Magento\Checkout\Model\Session as CheckoutSession;
11+
use Magento\Customer\Model\Session as CustomerSession;
12+
use Magento\Quote\Api\CartRepositoryInterface;
13+
use Magento\Store\Model\StoreSwitcher\ContextInterface;
14+
use Magento\Store\Model\StoreSwitcher\RedirectDataPreprocessorInterface;
15+
16+
/**
17+
* Collect checkout data to be redirected to target store
18+
*
19+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
20+
*/
21+
class RedirectDataPreprocessor implements RedirectDataPreprocessorInterface
22+
{
23+
/**
24+
* @var CartRepositoryInterface
25+
*/
26+
private $quoteRepository;
27+
28+
/**
29+
* @var CustomerSession
30+
*/
31+
private $customerSession;
32+
33+
/**
34+
* @var CheckoutSession
35+
*/
36+
private $checkoutSession;
37+
38+
/**
39+
* @param CartRepositoryInterface $quoteRepository
40+
* @param CustomerSession $customerSession
41+
* @param CheckoutSession $checkoutSession
42+
*/
43+
public function __construct(
44+
CartRepositoryInterface $quoteRepository,
45+
CustomerSession $customerSession,
46+
CheckoutSession $checkoutSession
47+
) {
48+
$this->quoteRepository = $quoteRepository;
49+
$this->customerSession = $customerSession;
50+
$this->checkoutSession = $checkoutSession;
51+
}
52+
/**
53+
* @inheritDoc
54+
*/
55+
public function process(ContextInterface $context, array $data): array
56+
{
57+
if ($this->checkoutSession->getQuoteId() && !$this->customerSession->isLoggedIn()) {
58+
$quote = $this->checkoutSession->getQuote();
59+
if ($quote
60+
&& $quote->getIsActive()
61+
&& in_array($context->getTargetStore()->getId(), $quote->getSharedStoreIds())
62+
) {
63+
$data['quote_id'] = (int) $quote->getId();
64+
}
65+
}
66+
return $data;
67+
}
68+
}

app/code/Magento/Checkout/etc/frontend/di.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,18 @@
9999
<type name="Magento\Quote\Model\Quote">
100100
<plugin name="clear_addresses_after_product_delete" type="Magento\Checkout\Plugin\Model\Quote\ResetQuoteAddresses"/>
101101
</type>
102+
<type name="Magento\Store\Model\StoreSwitcher\RedirectDataPreprocessorComposite">
103+
<arguments>
104+
<argument name="processors" xsi:type="array">
105+
<item name="checkout_session" xsi:type="object">Magento\Checkout\Model\StoreSwitcher\RedirectDataPreprocessor</item>
106+
</argument>
107+
</arguments>
108+
</type>
109+
<type name="Magento\Store\Model\StoreSwitcher\RedirectDataPostprocessorComposite">
110+
<arguments>
111+
<argument name="processors" xsi:type="array">
112+
<item name="checkout_session" xsi:type="object">Magento\Checkout\Model\StoreSwitcher\RedirectDataPostprocessor</item>
113+
</argument>
114+
</arguments>
115+
</type>
102116
</config>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Customer\Model\StoreSwitcher;
9+
10+
use Magento\Customer\Model\CustomerRegistry;
11+
use Magento\Customer\Model\Session;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Store\Model\StoreSwitcher\ContextInterface;
15+
use Magento\Store\Model\StoreSwitcher\RedirectDataPostprocessorInterface;
16+
use Psr\Log\LoggerInterface;
17+
18+
/**
19+
* Process customer data redirected from origin store
20+
*
21+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
22+
*/
23+
class RedirectDataPostprocessor implements RedirectDataPostprocessorInterface
24+
{
25+
/**
26+
* @var Session
27+
*/
28+
private $session;
29+
/**
30+
* @var LoggerInterface
31+
*/
32+
private $logger;
33+
/**
34+
* @var CustomerRegistry
35+
*/
36+
private $customerRegistry;
37+
38+
/**
39+
* @param CustomerRegistry $customerRegistry
40+
* @param Session $session
41+
* @param LoggerInterface $logger
42+
*/
43+
public function __construct(
44+
CustomerRegistry $customerRegistry,
45+
Session $session,
46+
LoggerInterface $logger
47+
) {
48+
$this->customerRegistry = $customerRegistry;
49+
$this->session = $session;
50+
$this->logger = $logger;
51+
}
52+
53+
/**
54+
* @inheritDoc
55+
*/
56+
public function process(ContextInterface $context, array $data): void
57+
{
58+
if (!empty($data['customer_id'])) {
59+
try {
60+
$customer = $this->customerRegistry->retrieve($data['customer_id']);
61+
if (!$this->session->isLoggedIn()
62+
&& in_array($context->getTargetStore()->getId(), $customer->getSharedStoreIds())
63+
) {
64+
$this->session->setCustomerDataAsLoggedIn($customer->getDataModel());
65+
}
66+
} catch (NoSuchEntityException $e) {
67+
$this->logger->error($e);
68+
throw new LocalizedException(__('The requested customer does not exist.'), $e);
69+
} catch (LocalizedException $e) {
70+
$this->logger->error($e);
71+
throw new LocalizedException(__('There was an error retrieving the customer record.'), $e);
72+
}
73+
}
74+
}
75+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Customer\Model\StoreSwitcher;
9+
10+
use Magento\Authorization\Model\UserContextInterface;
11+
use Magento\Customer\Model\CustomerRegistry;
12+
use Magento\Store\Model\StoreSwitcher\ContextInterface;
13+
use Magento\Store\Model\StoreSwitcher\RedirectDataPreprocessorInterface;
14+
use Psr\Log\LoggerInterface;
15+
use Throwable;
16+
17+
/**
18+
* Collect customer data to be redirected to target store
19+
*/
20+
class RedirectDataPreprocessor implements RedirectDataPreprocessorInterface
21+
{
22+
/**
23+
* @var UserContextInterface
24+
*/
25+
private $userContext;
26+
/**
27+
* @var LoggerInterface
28+
*/
29+
private $logger;
30+
/**
31+
* @var CustomerRegistry
32+
*/
33+
private $customerRegistry;
34+
35+
/**
36+
* @param CustomerRegistry $customerRegistry
37+
* @param UserContextInterface $userContext
38+
* @param LoggerInterface $logger
39+
*/
40+
public function __construct(
41+
CustomerRegistry $customerRegistry,
42+
UserContextInterface $userContext,
43+
LoggerInterface $logger
44+
) {
45+
$this->customerRegistry = $customerRegistry;
46+
$this->userContext = $userContext;
47+
$this->logger = $logger;
48+
}
49+
50+
/**
51+
* @inheritDoc
52+
*/
53+
public function process(ContextInterface $context, array $data): array
54+
{
55+
if ($this->userContext->getUserType() === UserContextInterface::USER_TYPE_CUSTOMER
56+
&& $this->userContext->getUserId()
57+
) {
58+
try {
59+
$customer = $this->customerRegistry->retrieve($this->userContext->getUserId());
60+
if (in_array($context->getTargetStore()->getId(), $customer->getSharedStoreIds())) {
61+
$data['customer_id'] = (int) $customer->getId();
62+
}
63+
} catch (Throwable $e) {
64+
$this->logger->error($e);
65+
}
66+
}
67+
68+
return $data;
69+
}
70+
}

app/code/Magento/Customer/etc/frontend/di.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,18 @@
113113
</argument>
114114
</arguments>
115115
</type>
116+
<type name="Magento\Store\Model\StoreSwitcher\RedirectDataPreprocessorComposite">
117+
<arguments>
118+
<argument name="processors" xsi:type="array">
119+
<item name="customer_session" xsi:type="object">Magento\Customer\Model\StoreSwitcher\RedirectDataPreprocessor</item>
120+
</argument>
121+
</arguments>
122+
</type>
123+
<type name="Magento\Store\Model\StoreSwitcher\RedirectDataPostprocessorComposite">
124+
<arguments>
125+
<argument name="processors" xsi:type="array">
126+
<item name="customer_session" xsi:type="object">Magento\Customer\Model\StoreSwitcher\RedirectDataPostprocessor</item>
127+
</argument>
128+
</arguments>
129+
</type>
116130
</config>

0 commit comments

Comments
 (0)