Skip to content

Commit 810c9b5

Browse files
author
Volodymyr Kublytskyi
authored
Merge branch '2.3-develop' into ASYNC-IMPORT-32
2 parents 69112e8 + 05d01d5 commit 810c9b5

File tree

9 files changed

+496
-2
lines changed

9 files changed

+496
-2
lines changed

app/code/Magento/ImportService/Api/Data/SourceUploadResponseInterface.php

+15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ interface SourceUploadResponseInterface
1818

1919
const ERROR = 'error';
2020

21+
const SOURCE_MODEL = 'source';
22+
2123
/**
2224
* Get file ID
2325
*
@@ -39,6 +41,13 @@ public function getStatus();
3941
*/
4042
public function getError();
4143

44+
/**
45+
* Get source
46+
*
47+
* @return \Magento\ImportService\Api\Data\SourceInterface
48+
*/
49+
public function getSource();
50+
4251
/**
4352
* @param $sourceId
4453
* @return mixed
@@ -56,4 +65,10 @@ public function setStatus($status);
5665
* @return mixed
5766
*/
5867
public function setError($error);
68+
69+
/**
70+
* @param \Magento\ImportService\Api\Data\SourceInterface $source
71+
* @return mixed
72+
*/
73+
public function setSource(\Magento\ImportService\Api\Data\SourceInterface $source);
5974
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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\ImportService\Model\Import\Processor;
9+
10+
use Magento\Framework\App\Filesystem\DirectoryList;
11+
use Magento\Framework\Filesystem;
12+
use Magento\ImportService\Exception as ImportServiceException;
13+
use Magento\ImportService\Model\Import\SourceProcessorPool;
14+
use Magento\ImportService\Model\Source\Validator;
15+
16+
/**
17+
* CSV files processor for asynchronous import
18+
*/
19+
class ExternalFileProcessor implements SourceProcessorInterface
20+
{
21+
/**
22+
* @var \Magento\Framework\Filesystem
23+
*/
24+
private $fileSystem;
25+
26+
/**
27+
* @var \Magento\ImportService\Model\Source\Validator
28+
*/
29+
private $validator;
30+
31+
/**
32+
* LocalPathFileProcessor constructor
33+
*
34+
* @param FileSystem $fileSystem
35+
* @param Validator $validator
36+
*/
37+
public function __construct(
38+
FileSystem $fileSystem,
39+
Validator $validator
40+
) {
41+
$this->fileSystem = $fileSystem;
42+
$this->validator = $validator;
43+
}
44+
45+
/**
46+
* {@inheritdoc}
47+
*/
48+
public function processUpload(\Magento\ImportService\Api\Data\SourceInterface $source, \Magento\ImportService\Api\Data\SourceUploadResponseInterface $response)
49+
{
50+
/** Validate the $source object */
51+
if ($errors = $this->validator->validateRequest($source)) {
52+
throw new ImportServiceException(
53+
__('Invalid request: %1', implode(", ", $errors))
54+
);
55+
}
56+
57+
/** Check if the domain exists and the file within that domain exists */
58+
if (!$this->validator->checkIfRemoteFileExists($source->getImportData())) {
59+
throw new ImportServiceException(
60+
__('Remote file %1 does not exist.', $source->getImportData())
61+
);
62+
}
63+
64+
/** Validate the remote file content type */
65+
if (!$this->validator->validateMimeTypeForRemoteFile($source->getImportData())) {
66+
throw new ImportServiceException(
67+
__('Invalid mime type, expected is one of: %1', implode(", ", $this->validator->getAllowedMimeTypes()))
68+
);
69+
}
70+
71+
/** @var string $workingDirectory */
72+
$workingDirectory = SourceProcessorPool::WORKING_DIR;
73+
74+
/** @var string $fileName */
75+
$fileName = uniqid() . '.' . $source->getSourceType();
76+
77+
/** @var \Magento\Framework\Filesystem\Directory\WriteInterface $writeInterface */
78+
$writeInterface = $this->fileSystem->getDirectoryWrite(DirectoryList::VAR_DIR);
79+
80+
/** If the directory is not present, it will be created */
81+
$writeInterface->create($workingDirectory);
82+
83+
/** @var string $copyFileFullPath*/
84+
$copyFileFullPath = $writeInterface->getAbsolutePath($workingDirectory) . $fileName;
85+
86+
/** Attempt a copy, may throw \Magento\Framework\Exception\FileSystemException */
87+
$writeInterface->getDriver()->copy($source->getImportData(), $copyFileFullPath);
88+
89+
return $response->setSource($source->setImportData($fileName))
90+
->setStatus($response::STATUS_UPLOADED);
91+
}
92+
}

