Skip to content

Commit 84996bb

Browse files
Merge pull request #8805 from magento-cia/cia-2.4.7-develop-bugfix-03012024
Cia 2.4.7 develop bugfix 03012024
2 parents 7fe2777 + 0aad7c2 commit 84996bb

File tree

9 files changed

+167
-42
lines changed

9 files changed

+167
-42
lines changed

app/code/Magento/Config/Model/Config/Backend/File.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Config\Model\Config\Backend;
79

810
use Exception;
@@ -114,7 +116,7 @@ public function beforeSave()
114116
if (is_array($value) && !empty($value['delete'])) {
115117
$this->setValue('');
116118
} elseif (is_array($value) && !empty($value['value'])) {
117-
$this->setValue($value['value']);
119+
$this->setValueAfterValidation($value['value']);
118120
} else {
119121
$this->unsValue();
120122
}
@@ -266,4 +268,21 @@ protected function _getAllowedExtensions()
266268
{
267269
return [];
268270
}
271+
272+
/**
273+
* Validate if the value is intercepted
274+
*
275+
* @param string $value
276+
* @return void
277+
* @throws LocalizedException
278+
*/
279+
private function setValueAfterValidation(string $value): void
280+
{
281+
// avoid intercepting value
282+
if (preg_match('/[^a-z0-9_\/\\-\\.]+/i', $value)) {
283+
throw new LocalizedException(__('Invalid file name'));
284+
}
285+
286+
$this->setValue($value);
287+
}
269288
}

app/code/Magento/Config/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,4 @@ Dashboard,Dashboard
122122
"Web Section","Web Section"
123123
"Store Email Addresses Section","Store Email Addresses Section"
124124
"Email to a Friend","Email to a Friend"
125+
"Invalid file name", "Invalid file name"

app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
7+
declare(strict_types=1);
8+
69
namespace Magento\Customer\Model\ResourceModel;
710

811
use Magento\Customer\Api\CustomerMetadataInterface;
@@ -27,6 +30,7 @@
2730
use Magento\Framework\Api\SearchCriteriaInterface;
2831
use Magento\Framework\App\ObjectManager;
2932
use Magento\Framework\Event\ManagerInterface;
33+
use Magento\Framework\Exception\InputException;
3034
use Magento\Framework\Exception\LocalizedException;
3135
use Magento\Framework\Exception\NoSuchEntityException;
3236
use Magento\Store\Model\StoreManagerInterface;
@@ -195,12 +199,19 @@ public function __construct(
195199
* @throws \Magento\Framework\Exception\LocalizedException
196200
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
197201
* @SuppressWarnings(PHPMD.NPathComplexity)
202+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
198203
*/
199204
public function save(CustomerInterface $customer, $passwordHash = null)
200205
{
201206
/** @var NewOperation|null $delegatedNewOperation */
202207
$delegatedNewOperation = !$customer->getId() ? $this->delegatedStorage->consumeNewOperation() : null;
203208
$prevCustomerData = $prevCustomerDataArr = null;
209+
if ($customer->getDefaultBilling()) {
210+
$this->validateDefaultAddress($customer, CustomerInterface::DEFAULT_BILLING);
211+
}
212+
if ($customer->getDefaultShipping()) {
213+
$this->validateDefaultAddress($customer, CustomerInterface::DEFAULT_SHIPPING);
214+
}
204215
if ($customer->getId()) {
205216
$prevCustomerData = $this->getById($customer->getId());
206217
$prevCustomerDataArr = $this->prepareCustomerData($prevCustomerData->__toArray());
@@ -228,7 +239,7 @@ public function save(CustomerInterface $customer, $passwordHash = null)
228239
$prevCustomerData ? $prevCustomerData->getStoreId() : $this->storeManager->getStore()->getId()
229240
);
230241
}
231-
$this->validateGroupId($customer->getGroupId());
242+
$this->validateGroupId((int)$customer->getGroupId());
232243
$this->setCustomerGroupId($customerModel, $customerArr, $prevCustomerDataArr);
233244
// Need to use attribute set or future updates can cause data loss
234245
if (!$customerModel->getAttributeSetId()) {
@@ -553,4 +564,34 @@ private function prepareCustomerData(array $customerData): array
553564
}
554565
return $customerData;
555566
}
567+
568+
/**
569+
* To validate default address
570+
*
571+
* @param CustomerInterface $customer
572+
* @param string $defaultAddressType
573+
* @return void
574+
* @throws InputException
575+
*/
576+
private function validateDefaultAddress(
577+
CustomerInterface $customer,
578+
string $defaultAddressType
579+
): void {
580+
$addressId = $defaultAddressType === CustomerInterface::DEFAULT_BILLING ? $customer->getDefaultBilling()
581+
: $customer->getDefaultShipping();
582+
if ($customer->getAddresses()) {
583+
foreach ($customer->getAddresses() as $address) {
584+
if ((int) $addressId === (int) $address->getId()) {
585+
return;
586+
}
587+
}
588+
589+
throw new InputException(
590+
__(
591+
'The %fieldName value is invalid. Set the correct value and try again.',
592+
['fieldName' => $defaultAddressType]
593+
)
594+
);
595+
}
596+
}
556597
}

dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ public function testActivateCustomer()
265265
$customerData[Customer::ID],
266266
[
267267
'id' => $customerData[Customer::ID],
268+
'addresses' => $customerData[Customer::KEY_ADDRESSES],
268269
'confirmation' => CustomerHelper::CONFIRMATION
269270
]
270271
);

dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,8 @@ public function testCreateNewCustomerWithPasswordHashWithNotAllowedCountry(): vo
421421
$customerData = $this->customerRepository->getById($customerId);
422422
$customerData->getAddresses()[1]->setRegion(null)->setCountryId($allowedCountryIdForSecondWebsite)
423423
->setRegionId(null);
424+
$customerData->getAddresses()[1]->setIsDefaultBilling(true);
425+
$customerData->getAddresses()[1]->setIsDefaultShipping(true);
424426
$customerData->setStoreId($store->getId())->setWebsiteId($store->getWebsiteId())->setId(null);
425427
$password = $this->random->getRandomString(8);
426428
$passwordHash = $this->encryptor->getHash($password, true);

dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public function testSameAsBillingWhenCustomerHasNoDefaultShippingAddress($unsetI
172172
/** @var AddressRepositoryInterface $addressRepository */
173173
$addressRepository = Bootstrap::getObjectManager()
174174
->create(AddressRepositoryInterface::class);
175-
$this->_customer->setDefaultShipping(-1)
175+
$this->_customer->setDefaultShipping(1)
176176
->setAddresses(
177177
[
178178
$addressRepository->getById($this->_address->getId()),
@@ -211,7 +211,7 @@ public function testSameAsBillingWhenCustomerHasDefaultShippingAddress()
211211
/** @var AddressRepositoryInterface $addressRepository */
212212
$addressRepository = Bootstrap::getObjectManager()
213213
->create(AddressRepositoryInterface::class);
214-
$this->_customer->setDefaultShipping(2)
214+
$this->_customer->setDefaultShipping(1)
215215
->setAddresses([$addressRepository->getById($this->_address->getId())]);
216216
$this->_customer = $this->customerRepository->save($this->_customer);
217217
// we should save the customer data in order to be able to use it

lib/internal/Magento/Framework/Data/Form/Element/Image.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,30 +71,27 @@ public function getElementHtml()
7171
{
7272
$html = '';
7373

74-
if ((string)$this->getValue()) {
74+
if ((string)$this->getEscapedValue()) {
7575
$url = $this->_getUrl();
7676

7777
if (!preg_match("/^http\:\/\/|https\:\/\//", $url)) {
7878
$url = $this->_urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]) . $url;
7979
}
8080

8181
$linkId = 'linkId' .$this->random->getRandomString(8);
82-
$html = '<a previewlinkid="' .$linkId .'" href="' .
83-
$url .
84-
'" ' .
82+
$html = '<a previewlinkid="' .$linkId .'" href="' .
83+
$url . '" ' .
8584
$this->_getUiId(
8685
'link'
8786
) .
8887
'>' .
89-
'<img src="' .
90-
$url .
91-
'" id="' .
88+
'<img src="' . $url . '" id="' .
9289
$this->getHtmlId() .
9390
'_image" title="' .
94-
$this->getValue() .
91+
$this->getEscapedValue() .
9592
'"' .
9693
' alt="' .
97-
$this->getValue() .
94+
$this->getEscapedValue() .
9895
'" height="22" width="22" class="small-image-preview v-middle" ' .
9996
$this->_getUiId() .
10097
' />' .
@@ -120,7 +117,7 @@ public function getElementHtml()
120117
protected function _getDeleteCheckbox()
121118
{
122119
$html = '';
123-
if ($this->getValue()) {
120+
if ($this->getEscapedValue()) {
124121
$label = (string)new \Magento\Framework\Phrase('Delete Image');
125122
$html .= '<span class="delete-image">';
126123
$html .= '<input type="checkbox"' .
@@ -153,7 +150,8 @@ protected function _getDeleteCheckbox()
153150
*/
154151
protected function _getHiddenInput()
155152
{
156-
return '<input type="hidden" name="' . parent::getName() . '[value]" value="' . $this->getValue() . '" />';
153+
return '<input type="hidden" name="' . parent::getName() .
154+
'[value]" value="' . $this->getEscapedValue() . '" />';
157155
}
158156

159157
/**
@@ -163,7 +161,7 @@ protected function _getHiddenInput()
163161
*/
164162
protected function _getUrl()
165163
{
166-
return $this->getValue();
164+
return $this->getEscapedValue();
167165
}
168166

169167
/**

lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/ImageTest.php

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
use Magento\Framework\Data\Form\Element\Image;
1616
use Magento\Framework\DataObject;
1717
use Magento\Framework\Escaper;
18+
use Magento\Framework\Math\Random;
19+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1820
use Magento\Framework\Url;
19-
use Magento\Framework\UrlInterface;
21+
use Magento\Framework\View\Helper\SecureHtmlRenderer;
2022
use PHPUnit\Framework\MockObject\MockObject;
2123
use PHPUnit\Framework\TestCase;
22-
use Magento\Framework\Math\Random;
23-
use Magento\Framework\View\Helper\SecureHtmlRenderer;
24+
use Magento\Framework\UrlInterface;
2425

2526
/**
2627
* Test for the widget.
@@ -44,11 +45,16 @@ class ImageTest extends TestCase
4445
*/
4546
protected $_image;
4647

48+
/**
49+
* @var array
50+
*/
51+
protected $testData;
52+
4753
protected function setUp(): void
4854
{
55+
$objectManager = new ObjectManager($this);
4956
$factoryMock = $this->createMock(Factory::class);
5057
$collectionFactoryMock = $this->createMock(CollectionFactory::class);
51-
$escaperMock = $this->createMock(Escaper::class);
5258
$this->urlBuilder = $this->createMock(Url::class);
5359
$randomMock = $this->createMock(Random::class);
5460
$randomMock->method('getRandomString')->willReturn('some-rando-string');
@@ -67,18 +73,28 @@ function (string $tag, array $attrs, ?string $content): string {
6773
return "<$tag {$attrs->serialize()}>$content</$tag>";
6874
}
6975
);
70-
$this->_image = new Image(
71-
$factoryMock,
72-
$collectionFactoryMock,
73-
$escaperMock,
74-
$this->urlBuilder,
75-
[],
76-
$secureRendererMock,
77-
$randomMock
76+
$this->_image = $objectManager->getObject(
77+
Image::class,
78+
[
79+
'factoryMock'=>$factoryMock,
80+
'collectionFactoryMock'=>$collectionFactoryMock,
81+
'urlBuilder' => $this->urlBuilder,
82+
'_escaper' => $objectManager->getObject(Escaper::class),
83+
'random' => $randomMock,
84+
'secureRenderer' => $secureRendererMock,
85+
]
7886
);
87+
$this->testData = [
88+
'html_id_prefix' => 'test_id_prefix_',
89+
'html_id' => 'test_id',
90+
'html_id_suffix' => '_test_id_suffix',
91+
'path' => 'catalog/product/placeholder',
92+
'value' => 'test_value',
93+
];
94+
7995
$formMock = new DataObject();
80-
$formMock->getHtmlIdPrefix('id_prefix');
81-
$formMock->getHtmlIdPrefix('id_suffix');
96+
$formMock->getHtmlIdPrefix($this->testData['html_id_prefix']);
97+
$formMock->getHtmlIdPrefix($this->testData['html_id_suffix']);
8298
$this->_image->setForm($formMock);
8399
}
84100

@@ -117,21 +133,32 @@ public function testGetElementHtmlWithoutValue()
117133
*/
118134
public function testGetElementHtmlWithValue()
119135
{
120-
$this->_image->setValue('test_value');
121-
$this->urlBuilder->expects($this->once())
122-
->method('getBaseUrl')
123-
->with(['_type' => UrlInterface::URL_TYPE_MEDIA])
124-
->willReturn('http://localhost/media/');
136+
$url = 'http://test.example.com/media/';
137+
138+
$this->_image->setValue($this->testData['value']);
139+
$this->_image->setHtmlId($this->testData['html_id']);
140+
141+
$this->urlBuilder->expects($this->once())->method('getBaseUrl')
142+
->with(['_type' => UrlInterface::URL_TYPE_MEDIA])->willReturn($url);
143+
144+
$expectedHtmlId = $this->testData['html_id'];
145+
125146
$html = $this->_image->getElementHtml();
147+
126148
$this->assertStringContainsString('class="input-file"', $html);
127149
$this->assertStringContainsString('<input', $html);
128150
$this->assertStringContainsString('type="file"', $html);
129151
$this->assertStringContainsString('value="test_value"', $html);
152+
130153
$this->assertStringContainsString(
131-
'<a previewlinkid="linkIdsome-rando-string" href="http://localhost/media/test_value"',
154+
'<a previewlinkid="linkIdsome-rando-string" href="'
155+
. $url
156+
. $this->testData['value']
157+
. '"',
132158
$html
133159
);
134-
$this->assertStringContainsString("imagePreview('_image');\nreturn false;", $html);
160+
161+
$this->assertStringContainsString("imagePreview('{$expectedHtmlId}_image');\nreturn false;", $html);
135162
$this->assertStringContainsString('<input type="checkbox"', $html);
136163
}
137164
}

0 commit comments

Comments
 (0)