Skip to content

Commit ecd889d

Browse files
Roman HaninRoman Hanin
Roman Hanin
authored and
Roman Hanin
committed
Merge branch '2.4-develop' of https://github.com/magento/magento2ce into B2B-1780
2 parents 336f29a + ed5c06d commit ecd889d

File tree

164 files changed

+5050
-1174
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+5050
-1174
lines changed

app/code/Magento/Backup/Model/Fs/Collection.php

Lines changed: 9 additions & 2 deletions
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\Backup\Model\Fs;
79

810
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -92,12 +94,17 @@ public function __construct(
9294
* Create .htaccess file and deny backups directory access from web
9395
*
9496
* @return void
97+
* @throws \Magento\Framework\Exception\FileSystemException
9598
*/
9699
protected function _hideBackupsForApache()
97100
{
98101
$filename = '.htaccess';
99-
if (!$this->_varDirectory->isFile($filename)) {
100-
$this->_varDirectory->writeFile($filename, 'deny from all');
102+
$driver = $this->_varDirectory->getDriver();
103+
$absolutePath = $driver->getAbsolutePath($this->_varDirectory->getAbsolutePath(), $filename);
104+
if (!$driver->isFile($absolutePath)) {
105+
$resource = $driver->fileOpen($absolutePath, 'w+');
106+
$driver->fileWrite($resource, 'deny from all');
107+
$driver->fileClose($resource);
101108
}
102109
}
103110

app/code/Magento/Backup/Test/Unit/Model/Fs/CollectionTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,15 @@ public function testConstructor()
3434
)->disableOriginalConstructor()
3535
->getMock();
3636
$backupData->expects($this->any())->method('getExtensions')->willReturn([]);
37-
37+
$driver = $this->getMockBuilder(
38+
Filesystem\DriverInterface::class
39+
)->disableOriginalConstructor()
40+
->getMock();
3841
$directoryWrite->expects($this->any())->method('create')->with('backups');
39-
$directoryWrite->expects($this->any())->method('getAbsolutePath')->with('backups');
42+
$directoryWrite->expects($this->any())->method('getAbsolutePath')->willReturn('');
43+
$directoryWrite->expects($this->at(3))->method('getAbsolutePath')->with('backups');
4044
$directoryWrite->expects($this->any())->method('isDirectory')->willReturn(true);
45+
$directoryWrite->expects($this->any())->method('getDriver')->willReturn($driver);
4146
$targetDirectory = $this->getMockBuilder(TargetDirectory::class)
4247
->disableOriginalConstructor()
4348
->getMock();

app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,10 @@ public function execute()
108108

109109
$result['url'] = $this->productMediaConfig->getTmpMediaUrl($result['file']);
110110
$result['file'] = $result['file'] . '.tmp';
111-
} catch (\Exception $e) {
111+
} catch (LocalizedException $e) {
112112
$result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
113+
} catch (\Throwable $e) {
114+
$result = ['error' => 'Something went wrong while saving the file(s).', 'errorcode' => 0];
113115
}
114116

115117
/** @var \Magento\Framework\Controller\Result\Raw $response */

app/code/Magento/Catalog/Model/Product.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,8 +883,8 @@ public function beforeSave()
883883

884884
$this->getTypeInstance()->beforeSave($this);
885885

886-
$hasOptions = $this->getData('has_options') === "1";
887-
$hasRequiredOptions = $this->getData('required_options') === "1";
886+
$hasOptions = $this->getData('has_options') === "1" && $this->isProductHasOptions();
887+
$hasRequiredOptions = $this->getData('required_options') === "1" && $this->isProductHasOptions();
888888

