Skip to content

Commit 6d43d57

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop
- merged latest code from mainline branch
2 parents 99a0999 + dc14e50 commit 6d43d57

File tree

8 files changed

+759
-22
lines changed

8 files changed

+759
-22
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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\Observer;
9+
10+
use Magento\Framework\Api\SearchCriteriaBuilder;
11+
use Magento\Framework\Event\Observer;
12+
use Magento\Framework\Event\ObserverInterface;
13+
use Magento\Sales\Api\Data\OrderInterface;
14+
use Magento\Sales\Api\OrderRepositoryInterface;
15+
use Magento\Sales\Model\ResourceModel\Order\Collection;
16+
use Magento\Customer\Model\Data\Customer;
17+
18+
/**
19+
* Class observer UpgradeOrderCustomerEmailObserver
20+
* Update orders customer email after corresponding customer email changed
21+
*/
22+
class UpgradeOrderCustomerEmailObserver implements ObserverInterface
23+
{
24+
/**
25+
* @var OrderRepositoryInterface
26+
*/
27+
private $orderRepository;
28+
29+
/**
30+
* @var SearchCriteriaBuilder
31+
*/
32+
private $searchCriteriaBuilder;
33+
34+
/**
35+
* @param OrderRepositoryInterface $orderRepository
36+
* @param SearchCriteriaBuilder $searchCriteriaBuilder
37+
*/
38+
public function __construct(
39+
OrderRepositoryInterface $orderRepository,
40+
SearchCriteriaBuilder $searchCriteriaBuilder
41+
) {
42+
$this->orderRepository = $orderRepository;
43+
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
44+
}
45+
46+
/**
47+
* Upgrade order customer email when customer has changed email
48+
*
49+
* @param Observer $observer
50+
* @return void
51+
*/
52+
public function execute(Observer $observer): void
53+
{
54+
/** @var Customer $originalCustomer */
55+
$originalCustomer = $observer->getEvent()->getOrigCustomerDataObject();
56+
if (!$originalCustomer) {
57+
return;
58+
}
59+
60+
/** @var Customer $customer */
61+
$customer = $observer->getEvent()->getCustomerDataObject();
62+
$customerEmail = $customer->getEmail();
63+
64+
if ($customerEmail === $originalCustomer->getEmail()) {
65+
return;
66+
}
67+
$searchCriteria = $this->searchCriteriaBuilder
68+
->addFilter(OrderInterface::CUSTOMER_ID, $customer->getId())
69+
->create();
70+
71+
/**
72+
* @var Collection $orders
73+
*/
74+
$orders = $this->orderRepository->getList($searchCriteria);
75+
$orders->setDataToAll(OrderInterface::CUSTOMER_EMAIL, $customerEmail);
76+
$orders->save();
77+
}
78+
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
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\Test\Unit\Observer;
9+
10+
use Magento\Customer\Api\Data\CustomerInterface;
11+
use Magento\Customer\Observer\UpgradeOrderCustomerEmailObserver;
12+
use Magento\Framework\Api\SearchCriteria;
13+
use Magento\Framework\Api\SearchCriteriaBuilder;
14+
use Magento\Framework\Event;
15+
use Magento\Framework\Event\Observer;
16+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
17+
use Magento\Sales\Api\Data\OrderInterface;
18+
use Magento\Sales\Api\OrderRepositoryInterface;
19+
use Magento\Sales\Model\ResourceModel\Order\Collection;
20+
use PHPUnit\Framework\MockObject\MockObject;
21+
use PHPUnit\Framework\TestCase;
22+
23+
/**
24+
* For testing upgrade order customer email
25+
*/
26+
class UpgradeOrderCustomerEmailObserverTest extends TestCase
27+
{
28+
private const NEW_CUSTOMER_EMAIL = "test@test.com";
29+
private const ORIGINAL_CUSTOMER_EMAIL = "origtest@test.com";
30+
31+
/**
32+
* @var UpgradeOrderCustomerEmailObserver
33+
*/
34+
private $orderCustomerEmailObserver;
35+
36+
/**
37+
* @var Observer|MockObject
38+
*/
39+
private $observerMock;
40+
41+
/**
42+
* @var OrderRepositoryInterface|MockObject
43+
*/
44+
private $orderRepositoryMock;
45+
46+
/**
47+
* @var SearchCriteriaBuilder|MockObject
48+
*/
49+
private $searchCriteriaBuilderMock;
50+
51+
/**
52+
* @var Event|MockObject
53+
*/
54+
private $eventMock;
55+
56+
/**
57+
* @var ObjectManagerHelper
58+
*/
59+
private $objectManagerHelper;
60+
61+
/**
62+
* @inheritDoc
63+
*/
64+
protected function setUp(): void
65+
{
66+
$this->orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class)
67+
->getMock();
68+
69+
$this->searchCriteriaBuilderMock = $this->getMockBuilder(SearchCriteriaBuilder::class)
70+
->disableOriginalConstructor()
71+
->getMock();
72+
73+
$this->eventMock = $this->getMockBuilder(Event::class)
74+
->disableOriginalConstructor()
75+
->setMethods(['getCustomerDataObject', 'getOrigCustomerDataObject'])
76+
->getMock();
77+
78+
$this->observerMock = $this->getMockBuilder(Observer::class)
79+
->disableOriginalConstructor()
80+
->getMock();
81+
82+
$this->observerMock->expects($this->any())->method('getEvent')->willReturn($this->eventMock);
83+
84+
$this->objectManagerHelper = new ObjectManagerHelper($this);
85+
86+
$this->orderCustomerEmailObserver = $this->objectManagerHelper->getObject(
87+
UpgradeOrderCustomerEmailObserver::class,
88+
[
89+
'orderRepository' => $this->orderRepositoryMock,
90+
'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock,
91+
]
92+
);
93+
}
94+
95+
/**
96+
* Verifying that the order email is not updated when the customer email is not updated
97+
*
98+
*/
99+
public function testUpgradeOrderCustomerEmailWhenMailIsNotChanged(): void
100+
{
101+
$customer = $this->createCustomerMock();
102+
$originalCustomer = $this->createCustomerMock();
103+
104+
$this->setCustomerToEventMock($customer);
105+
$this->setOriginalCustomerToEventMock($originalCustomer);
106+
107+
$this->setCustomerEmail($originalCustomer, self::ORIGINAL_CUSTOMER_EMAIL);
108+
$this->setCustomerEmail($customer, self::ORIGINAL_CUSTOMER_EMAIL);
109+
110+
$this->whenOrderRepositoryGetListIsNotCalled();
111+
112+
$this->orderCustomerEmailObserver->execute($this->observerMock);
113+
}
114+
115+
/**
116+
* Verifying that the order email is updated after the customer updates their email
117+
*
118+
*/
119+
public function testUpgradeOrderCustomerEmail(): void
120+
{
121+
$customer = $this->createCustomerMock();
122+
$originalCustomer = $this->createCustomerMock();
123+
$orderCollectionMock = $this->createOrderMock();
124+
125+
$this->setCustomerToEventMock($customer);
126+
$this->setOriginalCustomerToEventMock($originalCustomer);
127+
128+
$this->setCustomerEmail($originalCustomer, self::ORIGINAL_CUSTOMER_EMAIL);
129+
$this->setCustomerEmail($customer, self::NEW_CUSTOMER_EMAIL);
130+
131+
$this->whenOrderRepositoryGetListIsCalled($orderCollectionMock);
132+
133+
$this->whenOrderCollectionSetDataToAllIsCalled($orderCollectionMock);
134+
135+
$this->whenOrderCollectionSaveIsCalled($orderCollectionMock);
136+
137+
$this->orderCustomerEmailObserver->execute($this->observerMock);
138+
}
139+
140+
private function createCustomerMock(): MockObject
141+
{
142+
$customer = $this->getMockBuilder(CustomerInterface::class)
143+
->disableOriginalConstructor()
144+
->getMock();
145+
146+
return $customer;
147+
}
148+
149+
private function createOrderMock(): MockObject
150+
{
151+
$orderCollectionMock = $this->getMockBuilder(Collection::class)
152+
->disableOriginalConstructor()
153+
->getMock();
154+
155+
return $orderCollectionMock;
156+
}
157+
158+
private function setCustomerToEventMock(MockObject $customer): void
159+
{
160+
$this->eventMock->expects($this->once())
161+
->method('getCustomerDataObject')
162+
->willReturn($customer);
163+
}
164+
165+
private function setOriginalCustomerToEventMock(MockObject $originalCustomer): void
166+
{
167+
$this->eventMock->expects($this->once())
168+
->method('getOrigCustomerDataObject')
169+
->willReturn($originalCustomer);
170+
}
171+
172+
private function setCustomerEmail(MockObject $originalCustomer, string $email): void
173+
{
174+
$originalCustomer->expects($this->once())
175+
->method('getEmail')
176+
->willReturn($email);
177+
}
178+
179+
private function whenOrderRepositoryGetListIsCalled(MockObject $orderCollectionMock): void
180+
{
181+
$searchCriteriaMock = $this->getMockBuilder(SearchCriteria::class)
182+
->disableOriginalConstructor()
183+
->getMockForAbstractClass();
184+
185+
$this->searchCriteriaBuilderMock->expects($this->once())
186+
->method('create')
187+
->willReturn($searchCriteriaMock);
188+
189+
$this->searchCriteriaBuilderMock->expects($this->once())
190+
->method('addFilter')
191+
->willReturn($this->searchCriteriaBuilderMock);
192+
193+
$this->orderRepositoryMock->expects($this->once())
194+
->method('getList')
195+
->with($searchCriteriaMock)
196+
->willReturn($orderCollectionMock);
197+
}
198+
199+
private function whenOrderCollectionSetDataToAllIsCalled(MockObject $orderCollectionMock): void
200+
{
201+
$orderCollectionMock->expects($this->once())
202+
->method('setDataToAll')
203+
->with(OrderInterface::CUSTOMER_EMAIL, self::NEW_CUSTOMER_EMAIL);
204+
}
205+
206+
private function whenOrderCollectionSaveIsCalled(MockObject $orderCollectionMock): void
207+
{
208+
$orderCollectionMock->expects($this->once())
209+
->method('save');
210+
}
211+
212+
private function whenOrderRepositoryGetListIsNotCalled(): void
213+
{
214+
$this->searchCriteriaBuilderMock->expects($this->never())
215+
->method('addFilter');
216+
$this->searchCriteriaBuilderMock->expects($this->never())
217+
->method('create');
218+
219+
$this->orderRepositoryMock->expects($this->never())
220+
->method('getList');
221+
}
222+
}

app/code/Magento/Customer/etc/events.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<observer name="customer_visitor" instance="Magento\Customer\Observer\Visitor\BindQuoteCreateObserver" />
1717
</event>
1818
<event name="customer_save_after_data_object">
19+
<observer name="upgrade_order_customer_email" instance="Magento\Customer\Observer\UpgradeOrderCustomerEmailObserver"/>
1920
<observer name="upgrade_quote_customer_email" instance="Magento\Customer\Observer\UpgradeQuoteCustomerEmailObserver"/>
2021
</event>
2122
</config>

0 commit comments

Comments
 (0)