Skip to content

Commit 27a9951

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop-expedited-prs
- merged with '2.4-develop-prs' branch
2 parents 878c617 + d7d71d6 commit 27a9951

File tree

6 files changed

+163
-21
lines changed

6 files changed

+163
-21
lines changed

app/code/Magento/Cron/Model/Schedule.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public function matchCronExpression($expr, $num)
189189
}
190190

191191
// handle all match by modulus
192+
$offset = 0;
192193
if ($expr === '*') {
193194
$from = 0;
194195
$to = 60;
@@ -201,6 +202,13 @@ public function matchCronExpression($expr, $num)
201202

202203
$from = $this->getNumeric($e[0]);
203204
$to = $this->getNumeric($e[1]);
205+
if ($mod !== 1) {
206+
$offset = $from;
207+
}
208+
} elseif ($mod !== 1) {
209+
$offset = $this->getNumeric($expr);
210+
$from = 0;
211+
$to = 60;
204212
} else {
205213
// handle regular token
206214
$from = $this->getNumeric($expr);
@@ -211,7 +219,7 @@ public function matchCronExpression($expr, $num)
211219
throw new CronException(__('Invalid cron expression: %1', $expr));
212220
}
213221

214-
return $num >= $from && $num <= $to && $num % $mod === 0;
222+
return $num >= $from && $num <= $to && ($num - $offset) % $mod === 0;
215223
}
216224

