Skip to content

Commit a77ff7c

Browse files
committed
Merge branch 'MC-41783' into cia-2.4.3-bugfixes-4272021
2 parents 5d41f19 + 4dabcc7 commit a77ff7c

File tree

4 files changed

+199
-80
lines changed

4 files changed

+199
-80
lines changed

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
/**

dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfoTest.php

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,58 +6,72 @@
66

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

9+
use Magento\Catalog\Model\Product\Media\Config;
10+
use Magento\Catalog\Model\Product\Option;
11+
use Magento\Framework\App\Filesystem\DirectoryList;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\File\Size;
14+
use Magento\Framework\Filesystem;
15+
use Magento\Framework\ObjectManagerInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use PHPUnit\Framework\TestCase;
18+
use PHPUnit\Framework\MockObject\MockObject;
19+
use Zend_Validate;
20+
use Zend_Validate_File_ExcludeExtension;
21+
use Zend_Validate_File_Extension;
22+
use Zend_Validate_File_FilesSize;
23+
use Zend_Validate_File_ImageSize;
24+
925
/**
10-
* @magentoDataFixture Magento/Catalog/_files/validate_image_info.php
26+
1127
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1228
*/
13-
class ValidatorInfoTest extends \PHPUnit\Framework\TestCase
29+
class ValidatorInfoTest extends TestCase
1430
{
1531
/**
1632
* @var ValidatorInfo
1733
*/
1834
protected $model;
1935

2036
/**
21-
* @var \Magento\Framework\ObjectManagerInterface
37+
* @var ObjectManagerInterface
2238
*/
2339
protected $objectManager;
2440

2541
/** @var int */
2642
protected $maxFileSizeInMb;
2743

2844
/**
29-
* @var \Magento\Catalog\Model\Product\Option\Type\File\ValidateFactory|\PHPUnit\Framework\MockObject\MockObject
45+
* @var ValidateFactory|MockObject
3046
*/
3147
protected $validateFactoryMock;
3248

3349
/**
34-
* {@inheritdoc}
50+
* @inheritdoc
3551
*/
3652
protected function setUp(): void
3753
{
38-
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
39-
/** @var \Magento\Framework\File\Size $fileSize */
40-
$fileSize = $this->objectManager->create(\Magento\Framework\File\Size::class);
54+
$this->objectManager = Bootstrap::getObjectManager();
55+
/** @var Size $fileSize */
56+
$fileSize = $this->objectManager->create(Size::class);
4157
$this->maxFileSizeInMb = $fileSize->getMaxFileSizeInMb();
4258

43-
$this->validateFactoryMock = $this->createPartialMock(
44-
\Magento\Catalog\Model\Product\Option\Type\File\ValidateFactory::class,
45-
['create']
46-
);
59+
$this->validateFactoryMock = $this->createPartialMock(ValidateFactory::class, ['create']);
4760
$this->model = $this->objectManager->create(
48-
\Magento\Catalog\Model\Product\Option\Type\File\ValidatorInfo::class,
61+
ValidatorInfo::class,
4962
[
5063
'validateFactory' => $this->validateFactoryMock,
5164
]
5265
);
5366
}
5467

5568
/**
69+
* @magentoDataFixture Magento/Catalog/_files/validate_image_info.php
5670
* @return void
5771
*/
58-
public function testExceptionWithErrors()
72+
public function testExceptionWithErrors(): void
5973
{
60-
$this->expectException(\Magento\Framework\Exception\LocalizedException::class);
74+
$this->expectException(LocalizedException::class);
6175
$this->expectExceptionMessage(
6276
"The file 'test.jpg' for 'MediaOption' has an invalid extension.\n"
6377
. "The file 'test.jpg' for 'MediaOption' has an invalid extension.\n"
@@ -68,70 +82,77 @@ public function testExceptionWithErrors()
6882
)
6983
);
7084

71-
$validateMock = $this->createPartialMock(\Zend_Validate::class, ['isValid', 'getErrors']);
85+
$validateMock = $this->createPartialMock(Zend_Validate::class, ['isValid', 'getErrors']);
7286
$validateMock->expects($this->once())->method('isValid')->willReturn(false);
73-
$validateMock->expects($this->exactly(2))->method('getErrors')->willReturn([
74-
\Zend_Validate_File_ExcludeExtension::FALSE_EXTENSION,
75-
\Zend_Validate_File_Extension::FALSE_EXTENSION,
76-
\Zend_Validate_File_ImageSize::WIDTH_TOO_BIG,
77-
\Zend_Validate_File_FilesSize::TOO_BIG,
87+
$validateMock->expects($this->exactly(1))->method('getErrors')->willReturn([
88+
Zend_Validate_File_ExcludeExtension::FALSE_EXTENSION,
89+
Zend_Validate_File_Extension::FALSE_EXTENSION,
90+
Zend_Validate_File_ImageSize::WIDTH_TOO_BIG,
91+
Zend_Validate_File_FilesSize::TOO_BIG,
7892
]);
79-
$this->validateFactoryMock->expects($this->once())
80-
->method('create')
81-
->willReturn($validateMock);
93+
$this->validateFactoryMock->expects($this->once())->method('create')->willReturn($validateMock);
8294

83-
$this->model->validate(
84-
$this->getOptionValue(),
85-
$this->getProductOption()
86-
);
95+
$this->model->validate($this->getOptionValue(), $this->getProductOption());
8796
}
8897

8998
/**
99+
* @magentoDataFixture Magento/Catalog/_files/validate_image_info.php
90100
* @return void
91101
*/
92-
public function testExceptionWithoutErrors()
102+
public function testExceptionWithoutErrors(): void
93103
{
94-
$this->expectException(\Magento\Framework\Exception\LocalizedException::class);
104+
$this->expectException(LocalizedException::class);
95105
$this->expectExceptionMessage(
96106
"The product's required option(s) weren't entered. Make sure the options are entered and try again."
97107
);
98108

99-
$validateMock = $this->createPartialMock(\Zend_Validate::class, ['isValid', 'getErrors']);
109+
$validateMock = $this->createPartialMock(Zend_Validate::class, ['isValid', 'getErrors']);
100110
$validateMock->expects($this->once())->method('isValid')->willReturn(false);
101-
$validateMock->expects($this->exactly(1))->method('getErrors')->willReturn(false);
111+
$validateMock->expects($this->exactly(1))->method('getErrors')->willReturn([]);
102112
$this->validateFactoryMock->expects($this->once())
103113
->method('create')
104114
->willReturn($validateMock);
105115

106-
$this->model->validate(
107-
$this->getOptionValue(),
108-
$this->getProductOption()
116+
$this->model->validate($this->getOptionValue(), $this->getProductOption());
117+
}
118+
119+
/**
120+
* @magentoDataFixture Magento/Catalog/_files/validate_image_info_another.php
121+
* @return void
122+
*/
123+
public function testExceptionWrongExtension(): void
124+
{
125+
$this->expectException(LocalizedException::class);
126+
$this->expectExceptionMessage(
127+
"The product's required option(s) weren't entered. Make sure the options are entered and try again."
109128
);
129+
130+
$validateMock = $this->createPartialMock(Zend_Validate::class, ['isValid', 'getErrors']);
131+
$validateMock->expects($this->exactly(1))->method('getErrors')->willReturn([]);
132+
$this->validateFactoryMock->expects($this->once())->method('create')->willReturn($validateMock);
133+
134+
$this->model->validate($this->getOptionValue('magento_small_image.svg'), $this->getProductOption());
110135
}
111136

112137
/**
138+
* @magentoDataFixture Magento/Catalog/_files/validate_image_info.php
113139
* @return void
114140
*/
115-
public function testValidate()
141+
public function testValidate(): void
116142
{
117143
//use actual zend class to test changed functionality
118-
$validate = $this->objectManager->create(\Zend_Validate::class);
119-
$this->validateFactoryMock->expects($this->once())
120-
->method('create')
121-
->willReturn($validate);
122-
$this->assertTrue(
123-
$this->model->validate(
124-
$this->getOptionValue(),
125-
$this->getProductOption()
126-
)
127-
);
144+
$validate = $this->objectManager->create(Zend_Validate::class);
145+
$this->validateFactoryMock->expects($this->once())->method('create')->willReturn($validate);
146+
147+
$result = $this->model->validate($this->getOptionValue(), $this->getProductOption());
148+
$this->assertTrue($result);
128149
}
129150

130151
/**
131152
* @param array $options
132-
* @return \Magento\Catalog\Model\Product\Option
153+
* @return Option
133154
*/
134-
protected function getProductOption(array $options = [])
155+
protected function getProductOption(array $options = []): Option
135156
{
136157
$data = [
137158
'option_id' => '1',
@@ -154,35 +175,35 @@ protected function getProductOption(array $options = [])
154175
'price' => '5.0000',
155176
'price_type' => 'fixed',
156177
];
157-
$option = $this->objectManager->create(
158-
\Magento\Catalog\Model\Product\Option::class,
178+
179+
return $this->objectManager->create(
180+
Option::class,
159181
[
160182
'data' => array_merge($data, $options)
161183
]
162184
);
163-
164-
return $option;
165185
}
166186

167187
/**
188+
* @param string|null $fileName
168189
* @return array
169190
*/
170-
protected function getOptionValue()
191+
protected function getOptionValue(?string $fileName = 'magento_small_image.jpg'): array
171192
{
172-
/** @var \Magento\Catalog\Model\Product\Media\Config $config */
173-
$config = $this->objectManager->get(\Magento\Catalog\Model\Product\Media\Config::class);
174-
$file = $config->getBaseTmpMediaPath() . '/magento_small_image.jpg';
193+
/** @var Config $config */
194+
$config = $this->objectManager->get(Config::class);
195+
$file = $config->getBaseTmpMediaPath() . '/' . $fileName;
175196

176-
/** @var \Magento\Framework\Filesystem $filesystem */
177-
$filesystem = $this->objectManager->get(\Magento\Framework\Filesystem::class);
178-
$tmpDirectory = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
197+
/** @var Filesystem $filesystem */
198+
$filesystem = $this->objectManager->get(Filesystem::class);
199+
$tmpDirectory = $filesystem->getDirectoryRead(DirectoryList::MEDIA);
179200
$filePath = $tmpDirectory->getAbsolutePath($file);
180201

181202
return [
182203
'title' => 'test.jpg',
183204
'quote_path' => $file,
184205
'order_path' => $file,
185-
'secret_key' => substr(hash('sha256', file_get_contents($filePath)), 0, 20),
206+
'secret_key' => substr(hash('sha256', file_get_contents($filePath)), 0, 20)
186207
];
187208
}
188209
}

0 commit comments

Comments
 (0)