Skip to content

Commit bca0482

Browse files
Merge pull request #9289 from magento-cia/cia-2.4.8-beta2-develop-bugfix-10072024
Cia 2.4.8 beta2 develop bugfix 10072024
2 parents 42f0d08 + b179647 commit bca0482

File tree

12 files changed

+351
-121
lines changed

12 files changed

+351
-121
lines changed

app/code/Magento/Customer/Controller/Account/EditPost.php

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -237,17 +237,6 @@ public function execute()
237237
$customer = $this->getCustomerDataObject($this->session->getCustomerId());
238238
$customerCandidate = $this->populateNewCustomerDataObject($this->_request, $customer);
239239

240-
$attributeToDelete = (string)$this->_request->getParam('delete_attribute_value');
241-
if ($attributeToDelete !== "") {
242-
$attributesToDelete = $this->prepareAttributesToDelete($attributeToDelete);
243-
foreach ($attributesToDelete as $attribute) {
244-
$uploadedValue = $this->_request->getParam($attribute . File::UPLOADED_FILE_SUFFIX);
245-
if ((string)$uploadedValue === "") {
246-
$this->deleteCustomerFileAttribute($customerCandidate, $attribute);
247-
}
248-
}
249-
}
250-
251240
try {
252241
// whether a customer enabled change email option
253242
$isEmailChanged = $this->processChangeEmailRequest($customer);
@@ -310,26 +299,6 @@ public function execute()
310299
return $resultRedirect;
311300
}
312301

313-
/**
314-
* Convert comma-separated list of attributes to delete into array
315-
*
316-
* @param string $attribute
317-
* @return array
318-
*/
319-
private function prepareAttributesToDelete(string $attribute) : array
320-
{
321-
$result = [];
322-
if ($attribute !== "") {
323-
if (str_contains($attribute, ',')) {
324-
$result = explode(',', $attribute);
325-
} else {
326-
$result[] = $attribute;
327-
}
328-
$result = array_unique($result);
329-
}
330-
return $result;
331-
}
332-
333302
/**
334303
* Adds a complex success message if email confirmation is required
335304
*
@@ -484,38 +453,4 @@ private function disableAddressValidation($customer)
484453
$addressModel->setShouldIgnoreValidation(true);
485454
}
486455
}
487-
488-
/**
489-
* Removes file attribute from customer entity and file from filesystem
490-
*
491-
* @param CustomerInterface $customerCandidateDataObject
492-
* @param string $attributeToDelete
493-
* @return void
494-
* @throws FileSystemException
495-
*/
496-
private function deleteCustomerFileAttribute(
497-
CustomerInterface $customerCandidateDataObject,
498-
string $attributeToDelete
499-
) : void {
500-
if ($attributeToDelete !== '') {
501-
$attributes = $this->prepareAttributesToDelete($attributeToDelete);
502-
foreach ($attributes as $attr) {
503-
$attributeValue = $customerCandidateDataObject->getCustomAttribute($attr);
504-
if ($attributeValue!== null) {
505-
if ($attributeValue->getValue() !== '') {
506-
$mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
507-
$fileName = $attributeValue->getValue();
508-
$path = $mediaDirectory->getAbsolutePath('customer' . $fileName);
509-
if ($fileName && $mediaDirectory->isFile($path)) {
510-
$mediaDirectory->delete($path);
511-
}
512-
$customerCandidateDataObject->setCustomAttribute(
513-
$attr,
514-
''
515-
);
516-
}
517-
}
518-
}
519-
}
520-
}
521456
}