217225
/**

app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,24 +128,28 @@ public function setCronExprDataProvider(): array
128128
[', * * * *', [',', '*', '*', '*', '*']],
129129
['1-2 * * * *', ['1-2', '*', '*', '*', '*']],
130130
['0/5 * * * *', ['0/5', '*', '*', '*', '*']],
131+
['3/5 * * * *', ['3/5', '*', '*', '*', '*']],
131132

132133
['* 0 * * *', ['*', '0', '*', '*', '*']],
133134
['* 59 * * *', ['*', '59', '*', '*', '*']],
134135
['* , * * *', ['*', ',', '*', '*', '*']],
135136
['* 1-2 * * *', ['*', '1-2', '*', '*', '*']],
136137
['* 0/5 * * *', ['*', '0/5', '*', '*', '*']],
138+
['* 3/5 * * *', ['*', '3/5', '*', '*', '*']],
137139

138140
['* * 0 * *', ['*', '*', '0', '*', '*']],
139141
['* * 23 * *', ['*', '*', '23', '*', '*']],
140142
['* * , * *', ['*', '*', ',', '*', '*']],
141143
['* * 1-2 * *', ['*', '*', '1-2', '*', '*']],
142144
['* * 0/5 * *', ['*', '*', '0/5', '*', '*']],
145+
['* * 3/5 * *', ['*', '*', '3/5', '*', '*']],
143146

144147
['* * * 1 *', ['*', '*', '*', '1', '*']],
145148
['* * * 31 *', ['*', '*', '*', '31', '*']],
146149
['* * * , *', ['*', '*', '*', ',', '*']],
147150
['* * * 1-2 *', ['*', '*', '*', '1-2', '*']],
148151
['* * * 0/5 *', ['*', '*', '*', '0/5', '*']],
152+
['* * * 3/5 *', ['*', '*', '*', '3/5', '*']],
149153
['* * * ? *', ['*', '*', '*', '?', '*']],
150154
['* * * L *', ['*', '*', '*', 'L', '*']],
151155
['* * * W *', ['*', '*', '*', 'W', '*']],
@@ -156,6 +160,7 @@ public function setCronExprDataProvider(): array
156160
['* * * * ,', ['*', '*', '*', '*', ',']],
157161
['* * * * 1-2', ['*', '*', '*', '*', '1-2']],
158162
['* * * * 0/5', ['*', '*', '*', '*', '0/5']],
163+
['* * * * 3/5', ['*', '*', '*', '*', '3/5']],
159164
['* * * * JAN', ['*', '*', '*', '*', 'JAN']],
160165
['* * * * DEC', ['*', '*', '*', '*', 'DEC']],
161166
['* * * * JAN-DEC', ['*', '*', '*', '*', 'JAN-DEC']],
@@ -165,6 +170,7 @@ public function setCronExprDataProvider(): array
165170
['* * * * * ,', ['*', '*', '*', '*', '*', ',']],
166171
['* * * * * 1-2', ['*', '*', '*', '*', '*', '1-2']],
167172
['* * * * * 0/5', ['*', '*', '*', '*', '*', '0/5']],
173+
['* * * * * 3/5', ['*', '*', '*', '*', '*', '3/5']],
168174
['* * * * * ?', ['*', '*', '*', '*', '*', '?']],
169175
['* * * * * L', ['*', '*', '*', '*', '*', 'L']],
170176
['* * * * * 6#3', ['*', '*', '*', '*', '*', '6#3']],
@@ -372,9 +378,19 @@ public function matchCronExpressionDataProvider(): array
372378
['0-20/5', 21, false],
373379
['0-20/5', 25, false],
374380

381+
['3-20/5', 3, true],
382+
['3-20/5', 8, true],
383+
['3-20/5', 13, true],
384+
['3-20/5', 24, false],
385+
['3-20/5', 28, false],
386+
375387
['1/5', 5, false],
376388
['5/5', 5, true],
377389
['10/5', 10, true],
390+
391+
['4/5', 8, false],
392+
['8/5', 8, true],
393+
['13/5', 13, true],
378394
];
379395
}
380396

app/code/Magento/Newsletter/Test/Unit/Model/SubscriptionManagerTest.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,8 @@ public function testSubscribe(
136136
->with(Subscriber::XML_PATH_CONFIRMATION_FLAG, ScopeInterface::SCOPE_STORE, $storeId)
137137
->willReturn($isConfirmNeed);
138138

139-
$this->assertEquals(
140-
$subscriber,
141-
$this->subscriptionManager->subscribe($email, $storeId)
142-
);
143-
$this->assertEquals($subscriber->getData(), $expectedData);
139+
$this->assertEquals($subscriber, $this->subscriptionManager->subscribe($email, $storeId));
140+
$this->assertEquals($expectedData, $subscriber->getData());
144141
}
145142

146143
/**
@@ -308,7 +305,7 @@ public function testSubscribeCustomer(
308305
$subscriber,
309306
$this->subscriptionManager->subscribeCustomer($customerId, $storeId)
310307
);
311-
$this->assertEquals($subscriber->getData(), $expectedData);
308+
$this->assertEquals($expectedData, $subscriber->getData());
312309
}
313310

314311
/**
@@ -553,7 +550,7 @@ public function testUnsubscribeCustomer(
553550
$subscriber,
554551
$this->subscriptionManager->unsubscribeCustomer($customerId, $storeId)
555552
);
556-
$this->assertEquals($subscriber->getData(), $expectedData);
553+
$this->assertEquals($expectedData, $subscriber->getData());
557554
}
558555

559556
/**

app/code/Magento/Quote/Model/CustomerManagement.php

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Quote\Model;
89

9-
use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository;
1010
use Magento\Customer\Api\AccountManagementInterface as AccountManagement;
1111
use Magento\Customer\Api\AddressRepositoryInterface as CustomerAddressRepository;
12-
use Magento\Quote\Model\Quote as QuoteEntity;
12+
use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository;
13+
use Magento\Customer\Model\AddressFactory;
1314
use Magento\Framework\App\ObjectManager;
15+
use Magento\Framework\Validator\Exception as ValidatorException;
16+
use Magento\Framework\Validator\Factory as ValidatorFactory;
17+
use Magento\Quote\Model\Quote as QuoteEntity;
1418

1519
/**
1620
* Class Customer
@@ -33,12 +37,12 @@ class CustomerManagement
3337
protected $accountManagement;
3438

3539
/**
36-
* @var \Magento\Framework\Validator\Factory
40+
* @var ValidatorFactory
3741
*/
3842
private $validatorFactory;
3943