app/code/Magento/ImportService/Model/Import/SourceProcessorPool.php

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
*/
1717
class SourceProcessorPool
1818
{
19+
/**
20+
* Working directory
21+
*
22+
* @var string
23+
*/
24+
const WORKING_DIR = 'importservice/';
25+
1926
/**
2027
* @var array
2128
*/

app/code/Magento/ImportService/Model/Source.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77

88
namespace Magento\ImportService\Model;
99

10-
use Magento\Framework\Model\AbstractModel;
10+
use Magento\Framework\Model\AbstractExtensibleModel;
1111
use Magento\ImportService\Api\Data\SourceExtensionInterface;
1212
use Magento\ImportService\Api\Data\SourceInterface;
1313
use Magento\ImportService\Model\ResourceModel\Source as SourceResource;
1414

1515
/**
1616
* Class Source
1717
*/
18-
class Source extends AbstractModel implements SourceInterface
18+
class Source extends AbstractExtensibleModel implements SourceInterface
1919
{
2020
const CACHE_TAG = 'magento_import_service_source';
2121

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ImportService\Model\Source;
7+
8+
use Magento\Framework\File\Mime\Proxy as Mime;
9+
use Magento\Framework\Filesystem\Driver\Http\Proxy as Http;
10+
11+
/**
12+
* Class Validator
13+
*/
14+
class Validator
15+
{
16+
/**
17+
* @var string[]
18+
*/
19+
private $allowedMimeTypes;
20+
21+
/**
22+
* @var \Magento\Framework\File\Mime\Proxy
23+
*/
24+
private $mime;
25+
26+
/**
27+
* @var \Magento\Framework\Filesystem\Driver\Http
28+
*/
29+
private $httpDriver;
30+
31+
/**
32+
* @param string[] $allowedMimeTypes
33+
* @param Mime $mime
34+
* @param Http $httpDriver
35+
*/
36+
public function __construct(
37+
array $allowedMimeTypes,
38+
Mime $mime,
39+
Http $httpDriver
40+
) {
41+
$this->allowedMimeTypes = $allowedMimeTypes;
42+
$this->mime = $mime;
43+
$this->httpDriver = $httpDriver;
44+
}
45+
46+
/**
47+
* @return string[]
48+
*/
49+
public function getAllowedMimeTypes()
50+
{
51+
return $this->allowedMimeTypes;
52+
}
53+
54+
/**
55+
* @param \Magento\ImportService\Model\Source $source
56+
* @return array|null
57+
*/
58+
public function validateRequest(\Magento\ImportService\Model\Source $source)
59+
{
60+
$errors = [];
61+
62+
if (!$this->validateSourceType($source)) {
63+
$errors[] = __('%1 cannot be empty', $source::SOURCE_TYPE);
64+
}
65+
66+
if (!$this->validateImportData($source)) {
67+
$errors[] = __('%1 cannot be empty', $source::IMPORT_DATA);
68+
}
69+
70+
if (count($errors) > 0) {
71+
return $errors;
72+
}
73+
74+
return null;
75+
}
76+
77+
/**
78+
* @param \Magento\ImportService\Model\Source $source
79+
* @return bool
80+
*/
81+
public function validateSourceType(\Magento\ImportService\Model\Source $source)
82+
{
83+
if (!$source->getSourceType()) {
84+
return false;
85+
}
86+
87+
return true;
88+
}
89+
90+
/**
91+
* @param \Magento\ImportService\Model\Source $source
92+
* @return bool
93+
*/
94+
public function validateImportData(\Magento\ImportService\Model\Source $source)
95+
{
96+
if (!$source->getImportData()) {
97+
return false;
98+
}
99+
100+
return true;
101+
}
102+
103+
/**
104+
* @param string $absoluteFilePath
105+
* @return bool
106+
*/
107+
public function validateMimeTypeForLocalFile(string $absoluteFilePath)
108+
{
109+
/** @var string $mimeType */
110+
$mimeType = $this->mime->getMimeType($absoluteFilePath);
111+
112+
if (!in_array($mimeType, $this->allowedMimeTypes)) {
113+
return false;
114+
}
115+
116+
return true;
117+
}
118+
119+
/**
120+
* @param string $url
121+
* @return bool
122+
*/
123+
public function validateMimeTypeForRemoteFile(string $url)
124+
{
125+
/** @var array $stat */
126+
$stat = $this->httpDriver->stat($this->getSourceLocation($url));
127+
128+
if (!isset($stat['type']) || !in_array($stat['type'], $this->getAllowedMimeTypes())) {
129+
return false;
130+
}
131+
132+
return true;
133+
}
134+
135+
/**
136+
* @param string $url
137+
* @return bool
138+
* @throws \Magento\Framework\Exception\FileSystemException
139+
*/
140+
public function checkIfRemoteFileExists($url)
141+
{
142+
if (!$this->httpDriver->isExists($this->getSourceLocation($url))) {
143+
return false;
144+
}
145+
146+
return true;
147+
}
148+
149+
/**
150+
* @param string $url
151+
* @return string
152+
*/
153+
private function getSourceLocation($url)
154+
{
155+
return preg_replace("(^https?://)", "", $url);
156+
}
157+
}

app/code/Magento/ImportService/Model/SourceUploadResponse.php

+20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\Framework\Model\AbstractModel;
1111
use Magento\ImportService\Api\Data\SourceUploadResponseInterface;
12+
use Magento\ImportService\Api\Data\SourceInterface;
1213

1314
class SourceUploadResponse extends AbstractModel implements SourceUploadResponseInterface
1415
{
@@ -41,6 +42,16 @@ public function getError()
4142
return $this->getData(self::ERROR);
4243
}
4344

45+
/**
46+
* Get source
47+
*
48+
* @return SourceInterface
49+
*/
50+
public function getSource()
51+
{
52+
return $this->getData(self::SOURCE_MODEL);
53+
}
54+
4455
/**
4556
* @param $sourceId
4657
* @return SourceUploadResponse|mixed
@@ -67,4 +78,13 @@ public function setError($error)
6778
{
6879
return $this->setData(self::ERROR, $error);
6980
}
81+
82+
/**
83+
* @param SourceInterface $source
84+
* @return mixed
85+
*/
86+
public function setSource(SourceInterface $source)
87+
{
88+
return $this->setData(self::SOURCE_MODEL, $source);
89+
}
7090
}

app/code/Magento/ImportService/etc/di.xml

+12
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@
2323
xsi:type="object">Magento\ImportService\Model\Import\Processor\LocalPathFileProcessor\Proxy</item>
2424
<item name="import_type" xsi:type="string">local_path</item>
2525
</item>
26+
<item name="external" xsi:type="array">
27+
<item name="processor" xsi:type="object">Magento\ImportService\Model\Import\Processor\ExternalFileProcessor\Proxy</item>
28+
<item name="import_type" xsi:type="string">external</item>
29+
</item>
30+
</argument>
31+
</arguments>
32+
</type>
33+
<type name="\Magento\ImportService\Model\Source\Validator">
34+
<arguments>
35+
<argument name="allowedMimeTypes" xsi:type="array">
36+
<item name="plain" xsi:type="string">text/plain</item>
37+
<item name="csv" xsi:type="string">text/csv</item>
2638
</argument>
2739
</arguments>
2840
</type>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ImportService,ImportService
2+
"Remote file %1 does not exist", "Remote file %1 does not exist"
3+
"Invalid mime type, expected is one of: %1", "Invalid mime type, expected is one of: %1"
4+
"Invalid request: %1", "Invalid request: %1"
5+
"%1 cannot be empty", "%1 cannot be empty"

0 commit comments

Comments
 (0)