app/code/Magento/Customer/Model/Metadata/Form/File.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ public function compactValue($value)
314314
// Remove outdated file (in the case of file uploader UI component)
315315
if (!empty($this->_value)
316316
&& (!empty($value['delete'])
317-
|| ($this->_entityTypeCode == 'customer' && empty($value)))
317+
|| ($this->_entityTypeCode === 'customer' && empty($value)))
318318
) {
319319
$this->fileProcessor->removeUploadedFile($this->_value);
320320
return $value;

app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public function testExecute()
240240
->willReturn($customer);
241241

242242
$attr = 'attr1';
243-
$this->request->expects($this->exactly(5))
243+
$this->request->expects($this->exactly(3))
244244
->method('getParam')
245245
->willReturnCallback(
246246
function ($arg) use ($attr) {

app/code/Magento/Downloadable/view/adminhtml/templates/sales/items/column/downloadable/name.phtml

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,28 @@
1010

1111
<?php
1212
/** @var \Magento\Catalog\Helper\Data $catalogHelper */
13+
/** @var \Magento\Framework\Escaper $escaper */
1314
$catalogHelper = $block->getData('catalogHelper');
1415
if ($_item = $block->getItem()): ?>
15-
<div class="product-title"><?= $block->escapeHtml($_item->getName()) ?></div>
16+
<div class="product-title"><?= $escaper->escapeHtml($_item->getName()) ?></div>
1617
<div class="product-sku-block">
17-
<span><?= $block->escapeHtml(__('SKU')) ?>:</span>
18-
<?= /* @noEscape */ implode('<br />', $catalogHelper->splitSku($block->getSku())) ?>
18+
<span><?= $escaper->escapeHtml(__('SKU')) ?>:</span>
19+
<?= /* @noEscape */ implode('<br />', $catalogHelper->splitSku($escaper->escapeHtml($block->getSku()))) ?>
1920
</div>
2021
<?php if ($block->getOrderOptions()): ?>
2122
<dl class="item-options">
2223
<?php foreach ($block->getOrderOptions() as $_option): ?>
23-
<dt><?= $block->escapeHtml($_option['label']) ?>:</dt>
24+
<dt><?= $escaper->escapeHtml($_option['label']) ?>:</dt>
2425
<dd>
2526
<?php if (isset($_option['custom_view']) && $_option['custom_view']): ?>
26-
<?= $block->escapeHtml($_option['value']) ?>
27+
<?= $escaper->escapeHtml($_option['value']) ?>
2728
<?php else: ?>
28-
<?= $block->escapeHtml($block->truncateString($_option['value'], 55, '', $_remainder)) ?>
29+
<?= $escaper->escapeHtml($block->truncateString($_option['value'], 55, '', $_remainder)) ?>
2930
<?php if ($_remainder):?>
30-
... <span id="<?= $block->escapeHtmlAttr($_id = 'id' . uniqid()) ?>">
31-
<?= $block->escapeHtml($_remainder) ?>
31+
... <span id="<?= $escaper->escapeHtmlAttr($_id = 'id' . uniqid()) ?>">
32+
<?= $escaper->escapeHtml($_remainder) ?>
3233
</span>
33-
<?php $escapedId = /* @noEscape */ $block->escapeJs($_id);
34+
<?php $escapedId = /* @noEscape */ $escaper->escapeJs($_id);
3435
$scriptString = <<<script
3536
require(['prototype'], function(){
3637
$('{$escapedId}').hide();
@@ -48,14 +49,14 @@ script;
4849
<?php endif; ?>
4950
<?php if ($block->getLinks()): ?>
5051
<dl class="item-options">
51-
<dt><?= $block->escapeHtml($block->getLinksTitle()) ?>:</dt>
52+
<dt><?= $escaper->escapeHtml($block->getLinksTitle()) ?>:</dt>
5253
<?php foreach ($block->getLinks()->getPurchasedItems() as $_link): ?>
53-
<dd><?= $block->escapeHtml($_link->getLinkTitle()) ?>
54-
(<?= $block->escapeHtml($_link->getNumberOfDownloadsUsed() . ' / ' .
54+
<dd><?= $escaper->escapeHtml($_link->getLinkTitle()) ?>
55+
(<?= $escaper->escapeHtml($_link->getNumberOfDownloadsUsed() . ' / ' .
5556
($_link->getNumberOfDownloadsBought() ? $_link->getNumberOfDownloadsBought() : __('U'))) ?>)
5657
</dd>
5758
<?php endforeach; ?>
5859
</dl>
5960
<?php endif; ?>
60-
<?= $block->escapeHtml($_item->getDescription()) ?>
61+
<?= $escaper->escapeHtml($_item->getDescription()) ?>
6162
<?php endif; ?>

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

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,27 @@
77

88
namespace Magento\Quote\Model;
99

10+
use Magento\Customer\Api\AddressRepositoryInterface;
1011
use Magento\Framework\App\ObjectManager;
1112
use Magento\Framework\Exception\InputException;
1213
use Magento\Quote\Api\BillingAddressManagementInterface;
14+
use Magento\Quote\Api\CartRepositoryInterface;
1315
use Magento\Quote\Api\Data\AddressInterface;
1416
use Psr\Log\LoggerInterface as Logger;
1517

1618
/**
1719
* Quote billing address write service object.
20+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1821
*/
1922
class BillingAddressManagement implements BillingAddressManagementInterface
2023
{
24+
/**
25+
* Billing address lock const
26+
*
27+
* @var string
28+
*/
29+
private const CART_BILLING_ADDRESS_LOCK = 'cart_billing_address_lock_';
30+
2131
/**
2232
* Validator.
2333
*
@@ -35,12 +45,12 @@ class BillingAddressManagement implements BillingAddressManagementInterface
3545
/**
3646
* Quote repository object.
3747
*
38-
* @var \Magento\Quote\Api\CartRepositoryInterface
48+
* @var CartRepositoryInterface
3949
*/
4050
protected $quoteRepository;
4151

4252
/**
43-
* @var \Magento\Customer\Api\AddressRepositoryInterface
53+
* @var AddressRepositoryInterface
4454
*/
4555
protected $addressRepository;
4656

@@ -49,24 +59,33 @@ class BillingAddressManagement implements BillingAddressManagementInterface
4959
*/
5060
private $shippingAddressAssignment;
5161

62+
/**
63+
* @var CartAddressMutexInterface
64+
*/
65+
private $cartAddressMutex;
66+
5267
/**
5368
* Constructs a quote billing address service object.
5469
*
55-
* @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository Quote repository.
70+
* @param CartRepositoryInterface $quoteRepository Quote repository.
5671
* @param QuoteAddressValidator $addressValidator Address validator.
5772
* @param Logger $logger Logger.
58-
* @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository
73+
* @param AddressRepositoryInterface $addressRepository
74+
* @param CartAddressMutexInterface|null $cartAddressMutex
5975
*/
6076
public function __construct(
61-
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
77+
CartRepositoryInterface $quoteRepository,
6278
QuoteAddressValidator $addressValidator,
6379
Logger $logger,
64-
\Magento\Customer\Api\AddressRepositoryInterface $addressRepository
80+
AddressRepositoryInterface $addressRepository,
81+
?CartAddressMutexInterface $cartAddressMutex = null
6582
) {
6683
$this->addressValidator = $addressValidator;
6784
$this->logger = $logger;
6885
$this->quoteRepository = $quoteRepository;
6986
$this->addressRepository = $addressRepository;
87+
$this->cartAddressMutex = $cartAddressMutex ??
88+
ObjectManager::getInstance()->get(CartAddressMutex::class);
7089
}
7190

7291
/**
@@ -75,8 +94,29 @@ public function __construct(
7594
*/
7695
public function assign($cartId, AddressInterface $address, $useForShipping = false)
7796
{
78-
/** @var \Magento\Quote\Model\Quote $quote */
97+
/** @var Quote $quote */
7998
$quote = $this->quoteRepository->getActive($cartId);
99+
$billingAddressId = (int) $quote->getBillingAddress()->getId();
100+
101+
return $this->cartAddressMutex->execute(
102+
self::CART_BILLING_ADDRESS_LOCK.$billingAddressId,
103+
$this->assignBillingAddress(...),
104+
$billingAddressId,
105+
[$address, $quote, $useForShipping]
106+
);
107+
}
108+
109+
/**
110+
* Assign billing address to cart
111+
*
112+
* @param AddressInterface $address
113+
* @param Quote $quote
114+
* @param bool $useForShipping
115+
* @return mixed
116+
* @throws InputException
117+
*/
118+
private function assignBillingAddress(AddressInterface $address, Quote $quote, bool $useForShipping = false)
119+
{
80120
$address->setCustomerId($quote->getCustomerId());
81121
$quote->removeAddress($quote->getBillingAddress()->getId());
82122
$quote->setBillingAddress($address);
@@ -85,9 +125,10 @@ public function assign($cartId, AddressInterface $address, $useForShipping = fal
85125
$quote->setDataChanges(true);
86126
$this->quoteRepository->save($quote);
87127
} catch (\Exception $e) {
88-
$this->logger->critical($e);
128+
$this->logger->critical($e->getMessage());
89129
throw new InputException(__('The address failed to save. Verify the address and try again.'));
90130
}
131+
91132
return $quote->getBillingAddress()->getId();
92133
}
93134

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\Quote\Model;
20+
21+
use Magento\Framework\Lock\LockManagerInterface;
22+
23+
/**
24+
* @inheritDoc
25+
*/
26+
class CartAddressMutex implements CartAddressMutexInterface
27+
{
28+
/**
29+
* @var LockManagerInterface
30+
*/
31+
private $lockManager;
32+
33+
/**
34+
* @param LockManagerInterface $lockManager
35+
*/
36+
public function __construct(
37+
LockManagerInterface $lockManager,
38+
) {
39+
$this->lockManager = $lockManager;
40+
}
41+
42+
/**
43+
* @inheritDoc
44+
*/
45+
public function execute(string $lockName, callable $callable, int $result, array $args = [])
46+
{
47+
if (!$this->lockManager->lock($lockName, 0)) {
48+
return $result;
49+
}
50+
try {
51+
$result = $callable(...$args);
52+
} finally {
53+
$this->lockManager->unlock($lockName);
54+
}
55+
56+
return $result;
57+
}
58+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\Quote\Model;
20+
21+
/**
22+
* Intended to prevent race conditions during quote address processing by concurrent requests.
23+
*/
24+
interface CartAddressMutexInterface
25+
{
26+
/**
27+
* Acquires a lock for quote address, executes callable and releases the lock after.
28+
*
29+
* @param string $lockName
30+
* @param callable $callable
31+
* @param int $result
32+
* @param array $args
33+
* @return mixed
34+
*/
35+
public function execute(string $lockName, callable $callable, int $result, array $args = []);
36+
}

0 commit comments

Comments
 (0)