Skip to content

Commit a068a64

Browse files
author
Alexander Tolochko
committed
Possibility to upload WebP and SVG image via API
1 parent 1f08dfe commit a068a64

File tree

2 files changed

+258
-1
lines changed

2 files changed

+258
-1
lines changed
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
<?php
2+
3+
namespace MagestyApps\WebImages\Plugin\Product\Gallery;
4+
5+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
6+
use Magento\Catalog\Model\Product;
7+
use Magento\Catalog\Model\Product\Gallery\Processor;
8+
use Magento\Catalog\Model\Product\Media\Config;
9+
use Magento\Framework\Api\Data\ImageContentInterface;
10+
use Magento\Framework\App\Filesystem\DirectoryList;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\Filesystem;
13+
use Magento\Framework\Filesystem\Directory\WriteInterface;
14+
use Magento\MediaStorage\Helper\File\Storage\Database;
15+
use MagestyApps\WebImages\Helper\ImageHelper;
16+
17+
class ProcessorPlugin
18+
{
19+
/**
20+
* @var ImageHelper
21+
*/
22+
private $imageHelper;
23+
24+
/**
25+
* @var WriteInterface
26+
*/
27+
private $mediaDirectory;
28+
29+
/**
30+
* @var Config
31+
*/
32+
private $mediaConfig;
33+
34+
/**
35+
* @var Database
36+
*/
37+
private $fileStorageDb;
38+
39+
/**
40+
* @var ProductAttributeRepositoryInterface
41+
*/
42+
private $attributeRepository;
43+
44+
/**
45+
* @var \Magento\Framework\File\Mime
46+
*/
47+
private $mime;
48+
49+
/**
50+
* @var \Magento\Catalog\Api\Data\ProductAttributeInterface
51+
*/
52+
private $attribute;
53+
54+
public function __construct(
55+
ImageHelper $imageHelper,
56+
Filesystem $filesystem,
57+
Config $mediaConfig,
58+
Database $fileStorageDb,
59+
ProductAttributeRepositoryInterface $attributeRepository,
60+
\Magento\Framework\File\Mime $mime
61+
) {
62+
$this->imageHelper = $imageHelper;
63+
$this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
64+
$this->mediaConfig = $mediaConfig;
65+
$this->fileStorageDb = $fileStorageDb;
66+
$this->attributeRepository = $attributeRepository;
67+
$this->mime = $mime;
68+
}
69+
70+
/**
71+
* We have to duplicate so many code lines because Magento hardcoded allowed image extensions
72+
*
73+
* @param Product\Gallery\Processor $subject
74+
* @param callable $proceed
75+
* @param Product $product
76+
* @param $file
77+
* @param $mediaAttribute
78+
* @param $move
79+
* @param $exclude
80+
* @return string
81+
*/
82+
public function aroundAddImage(
83+
Product\Gallery\Processor $subject,
84+
callable $proceed,
85+
Product $product,
86+
$file,
87+
$mediaAttribute = null,
88+
$move = false,
89+
$exclude = true
90+
) {
91+
$pathinfo = pathinfo($file);
92+
if (!in_array($pathinfo['extension'], $this->imageHelper->getWebImageExtensions())) {
93+
return $proceed($product, $file, $mediaAttribute, $move, $exclude);
94+
}
95+
96+
$file = $this->mediaDirectory->getRelativePath($file);
97+
if (!$this->mediaDirectory->isFile($file)) {
98+
throw new LocalizedException(__("The image doesn't exist."));
99+
}
100+
101+
$fileName = \Magento\MediaStorage\Model\File\Uploader::getCorrectFileName($pathinfo['basename']);
102+
$dispersionPath = \Magento\MediaStorage\Model\File\Uploader::getDispersionPath($fileName);
103+
$fileName = $dispersionPath . '/' . $fileName;
104+
105+
$fileName = $this->getNotDuplicatedFilename($fileName, $dispersionPath);
106+
107+
$destinationFile = $this->mediaConfig->getTmpMediaPath($fileName);
108+
109+
try {
110+
/** @var $storageHelper \Magento\MediaStorage\Helper\File\Storage\Database */
111+
$storageHelper = $this->fileStorageDb;
112+
if ($move) {
113+
$this->mediaDirectory->renameFile($file, $destinationFile);
114+
115+
//If this is used, filesystem should be configured properly
116+
$storageHelper->saveFile($this->mediaConfig->getTmpMediaShortUrl($fileName));
117+
} else {
118+
$this->mediaDirectory->copyFile($file, $destinationFile);
119+
120+
$storageHelper->saveFile($this->mediaConfig->getTmpMediaShortUrl($fileName));
121+
}
122+
} catch (\Exception $e) {
123+
throw new LocalizedException(__('The "%1" file couldn\'t be moved.', $e->getMessage()));
124+
}
125+
126+
$fileName = str_replace('\\', '/', $fileName);
127+
128+
$attrCode = $this->getAttribute()->getAttributeCode();
129+
$mediaGalleryData = $product->getData($attrCode);
130+
$position = 0;
131+
132+
$absoluteFilePath = $this->mediaDirectory->getAbsolutePath($destinationFile);
133+
$imageMimeType = $this->mime->getMimeType($absoluteFilePath);
134+
$imageContent = $this->mediaDirectory->readFile($absoluteFilePath);
135+
$imageBase64 = base64_encode($imageContent);
136+
$imageName = $pathinfo['filename'];
137+
138+
if (!is_array($mediaGalleryData)) {
139+
$mediaGalleryData = ['images' => []];
140+
}
141+
142+
foreach ($mediaGalleryData['images'] as &$image) {
143+
if (isset($image['position']) && $image['position'] > $position) {
144+
$position = $image['position'];
145+
}
146+
}
147+
148+
$position++;
149+
$mediaGalleryData['images'][] = [
150+
'file' => $fileName,
151+
'position' => $position,
152+
'label' => '',
153+
'disabled' => (int)$exclude,
154+
'media_type' => 'image',
155+
'types' => $mediaAttribute,
156+
'content' => [
157+
'data' => [
158+
ImageContentInterface::NAME => $imageName,
159+
ImageContentInterface::BASE64_ENCODED_DATA => $imageBase64,
160+
ImageContentInterface::TYPE => $imageMimeType,
161+
]
162+
]
163+
];
164+
165+
$product->setData($attrCode, $mediaGalleryData);
166+
167+
if ($mediaAttribute !== null) {
168+
$this->setMediaAttribute($product, $mediaAttribute, $fileName);
169+
}
170+
171+
return $fileName;
172+
}
173+
174+
/**
175+
* Get filename which is not duplicated with other files in media temporary and media directories
176+
*
177+
* @param string $fileName
178+
* @param string $dispersionPath
179+
* @return string
180+
* @since 101.0.0
181+
*/
182+
protected function getNotDuplicatedFilename($fileName, $dispersionPath)
183+
{
184+
$fileMediaName = $dispersionPath . '/'
185+
. \Magento\MediaStorage\Model\File\Uploader::getNewFileName($this->mediaConfig->getMediaPath($fileName));
186+
$fileTmpMediaName = $dispersionPath . '/'
187+
. \Magento\MediaStorage\Model\File\Uploader::getNewFileName($this->mediaConfig->getTmpMediaPath($fileName));
188+
189+
if ($fileMediaName != $fileTmpMediaName) {
190+
if ($fileMediaName != $fileName) {
191+
return $this->getNotDuplicatedFilename(
192+
$fileMediaName,
193+
$dispersionPath
194+
);
195+
} elseif ($fileTmpMediaName != $fileName) {
196+
return $this->getNotDuplicatedFilename(
197+
$fileTmpMediaName,
198+
$dispersionPath
199+
);
200+
}
201+
}
202+
203+
return $fileMediaName;
204+
}
205+
206+
/**
207+
* Return media_gallery attribute
208+
*
209+
* @return \Magento\Catalog\Api\Data\ProductAttributeInterface
210+
* @since 101.0.0
211+
*/
212+
public function getAttribute()
213+
{
214+
if (!$this->attribute) {
215+
$this->attribute = $this->attributeRepository->get('media_gallery');
216+
}
217+
218+
return $this->attribute;
219+
}
220+
221+
/**
222+
* Set media attribute value
223+
*
224+
* @param \Magento\Catalog\Model\Product $product
225+
* @param string|string[] $mediaAttribute
226+
* @param string $value
227+
* @return $this
228+
* @since 101.0.0
229+
*/
230+
public function setMediaAttribute(\Magento\Catalog\Model\Product $product, $mediaAttribute, $value)
231+
{
232+
$mediaAttributeCodes = $this->mediaConfig->getMediaAttributeCodes();
233+
234+
if (is_array($mediaAttribute)) {
235+
foreach ($mediaAttribute as $attribute) {
236+
if (in_array($attribute, $mediaAttributeCodes)) {
237+
$product->setData($attribute, $value);
238+
}
239+
}
240+
} elseif (in_array($mediaAttribute, $mediaAttributeCodes)) {
241+
$product->setData($mediaAttribute, $value);
242+
}
243+
244+
return $this;
245+
}
246+
}

etc/di.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,18 @@
4343
</argument>
4444
</arguments>
4545
</type>
46-
46+
<type name="Magento\Framework\Api\ImageContentValidator">
47+
<arguments>
48+
<argument name="allowedMimeTypes" xsi:type="array">
49+
<item name="svg" xsi:type="string">image/svg</item>
50+
<item name="svg-xml" xsi:type="string">image/svg+xml</item>
51+
<item name="webp" xsi:type="string">image/webp</item>
52+
</argument>
53+
</arguments>
54+
</type>
55+
<type name="Magento\Catalog\Model\Product\Gallery\Processor">
56+
<plugin name="web-images-gallery-processor-plugin" type="MagestyApps\WebImages\Plugin\Product\Gallery\ProcessorPlugin" />
57+
</type>
4758
<type name="Magento\MediaStorage\App\Media">
4859
<plugin name="web-images-media-plugin" type="MagestyApps\WebImages\Plugin\App\MediaPlugin" />
4960
</type>

0 commit comments

Comments
 (0)