889889
/**
890890
* $this->_canAffectOptions - set by type instance only
@@ -934,6 +934,21 @@ public function beforeSave()
934934
parent::beforeSave();
935935
}
936936

937+
/**
938+
* Check based on options data
939+
*
940+
* @return bool
941+
*/
942+
private function isProductHasOptions() : bool
943+
{
944+
if ($this->getData('options') === null) {
945+
$result = true;
946+
} else {
947+
$result = is_array($this->getData('options')) && count($this->getData('options')) > 0;
948+
}
949+
return $result;
950+
}
951+
937952
/**
938953
* Check/set if options can be affected when saving product
939954
*

app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php

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

78
namespace Magento\Catalog\Model\Product\Option\Type\File;
89

910
use Magento\Catalog\Model\Product;
10-
use Magento\Framework\App\Filesystem\DirectoryList;
1111
use Magento\Catalog\Model\Product\Exception as ProductException;
12+
use Magento\Framework\App\Filesystem\DirectoryList;
13+
use Magento\Framework\App\ObjectManager;
1214
use Magento\Framework\Exception\LocalizedException;
1315
use Magento\Framework\Math\Random;
14-
use Magento\Framework\App\ObjectManager;
1516
use Magento\MediaStorage\Model\File\Uploader;
1617

1718
/**
@@ -254,8 +255,12 @@ protected function initFilesystem()
254255

255256
// Directory listing and hotlink secure
256257
$path = $this->path . '/.htaccess';
257-
if (!$this->mediaDirectory->isFile($path)) {
258-
$this->mediaDirectory->writeFile($path, "Order deny,allow\nDeny from all");
258+
$driver = $this->mediaDirectory->getDriver();
259+
$absolutePath = $driver->getAbsolutePath($this->mediaDirectory->getAbsolutePath(), $path);
260+
if (!$driver->isFile($absolutePath)) {
261+
$resource = $driver->fileOpen($absolutePath, 'w+');
262+
$driver->fileWrite($resource, "Order deny,allow\nDeny from all");
263+
$driver->fileClose($resource);
259264
}
260265
}
261266

app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@
66

77
namespace Magento\Catalog\Model\Product\Option\Type\File;
88

9+
use Magento\Framework\App\Config\ScopeConfigInterface;
10+
use Magento\Framework\Exception\InputException;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\File\Size;
13+
use Magento\Framework\Filesystem;
14+
use Magento\Framework\Filesystem\Io\File as IoFile;
15+
use Magento\MediaStorage\Helper\File\Storage\Database;
16+
use Magento\MediaStorage\Model\File\Validator\NotProtectedExtension;
17+
918
/**
1019
* Validator for existing files.
1120
*/
1221
class ValidatorInfo extends Validator
1322
{
1423
/**
15-
* @var \Magento\MediaStorage\Helper\File\Storage\Database
24+
* @var Database
1625
*/
1726
protected $coreFileStorageDatabase;
1827

@@ -36,24 +45,39 @@ class ValidatorInfo extends Validator
3645
*/
3746
protected $fileRelativePath;
3847

48+
/**
49+
* @var IoFile
50+
*/
51+
private $ioFile;
52+
/**
53+
* @var NotProtectedExtension
54+
*/
55+
private $fileValidator;
56+
3957
/**
4058
* Construct method
4159
*
42-
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
43-
* @param \Magento\Framework\Filesystem $filesystem
44-
* @param \Magento\Framework\File\Size $fileSize
45-
* @param \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase
60+
* @param ScopeConfigInterface $scopeConfig
61+
* @param Filesystem $filesystem
62+
* @param Size $fileSize
63+
* @param Database $coreFileStorageDatabase
4664
* @param ValidateFactory $validateFactory
65+
* @param NotProtectedExtension $fileValidator
66+
* @param IoFile $ioFile
4767
*/
4868
public function __construct(
49-
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
50-
\Magento\Framework\Filesystem $filesystem,
51-
\Magento\Framework\File\Size $fileSize,
52-
\Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase,
53-
\Magento\Catalog\Model\Product\Option\Type\File\ValidateFactory $validateFactory
69+
ScopeConfigInterface $scopeConfig,
70+
Filesystem $filesystem,
71+
Size $fileSize,
72+
Database $coreFileStorageDatabase,
73+
ValidateFactory $validateFactory,
74+
NotProtectedExtension $fileValidator,
75+
IoFile $ioFile
5476
) {
5577
$this->coreFileStorageDatabase = $coreFileStorageDatabase;
5678
$this->validateFactory = $validateFactory;
79+
$this->fileValidator = $fileValidator;
80+
$this->ioFile = $ioFile;
5781
parent::__construct($scopeConfig, $filesystem, $fileSize);
5882
}
5983

@@ -94,27 +118,42 @@ public function validate($optionValue, $option)
94118
$validatorChain = $this->validateFactory->create();
95119
try {
96120
$validatorChain = $this->buildImageValidator($validatorChain, $option, $this->fileFullPath);
97-
} catch (\Magento\Framework\Exception\InputException $notImage) {
121+
} catch (InputException $notImage) {
98122
return false;
99123
}
100124

101-
$result = false;
102-
if ($validatorChain->isValid($this->fileFullPath, $optionValue['title'])) {
103-
$result = $this->rootDirectory->isReadable($this->fileRelativePath)
125+
if ($this->validatePath($optionValue) && $validatorChain->isValid($this->fileFullPath, $optionValue['title'])) {
126+
return $this->rootDirectory->isReadable($this->fileRelativePath)
104127
&& isset($optionValue['secret_key'])
105128
&& $this->buildSecretKey($this->fileRelativePath) == $optionValue['secret_key'];
106-
} elseif ($validatorChain->getErrors()) {
129+
} else {
107130
$errors = $this->getValidatorErrors($validatorChain->getErrors(), $optionValue, $option);
108-
109131
if (count($errors) > 0) {
110-
throw new \Magento\Framework\Exception\LocalizedException(__(implode("\n", $errors)));
132+
throw new LocalizedException(__(implode("\n", $errors)));
111133
}
112-
} else {
113-
throw new \Magento\Framework\Exception\LocalizedException(
134+
throw new LocalizedException(
114135
__("The product's required option(s) weren't entered. Make sure the options are entered and try again.")
115136
);
116137
}
117-
return $result;
138+
}
139+
140+
/**
141+
* Validate quote_path and order_path.
142+
*
143+
* @param array $optionValuePath
144+
* @return bool
145+
*/
146+
private function validatePath(array $optionValuePath): bool
147+
{
148+
foreach ([$optionValuePath['quote_path'], $optionValuePath['order_path']] as $path) {
149+
$pathInfo = $this->ioFile->getPathInfo($path);
150+
if (isset($pathInfo['extension'])) {
151+
if (!$this->fileValidator->isValid($pathInfo['extension'])) {
152+
return false;
153+
}
154+
}
155+
}
156+
return true;
118157
}
119158

120159
/**

app/code/Magento/Catalog/Test/Mftf/Section/AdminAddProductsToOptionPanelSection.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
* See COPYING.txt for license details.
66
*/
77
-->
8-
98
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
109
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
1110
<section name="AdminAddProductsToOptionPanel">
@@ -16,4 +15,4 @@
1615
<element name="firstCheckbox" type="input" selector="//tr[1]//input[@data-action='select-row']"/>
1716
<element name="nthCheckbox" type="input" selector="//tr[{{var}}]//input[@data-action='select-row']" parameterized="true"/>
1817
</section>
19-
</sections>
18+
</sections>

app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,21 @@ public function testSaveWithProvidedRequiredOptions()
11131113
$this->assertTrue($this->model->getRequiredOptions());
11141114
}
11151115

1116+
/**
1117+
* Test for save method with provided options settled via magic method
1118+
*/
1119+
public function testSaveWithProvidedRequiredOptionsValue()
1120+
{
1121+
$this->model->setHasOptions("1");
1122+
$this->model->setRequiredOptions("1");
1123+
$this->model->setData("options", null);
1124+
$this->configureSaveTest();
1125+
$this->model->beforeSave();
1126+
$this->model->afterSave();
1127+
$this->assertTrue($this->model->getHasOptions());
1128+
$this->assertTrue($this->model->getRequiredOptions());
1129+
}
1130+
11161131
public function testGetIsSalableSimple()
11171132
{
11181133
$typeInstanceMock =

app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public function validate(Observer $observer)
185185
* Check item for options
186186
*/
187187
if ($options) {
188-
$qty = $product->getTypeInstance()->prepareQuoteItemQty($qty, $product);
188+
$qty = $product->getTypeInstance()->prepareQuoteItemQty($quoteItem->getQty(), $product);
189189
$quoteItem->setData('qty', $qty);
190190
if ($stockStatus) {
191191
$this->checkOptionsQtyIncrements($quoteItem, $options);

app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/Initializer/Option.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public function initialize(
120120
/**
121121
* if option's qty was updates we also need to update quote item qty
122122
*/
123-
$quoteItem->setData('qty', (int) $qty);
123+
$quoteItem->setData('qty', (int) $result->getItemQty());
124124
}
125125
if ($result->getMessage() !== null) {
126126
$option->setMessage($result->getMessage());

app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/OptionTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ protected function setUp(): void
125125
);
126126
$this->resultMock = $this->getMockBuilder(DataObject::class)
127127
->addMethods(
128-
['getItemIsQtyDecimal', 'getHasQtyOptionUpdate', 'getOrigQty', 'getMessage', 'getItemBackorders']
128+
['getItemIsQtyDecimal', 'getHasQtyOptionUpdate', 'getOrigQty', 'getMessage', 'getItemBackorders', 'getItemQty']
129129
)
130130
->disableOriginalConstructor()
131131
->getMock();
@@ -217,6 +217,7 @@ public function testInitializeWhenResultIsDecimalGetBackordersMessageHasOptionQt
217217
$this->optionMock->expects($this->once())->method('setBackorders')->with('backorders');
218218

219219
$this->stockItemMock->expects($this->once())->method('unsIsChildItem');
220+
$this->resultMock->expects($this->once())->method('getItemQty')->willReturn($qty);
220221
$this->validator->initialize($this->optionMock, $this->quoteItemMock, $qty);
221222
}
222223

app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/QuantityValidatorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ private function createInitialStub($qty)
564564
$this->quoteItemMock->expects($this->any())
565565
->method('getQuote')
566566
->willReturn($this->quoteMock);
567-
$this->quoteItemMock->expects($this->once())
567+
$this->quoteItemMock->expects($this->any())
568568
->method('getQty')
569569
->willReturn($qty);
570570
$this->quoteItemMock->expects($this->any())

app/code/Magento/Cms/Controller/Adminhtml/Page/PostDataProcessor.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\App\ObjectManager;
1111
use Magento\Framework\Config\Dom\ValidationException;
1212
use Magento\Framework\Config\Dom\ValidationSchemaException;
13+
use Magento\Cms\Model\Page\CustomLayout\CustomLayoutValidator;
1314

1415
/**
1516
* Controller helper for user input.
@@ -36,23 +37,32 @@ class PostDataProcessor
3637
*/
3738
private $validationState;
3839

40+
/**
41+
* @var CustomLayoutValidator
42+
*/
43+
private $customLayoutValidator;
44+
3945
/**
4046
* @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
4147
* @param \Magento\Framework\Message\ManagerInterface $messageManager
4248
* @param \Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory
43-
* @param DomValidationState $validationState
49+
* @param DomValidationState|null $validationState
50+
* @param CustomLayoutValidator|null $customLayoutValidator
4451
*/
4552
public function __construct(
4653
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
4754
\Magento\Framework\Message\ManagerInterface $messageManager,
4855
\Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory,
49-
DomValidationState $validationState = null
56+
DomValidationState $validationState = null,
57+
CustomLayoutValidator $customLayoutValidator = null
5058
) {
5159
$this->dateFilter = $dateFilter;
5260
$this->messageManager = $messageManager;
5361
$this->validatorFactory = $validatorFactory;
5462
$this->validationState = $validationState
5563
?: ObjectManager::getInstance()->get(DomValidationState::class);
64+
$this->customLayoutValidator = $customLayoutValidator
65+
?: ObjectManager::getInstance()->get(CustomLayoutValidator::class);
5666
}
5767

5868
/**
@@ -146,6 +156,9 @@ private function validateData($data, $layoutXmlValidator)
146156
) {
147157
return false;
148158
}
159+
if (!$this->customLayoutValidator->validate($data)) {
160+
return false;
161+
}
149162
} catch (ValidationException $e) {
150163
return false;
151164
} catch (ValidationSchemaException $e) {

0 commit comments

Comments
 (0)