ImageProcessor.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Api;
  7. use Magento\Framework\Api\Data\ImageContentInterface;
  8. use Magento\Framework\App\Filesystem\DirectoryList;
  9. use Magento\Framework\Exception\InputException;
  10. use Magento\Framework\Filesystem;
  11. use Magento\Framework\Phrase;
  12. /**
  13. * Class ImageProcessor
  14. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  15. */
  16. class ImageProcessor implements ImageProcessorInterface
  17. {
  18. /**
  19. * MIME type/extension map
  20. *
  21. * @var array
  22. */
  23. protected $mimeTypeExtensionMap = [
  24. 'image/jpg' => 'jpg',
  25. 'image/jpeg' => 'jpg',
  26. 'image/gif' => 'gif',
  27. 'image/png' => 'png',
  28. ];
  29. /**
  30. * @var Filesystem
  31. */
  32. private $filesystem;
  33. /**
  34. * @var Filesystem
  35. */
  36. private $contentValidator;
  37. /**
  38. * @var DataObjectHelper
  39. */
  40. private $dataObjectHelper;
  41. /**
  42. * @var \Psr\Log\LoggerInterface
  43. */
  44. protected $logger;
  45. /**
  46. * @var Uploader
  47. */
  48. private $uploader;
  49. /**
  50. * @var \Magento\Framework\Filesystem\Directory\WriteInterface
  51. */
  52. private $mediaDirectory;
  53. /**
  54. * @param Filesystem $fileSystem
  55. * @param ImageContentValidatorInterface $contentValidator
  56. * @param DataObjectHelper $dataObjectHelper
  57. * @param \Psr\Log\LoggerInterface $logger
  58. * @param Uploader $uploader
  59. */
  60. public function __construct(
  61. Filesystem $fileSystem,
  62. ImageContentValidatorInterface $contentValidator,
  63. DataObjectHelper $dataObjectHelper,
  64. \Psr\Log\LoggerInterface $logger,
  65. Uploader $uploader
  66. ) {
  67. $this->filesystem = $fileSystem;
  68. $this->contentValidator = $contentValidator;
  69. $this->dataObjectHelper = $dataObjectHelper;
  70. $this->logger = $logger;
  71. $this->uploader = $uploader;
  72. $this->mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. public function save(
  78. CustomAttributesDataInterface $dataObjectWithCustomAttributes,
  79. $entityType,
  80. CustomAttributesDataInterface $previousCustomerData = null
  81. ) {
  82. //Get all Image related custom attributes
  83. $imageDataObjects = $this->dataObjectHelper->getCustomAttributeValueByType(
  84. $dataObjectWithCustomAttributes->getCustomAttributes(),
  85. \Magento\Framework\Api\Data\ImageContentInterface::class
  86. );
  87. // Return if no images to process
  88. if (empty($imageDataObjects)) {
  89. return $dataObjectWithCustomAttributes;
  90. }
  91. // For every image, save it and replace it with corresponding Eav data object
  92. /** @var $imageDataObject \Magento\Framework\Api\AttributeValue */
  93. foreach ($imageDataObjects as $imageDataObject) {
  94. /** @var $imageContent \Magento\Framework\Api\Data\ImageContentInterface */
  95. $imageContent = $imageDataObject->getValue();
  96. $filename = $this->processImageContent($entityType, $imageContent);
  97. //Set filename from static media location into data object
  98. $dataObjectWithCustomAttributes->setCustomAttribute(
  99. $imageDataObject->getAttributeCode(),
  100. $filename
  101. );
  102. //Delete previously saved image if it exists
  103. if ($previousCustomerData) {
  104. $previousImageAttribute = $previousCustomerData->getCustomAttribute(
  105. $imageDataObject->getAttributeCode()
  106. );
  107. if ($previousImageAttribute) {
  108. $previousImagePath = $previousImageAttribute->getValue();
  109. if (!empty($previousImagePath) && ($previousImagePath != $filename)) {
  110. @unlink($this->mediaDirectory->getAbsolutePath() . $entityType . $previousImagePath);
  111. }
  112. }
  113. }
  114. }
  115. return $dataObjectWithCustomAttributes;
  116. }
  117. /**
  118. * {@inheritdoc}
  119. */
  120. public function processImageContent($entityType, $imageContent)
  121. {
  122. if (!$this->contentValidator->isValid($imageContent)) {
  123. throw new InputException(new Phrase('The image content is invalid. Verify the content and try again.'));
  124. }
  125. $fileContent = @base64_decode($imageContent->getBase64EncodedData(), true);
  126. $tmpDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::SYS_TMP);
  127. $fileName = $this->getFileName($imageContent);
  128. $tmpFileName = substr(md5(rand()), 0, 7) . '.' . $fileName;
  129. $tmpDirectory->writeFile($tmpFileName, $fileContent);
  130. $fileAttributes = [
  131. 'tmp_name' => $tmpDirectory->getAbsolutePath() . $tmpFileName,
  132. 'name' => $imageContent->getName()
  133. ];
  134. try {
  135. $this->uploader->processFileAttributes($fileAttributes);
  136. $this->uploader->setFilesDispersion(true);
  137. $this->uploader->setFilenamesCaseSensitivity(false);
  138. $this->uploader->setAllowRenameFiles(true);
  139. $destinationFolder = $entityType;
  140. $this->uploader->save($this->mediaDirectory->getAbsolutePath($destinationFolder), $fileName);
  141. } catch (\Exception $e) {
  142. $this->logger->critical($e);
  143. }
  144. return $this->uploader->getUploadedFileName();
  145. }
  146. /**
  147. * @param string $mimeType
  148. * @return string
  149. */
  150. protected function getMimeTypeExtension($mimeType)
  151. {
  152. return $this->mimeTypeExtensionMap[$mimeType] ?? '';
  153. }
  154. /**
  155. * @param ImageContentInterface $imageContent
  156. * @return string
  157. * @throws \Magento\Framework\Exception\LocalizedException
  158. */
  159. private function getFileName($imageContent)
  160. {
  161. $fileName = $imageContent->getName();
  162. if (!pathinfo($fileName, PATHINFO_EXTENSION)) {
  163. if (!$imageContent->getType() || !$this->getMimeTypeExtension($imageContent->getType())) {
  164. throw new InputException(new Phrase('Cannot recognize image extension.'));
  165. }
  166. $fileName .= '.' . $this->getMimeTypeExtension($imageContent->getType());
  167. }
  168. return $fileName;
  169. }
  170. }