4044
/**
41-
* @var \Magento\Customer\Model\AddressFactory
45+
* @var AddressFactory
4246
*/
4347
private $addressFactory;
4448

@@ -47,23 +51,23 @@ class CustomerManagement
4751
* @param CustomerRepository $customerRepository
4852
* @param CustomerAddressRepository $customerAddressRepository
4953
* @param AccountManagement $accountManagement
50-
* @param \Magento\Framework\Validator\Factory|null $validatorFactory
51-
* @param \Magento\Customer\Model\AddressFactory|null $addressFactory
54+
* @param ValidatorFactory|null $validatorFactory
55+
* @param AddressFactory|null $addressFactory
5256
*/
5357
public function __construct(
5458
CustomerRepository $customerRepository,
5559
CustomerAddressRepository $customerAddressRepository,
5660
AccountManagement $accountManagement,
57-
\Magento\Framework\Validator\Factory $validatorFactory = null,
58-
\Magento\Customer\Model\AddressFactory $addressFactory = null
61+
ValidatorFactory $validatorFactory = null,
62+
AddressFactory $addressFactory = null
5963
) {
6064
$this->customerRepository = $customerRepository;
6165
$this->customerAddressRepository = $customerAddressRepository;
6266
$this->accountManagement = $accountManagement;
6367
$this->validatorFactory = $validatorFactory ?: ObjectManager::getInstance()
64-
->get(\Magento\Framework\Validator\Factory::class);
68+
->get(ValidatorFactory::class);
6569
$this->addressFactory = $addressFactory ?: ObjectManager::getInstance()
66-
->get(\Magento\Customer\Model\AddressFactory::class);
70+
->get(AddressFactory::class);
6771
}
6872

