Skip to content

Commit 9d60d6f

Browse files
committed
Merge remote-tracking branch 'origin/B2B-2048' into B2B-2022
2 parents f9d370f + 3cc2d41 commit 9d60d6f

File tree

9 files changed

+419
-3
lines changed

9 files changed

+419
-3
lines changed

app/code/Magento/ImportExport/Model/Import/Source/Zip.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\ImportExport\Model\Import\Source;
77

8+
use Magento\Framework\App\ObjectManager;
89
use Magento\Framework\Exception\ValidatorException;
910

1011
/**
@@ -16,15 +17,17 @@ class Zip extends Csv
1617
* @param string $file
1718
* @param \Magento\Framework\Filesystem\Directory\Write $directory
1819
* @param string $options
20+
* @param \Magento\Framework\Archive\Zip|null $zipArchive
1921
* @throws \Magento\Framework\Exception\LocalizedException
2022
* @throws \Magento\Framework\Exception\ValidatorException
2123
*/
2224
public function __construct(
2325
$file,
2426
\Magento\Framework\Filesystem\Directory\Write $directory,
25-
$options
27+
$options,
28+
\Magento\Framework\Archive\Zip $zipArchive = null
2629
) {
27-
$zip = new \Magento\Framework\Archive\Zip();
30+
$zip = $zipArchive ?? ObjectManager::getInstance()->get(\Magento\Framework\Archive\Zip::class);
2831
$csvFile = $zip->unpack(
2932
$file,
3033
preg_replace('/\.zip$/i', '.csv', $file)
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
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\RemoteStorage\Plugin;
9+
10+
use Magento\Framework\App\Filesystem\DirectoryList;
11+
use Magento\Framework\Exception\FileSystemException;
12+
use Magento\Framework\Exception\RuntimeException;
13+
use Magento\Framework\Filesystem;
14+
use Magento\Framework\Filesystem\Directory\TargetDirectory;
15+
use Magento\Framework\Filesystem\Directory\WriteInterface;
16+
use Magento\RemoteStorage\Model\Config;
17+
18+
/**
19+
* @see \Magento\Framework\Archive\Zip
20+
*/
21+
class Zip
22+
{
23+
/**
24+
* @var WriteInterface
25+
*/
26+
private WriteInterface $tmpDirectoryWrite;
27+
28+
/**
29+
* @var WriteInterface
30+
*/
31+
private WriteInterface $remoteDirectoryWrite;
32+
33+
/**
34+
* @var Config
35+
*/
36+
private Config $config;
37+
38+
/**
39+
* @param Filesystem $filesystem
40+
* @param TargetDirectory $targetDirectory
41+
* @param Config $config
42+
* @throws FileSystemException
43+
*/
44+
public function __construct(
45+
Filesystem $filesystem,
46+
TargetDirectory $targetDirectory,
47+
Config $config
48+
) {
49+
$this->tmpDirectoryWrite = $filesystem->getDirectoryWrite(DirectoryList::TMP);
50+
$this->remoteDirectoryWrite = $targetDirectory->getDirectoryWrite(DirectoryList::ROOT);
51+
$this->config = $config;
52+
}
53+
54+
/**
55+
* Wrapper method around \Magento\Framework\Archive\Zip::unpack().
56+
* Copies file from the remote storage to the tmp directory unpacks it
57+
* and uploads unpacked file to the remote storage.
58+
*
59+
* @param \Magento\Framework\Archive\Zip $subject
60+
* @param callable $proceed
61+
* @param string $source
62+
* @param string $destination
63+
* @return string
64+
* @throws FileSystemException|RuntimeException
65+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
66+
*/
67+
public function aroundUnpack(
68+
\Magento\Framework\Archive\Zip $subject,
69+
callable $proceed,
70+
$source,
71+
$destination
72+
): string {
73+
return $this->proceedFileOperation($proceed, $source, $destination);
74+
}
75+
76+
/**
77+
* Wrapper method around \Magento\Framework\Archive\Zip::pack().
78+
* Copies file from the remote storage to the tmp directory packs it
79+
* and uploads packed file to the remote storage.
80+
*
81+
* @param \Magento\Framework\Archive\Zip $subject
82+
* @param callable $proceed
83+
* @param string $source
84+
* @param string $destination
85+
* @return string
86+
* @throws FileSystemException|RuntimeException
87+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
88+
*/
89+
public function aroundPack(
90+
\Magento\Framework\Archive\Zip $subject,
91+
callable $proceed,
92+
$source,
93+
$destination
94+
): string {
95+
return $this->proceedFileOperation($proceed, $source, $destination);
96+
}
97+
98+
/**
99+
* Common method for both pack and unpack operations
100+
*
101+
* @param callable $proceed
102+
* @param string $source
103+
* @param string $destination
104+
* @return string
105+
* @throws FileSystemException|RuntimeException
106+
*/
107+
private function proceedFileOperation(callable $proceed, $source, $destination): string
108+
{
109+
if ($this->config->isEnabled()) {
110+
$tmpPath = $this->copyFileToTmp($source);
111+
$tmpDestination = $this->getTmpPath($destination);
112+
113+
$proceed($tmpPath, $tmpDestination);
114+
115+
$this->tmpDirectoryWrite->getDriver()->rename(
116+
$tmpDestination,
117+
$destination,
118+
$this->remoteDirectoryWrite->getDriver()
119+
);
120+
$this->tmpDirectoryWrite->delete($tmpPath);
121+
122+
return $destination;
123+
} else {
124+
return $proceed($source, $destination);
125+
}
126+
}
127+
128+
/**
129+
* Copies file from remote storage to tmp folder
130+
*
131+
* @param string $filePath
132+
* @return string
133+
* @throws FileSystemException
134+
*/
135+
private function copyFileToTmp(string $filePath): string
136+
{
137+
$absolutePath = $this->remoteDirectoryWrite->getAbsolutePath($filePath);
138+
if ($this->remoteDirectoryWrite->isFile($absolutePath)) {
139+
$this->tmpDirectoryWrite->create();
140+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
141+
$tmpPath = $this->getTmpPath($filePath);
142+
$content = $this->remoteDirectoryWrite->getDriver()->fileGetContents($filePath);
143+
$filePath = $this->tmpDirectoryWrite->getDriver()->filePutContents($tmpPath, $content) >= 0
144+
? $tmpPath
145+
: $filePath;
146+
}
147+
148+
return $filePath;
149+
}
150+
151+
/**
152+
* Returns tmp path for given file
153+
*
154+
* @param string $filePath
155+
* @return string
156+
*/
157+
private function getTmpPath(string $filePath): string
158+
{
159+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
160+
return $this->tmpDirectoryWrite->getAbsolutePath() . basename($filePath);
161+
}
162+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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\RemoteStorage\Test\Unit\Plugin;
9+
10+
use Magento\Framework\App\Filesystem\DirectoryList;
11+
use Magento\Framework\Filesystem;
12+
use Magento\Framework\Filesystem\Directory\TargetDirectory;
13+
use Magento\Framework\Filesystem\Directory\WriteInterface;
14+
use Magento\Framework\Filesystem\DriverInterface;
15+
use Magento\RemoteStorage\Model\Config;
16+
use Magento\RemoteStorage\Plugin\Zip;
17+
use PHPUnit\Framework\MockObject\MockObject;
18+
use PHPUnit\Framework\TestCase;
19+
20+
class ZipTest extends TestCase
21+
{
22+
/**
23+
* @var Zip
24+
*/
25+
private $plugin;
26+
27+
/**
28+
* @var WriteInterface|MockObject
29+
*/
30+
private $tmpDirectoryWriteMock;
31+
32+
/**
33+
* @var WriteInterface|MockObject
34+
*/
35+
private $remoteDirectoryWriteMock;
36+
37+
/**
38+
* @var Config|MockObject
39+
*/
40+
private $configMock;
41+
42+
/**
43+
* @var \Magento\Framework\Archive\Zip|MockObject
44+
*/
45+
private $subjectMock;
46+
47+
/**
48+
* @return void
49+
* @throws \Magento\Framework\Exception\FileSystemException
50+
*/
51+
protected function setUp(): void
52+
{
53+
/** @var Filesystem|MockObject $filesystem */
54+
$filesystem = $this->createMock(Filesystem::class);
55+
/** @var TargetDirectory|MockObject $targetDirectory */
56+
$targetDirectory = $this->createMock(TargetDirectory::class);
57+
$this->subjectMock = $this->createMock(\Magento\Framework\Archive\Zip::class);
58+
$this->configMock = $this->createMock(Config::class);
59+
$this->tmpDirectoryWriteMock = $this->getMockForAbstractClass(WriteInterface::class);
60+
$this->remoteDirectoryWriteMock = $this->getMockForAbstractClass(WriteInterface::class);
61+
$filesystem->expects(self::once())
62+
->method('getDirectoryWrite')
63+
->with(DirectoryList::TMP)
64+
->willReturn($this->tmpDirectoryWriteMock);
65+
$targetDirectory->expects(self::once())
66+
->method('getDirectoryWrite')
67+
->with(DirectoryList::ROOT)
68+
->willReturn($this->remoteDirectoryWriteMock);
69+
70+
$this->plugin = new Zip(
71+
$filesystem,
72+
$targetDirectory,
73+
$this->configMock
74+
);
75+
}
76+
77+
public function testRemoteStorageEnabled()
78+
{
79+
$this->configMock->expects(self::once())
80+
->method('isEnabled')
81+
->willReturn(false);
82+
$this->remoteDirectoryWriteMock->expects(self::never())
83+
->method('getAbsolutePath');
84+
$this->tmpDirectoryWriteMock->expects(self::never())
85+
->method('getAbsolutePath');
86+
87+
self::assertEquals(
88+
'/path/to.zip',
89+
$this->plugin->aroundUnpack(
90+
$this->subjectMock,
91+
$this->getProceedFunction(),
92+
'/path/from.csv',
93+
'/path/to.zip'
94+
)
95+
);
96+
}
97+
98+
public function testRemoteStorageIsNotEnabled()
99+
{
100+
$remoteDriverMock = $this->getMockForAbstractClass(DriverInterface::class);
101+
$tmpDriverMock = $this->getMockForAbstractClass(DriverInterface::class);
102+
$this->configMock->expects(self::once())
103+
->method('isEnabled')
104+
->willReturn(true);
105+
$this->remoteDirectoryWriteMock->expects(self::any())
106+
->method('getDriver')
107+
->willReturn($remoteDriverMock);
108+
$this->tmpDirectoryWriteMock->expects(self::any())
109+
->method('getDriver')
110+
->willReturn($tmpDriverMock);
111+
$this->remoteDirectoryWriteMock->expects(self::once())
112+
->method('getAbsolutePath')
113+
->with('/remote/path/from.csv')
114+
->willReturn('/remote/path/from.csv');
115+
$this->remoteDirectoryWriteMock->expects(self::once())
116+
->method('isFile')
117+
->with('/remote/path/from.csv')
118+
->willReturn(true);
119+
$this->tmpDirectoryWriteMock->expects(self::exactly(2))
120+
->method('getAbsolutePath')
121+
->willReturn('/path/to/tmp/dir/');
122+
$remoteDriverMock->expects(self::once())
123+
->method('fileGetContents')
124+
->with('/remote/path/from.csv')
125+
->willReturn('file content');
126+
$tmpDriverMock->expects(self::once())
127+
->method('filePutContents')
128+
->with('/path/to/tmp/dir/from.csv', 'file content')
129+
->willReturn(true);
130+
$tmpDriverMock->expects(self::once())
131+
->method('rename')
132+
->with('/path/to/tmp/dir/to.zip', '/remote/path/to.zip', $remoteDriverMock);
133+
$this->tmpDirectoryWriteMock->expects(self::once())
134+
->method('delete')
135+
->with('/path/to/tmp/dir/from.csv');
136+
137+
self::assertEquals(
138+
'/remote/path/to.zip',
139+
$this->plugin->aroundUnpack(
140+
$this->subjectMock,
141+
$this->getProceedFunction(),
142+
'/remote/path/from.csv',
143+
'/remote/path/to.zip'
144+
)
145+
);
146+
}
147+
148+
/**
149+
* @return \Closure
150+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
151+
*/
152+
private function getProceedFunction()
153+
{
154+
return function ($source, $destination) {
155+
return $destination;
156+
};
157+
}
158+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@
107107
<type name="Magento\Framework\Image\Adapter\AbstractAdapter">
108108
<plugin name="remoteImageFile" type="Magento\RemoteStorage\Plugin\Image" sortOrder="10"/>
109109
</type>
110+
<type name="Magento\Framework\Archive\Zip">
111+
<plugin name="remoteZipArchive" type="Magento\RemoteStorage\Plugin\Zip" sortOrder="10"/>
112+
</type>
110113
<type name="Magento\Catalog\Model\Category\FileInfo">
111114
<arguments>
112115
<argument name="filesystem" xsi:type="object">fullRemoteFilesystem</argument>

0 commit comments

Comments
 (0)