6973
/**
@@ -82,6 +86,7 @@ public function populateCustomerInfo(QuoteEntity $quote)
8286
$quote->getPasswordHash()
8387
);
8488
$quote->setCustomer($customer);
89+
$this->fillCustomerAddressId($quote);
8590
}
8691
if (!$quote->getBillingAddress()->getId() && $customer->getDefaultBilling()) {
8792
$quote->getBillingAddress()->importCustomerAddressData(
@@ -100,11 +105,36 @@ public function populateCustomerInfo(QuoteEntity $quote)
100105
}
101106
}
102107

108+
/**
109+
* Filling 'CustomerAddressId' in quote for a newly created customer.
110+
*
111+
* @param QuoteEntity $quote
112+
* @return void
113+
*/
114+
private function fillCustomerAddressId(QuoteEntity $quote): void
115+
{
116+
$customer = $quote->getCustomer();
117+
118+
$customer->getDefaultBilling() ?
119+
$quote->getBillingAddress()->setCustomerAddressId($customer->getDefaultBilling()) :
120+
$quote->getBillingAddress()->setCustomerAddressId(0);
121+
122+
if ($customer->getDefaultShipping() || $customer->getDefaultBilling()) {
123+
if ($quote->getShippingAddress()->getSameAsBilling()) {
124+
$quote->getShippingAddress()->setCustomerAddressId($customer->getDefaultBilling());
125+
} else {
126+
$quote->getShippingAddress()->setCustomerAddressId($customer->getDefaultShipping());
127+
}
128+
} else {
129+
$quote->getShippingAddress()->setCustomerAddressId(0);
130+
}
131+
}
132+
103133
/**
104134
* Validate Quote Addresses
105135
*
106136
* @param Quote $quote
107-
* @throws \Magento\Framework\Validator\Exception
137+
* @throws ValidatorException
108138
* @return void
109139
*/
110140
public function validateAddresses(QuoteEntity $quote)
@@ -126,7 +156,7 @@ public function validateAddresses(QuoteEntity $quote)
126156
$addressModel = $this->addressFactory->create();
127157
$addressModel->updateData($address);
128158
if (!$validator->isValid($addressModel)) {
129-
throw new \Magento\Framework\Validator\Exception(
159+
throw new ValidatorException(
130160
null,
131161
null,
132162
$validator->getMessages()

app/code/Magento/Quote/Test/Unit/Model/CustomerManagementTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ protected function setUp(): void
147147

148148
public function testPopulateCustomerInfo()
149149
{
150-
$this->quoteMock->expects($this->once())
150+
$this->quoteMock->expects($this->atLeastOnce())
151151
->method('getCustomer')
152152
->willReturn($this->customerMock);
153153
$this->customerMock->expects($this->atLeastOnce())
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\Quote\Model;
9+
10+
use Magento\Customer\Api\CustomerRepositoryInterface;
11+
use Magento\Customer\Api\Data\CustomerInterface;
12+
use Magento\Framework\Api\SearchCriteriaBuilder;
13+
use Magento\Framework\ObjectManagerInterface;
14+
use Magento\Quote\Api\CartRepositoryInterface;
15+
use Magento\TestFramework\Helper\Bootstrap as BootstrapHelper;
16+
use PHPUnit\Framework\TestCase;
17+
18+
/**
19+
* @magentoDbIsolation disabled
20+
* @magentoAppArea adminhtml
21+
*/
22+
class CustomerManagementTest extends TestCase
23+
{
24+
/**
25+
* @var ObjectManagerInterface
26+
*/
27+
private $objectManager;
28+
29+
/**
30+
* @var CustomerManagement
31+
*/
32+
private $customerManagemet;
33+
34+
/**
35+
* @var CustomerInterface
36+
*/
37+
private $customer;
38+
39+
protected function setUp(): void
40+
{
41+
$this->objectManager = BootstrapHelper::getObjectManager();
42+
$this->customerManagemet = $this->objectManager->create(CustomerManagement::class);
43+
$this->customer = $this->objectManager->create(CustomerInterface::class);
44+
}
45+
46+
protected function tearDown(): void
47+
{
48+
/** @var CustomerRepositoryInterface $customerRepository */
49+
$customerRepository = $this->objectManager->create(CustomerRepositoryInterface::class);
50+
$customer = $customerRepository->get('john1.doe001@test.com');
51+
$customerRepository->delete($customer);
52+
}
53+
54+
/**
55+
* @magentoDataFixture Magento/Sales/_files/quote.php
56+
*/
57+
public function testCustomerAddressIdQuote(): void
58+
{
59+
$reservedOrderId = 'test01';
60+
61+
$this->customer->setEmail('john1.doe001@test.com')
62+
->setFirstname('doe')
63+
->setLastname('john');
64+
65+
$quote = $this->getQuote($reservedOrderId)->setCustomer($this->customer);
66+
$this->customerManagemet->populateCustomerInfo($quote);
67+
self::assertNotNull($quote->getBillingAddress()->getCustomerAddressId());
68+
self::assertNotNull($quote->getShippingAddress()->getCustomerAddressId());
69+
}
70+
71+
/**
72+
* Gets quote by reserved order ID.
73+
*
74+
* @param string $reservedOrderId
75+
* @return Quote
76+
*/
77+
private function getQuote(string $reservedOrderId): Quote
78+
{
79+
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
80+
$searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class);
81+
$searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId)
82+
->create();
83+
84+
/** @var CartRepositoryInterface $quoteRepository */
85+
$quoteRepository = $this->objectManager->get(CartRepositoryInterface::class);
86+
$items = $quoteRepository->getList($searchCriteria)
87+
->getItems();
88+
89+
return array_pop($items);
90+
}
91+
}

0 commit comments

Comments
 (0)