Media.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Swatches\Helper;
  7. use Magento\Catalog\Helper\Image;
  8. use Magento\Framework\App\Area;
  9. use Magento\Framework\App\Filesystem\DirectoryList;
  10. /**
  11. * Helper to move images from tmp to catalog directory
  12. * @api
  13. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  14. * @since 100.0.2
  15. */
  16. class Media extends \Magento\Framework\App\Helper\AbstractHelper
  17. {
  18. /**
  19. * Swatch area inside media folder
  20. *
  21. */
  22. const SWATCH_MEDIA_PATH = 'attribute/swatch';
  23. /**
  24. * @var \Magento\Catalog\Model\Product\Media\Config
  25. */
  26. protected $mediaConfig;
  27. /**
  28. * @var \Magento\Framework\Filesystem\Directory\WriteInterface
  29. */
  30. protected $mediaDirectory;
  31. /**
  32. * Core file storage database
  33. *
  34. * @var \Magento\MediaStorage\Helper\File\Storage\Database
  35. */
  36. protected $fileStorageDb = null;
  37. /**
  38. * Store manager
  39. *
  40. * @var \Magento\Store\Model\StoreManagerInterface
  41. */
  42. protected $storeManager;
  43. /**
  44. * @var \Magento\Framework\Image\Factory
  45. */
  46. protected $imageFactory;
  47. /**
  48. * @var \Magento\Theme\Model\ResourceModel\Theme\Collection
  49. */
  50. protected $themeCollection;
  51. /**
  52. * @var \Magento\Framework\View\ConfigInterface
  53. */
  54. protected $viewConfig;
  55. /**
  56. * @var array
  57. */
  58. protected $swatchImageTypes = ['swatch_image', 'swatch_thumb'];
  59. /**
  60. * @var array
  61. */
  62. private $imageConfig;
  63. /**
  64. * @param \Magento\Catalog\Model\Product\Media\Config $mediaConfig
  65. * @param \Magento\Framework\Filesystem $filesystem
  66. * @param \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageDb
  67. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  68. * @param \Magento\Framework\Image\Factory $imageFactory
  69. * @param \Magento\Theme\Model\ResourceModel\Theme\Collection $themeCollection
  70. * @param \Magento\Framework\View\ConfigInterface $configInterface
  71. */
  72. public function __construct(
  73. \Magento\Catalog\Model\Product\Media\Config $mediaConfig,
  74. \Magento\Framework\Filesystem $filesystem,
  75. \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageDb,
  76. \Magento\Store\Model\StoreManagerInterface $storeManager,
  77. \Magento\Framework\Image\Factory $imageFactory,
  78. \Magento\Theme\Model\ResourceModel\Theme\Collection $themeCollection,
  79. \Magento\Framework\View\ConfigInterface $configInterface
  80. ) {
  81. $this->mediaConfig = $mediaConfig;
  82. $this->fileStorageDb = $fileStorageDb;
  83. $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
  84. $this->storeManager = $storeManager;
  85. $this->imageFactory = $imageFactory;
  86. $this->themeCollection = $themeCollection;
  87. $this->viewConfig = $configInterface;
  88. }
  89. /**
  90. * @param string $swatchType
  91. * @param string $file
  92. * @return string
  93. */
  94. public function getSwatchAttributeImage($swatchType, $file)
  95. {
  96. $generationPath = $swatchType . '/' . $this->getFolderNameSize($swatchType) . $file;
  97. $absoluteImagePath = $this->mediaDirectory
  98. ->getAbsolutePath($this->getSwatchMediaPath() . '/' . $generationPath);
  99. if (!file_exists($absoluteImagePath)) {
  100. try {
  101. $this->generateSwatchVariations($file);
  102. } catch (\Exception $e) {
  103. return '';
  104. }
  105. }
  106. return $this->getSwatchMediaUrl() . '/' . $generationPath;
  107. }
  108. /**
  109. * move image from tmp to catalog dir
  110. *
  111. * @param string $file
  112. * @return string path
  113. */
  114. public function moveImageFromTmp($file)
  115. {
  116. if (strrpos($file, '.tmp') == strlen($file) - 4) {
  117. $file = substr($file, 0, strlen($file) - 4);
  118. }
  119. $destinationFile = $this->getUniqueFileName($file);
  120. /** @var $storageHelper \Magento\MediaStorage\Helper\File\Storage\Database */
  121. $storageHelper = $this->fileStorageDb;
  122. if ($storageHelper->checkDbUsage()) {
  123. $storageHelper->renameFile(
  124. $this->mediaConfig->getTmpMediaShortUrl($file),
  125. $this->mediaConfig->getMediaShortUrl($destinationFile)
  126. );
  127. $this->mediaDirectory->delete($this->mediaConfig->getTmpMediaPath($file));
  128. $this->mediaDirectory->delete($this->getAttributeSwatchPath($destinationFile));
  129. } else {
  130. $this->mediaDirectory->renameFile(
  131. $this->mediaConfig->getTmpMediaPath($file),
  132. $this->getAttributeSwatchPath($destinationFile)
  133. );
  134. }
  135. return str_replace('\\', '/', $destinationFile);
  136. }
  137. /**
  138. * Check whether file to move exists. Getting unique name
  139. *
  140. * @param <type> $file
  141. * @return string
  142. */
  143. protected function getUniqueFileName($file)
  144. {
  145. if ($this->fileStorageDb->checkDbUsage()) {
  146. $destFile = $this->fileStorageDb->getUniqueFilename(
  147. $this->mediaConfig->getBaseMediaUrlAddition(),
  148. $file
  149. );
  150. } else {
  151. $destFile = dirname($file) . '/' . \Magento\MediaStorage\Model\File\Uploader::getNewFileName(
  152. $this->mediaDirectory->getAbsolutePath($this->getAttributeSwatchPath($file))
  153. );
  154. }
  155. return $destFile;
  156. }
  157. /**
  158. * Generate swatch thumb and small swatch image
  159. *
  160. * @param string $imageUrl
  161. * @return $this
  162. */
  163. public function generateSwatchVariations($imageUrl)
  164. {
  165. $absoluteImagePath = $this->mediaDirectory->getAbsolutePath($this->getAttributeSwatchPath($imageUrl));
  166. foreach ($this->swatchImageTypes as $swatchType) {
  167. $imageConfig = $this->getImageConfig();
  168. $swatchNamePath = $this->generateNamePath($imageConfig, $imageUrl, $swatchType);
  169. $image = $this->imageFactory->create($absoluteImagePath);
  170. $this->setupImageProperties($image);
  171. $image->resize($imageConfig[$swatchType]['width'], $imageConfig[$swatchType]['height']);
  172. $this->setupImageProperties($image, true);
  173. $image->save($swatchNamePath['path_for_save'], $swatchNamePath['name']);
  174. }
  175. return $this;
  176. }
  177. /**
  178. * Setup base image properties for resize
  179. *
  180. * @param \Magento\Framework\Image $image
  181. * @param bool $isSwatch
  182. * @return $this
  183. */
  184. protected function setupImageProperties(\Magento\Framework\Image $image, $isSwatch = false)
  185. {
  186. $image->quality(100);
  187. $image->constrainOnly(true);
  188. $image->keepAspectRatio(true);
  189. if ($isSwatch) {
  190. $image->keepFrame(true);
  191. $image->keepTransparency(true);
  192. $image->backgroundColor([255, 255, 255]);
  193. }
  194. return $this;
  195. }
  196. /**
  197. * Generate swatch path and name for saving
  198. *
  199. * @param array $imageConfig
  200. * @param string $imageUrl
  201. * @param string $swatchType
  202. * @return array
  203. */
  204. protected function generateNamePath($imageConfig, $imageUrl, $swatchType)
  205. {
  206. $fileName = $this->prepareFileName($imageUrl);
  207. $absolutePath = $this->mediaDirectory->getAbsolutePath($this->getSwatchCachePath($swatchType));
  208. return [
  209. 'path_for_save' => $absolutePath . $this->getFolderNameSize($swatchType, $imageConfig) . $fileName['path'],
  210. 'name' => $fileName['name']
  211. ];
  212. }
  213. /**
  214. * Generate folder name WIDTHxHEIGHT based on config in view.xml
  215. *
  216. * @param string $swatchType
  217. * @param null $imageConfig
  218. * @return string
  219. */
  220. public function getFolderNameSize($swatchType, $imageConfig = null)
  221. {
  222. if ($imageConfig === null) {
  223. $imageConfig = $this->getImageConfig();
  224. }
  225. return $imageConfig[$swatchType]['width'] . 'x' . $imageConfig[$swatchType]['height'];
  226. }
  227. /**
  228. * Merged config from view.xml
  229. *
  230. * @return array
  231. */
  232. public function getImageConfig()
  233. {
  234. if (!$this->imageConfig) {
  235. $this->imageConfig = $this->viewConfig->getViewConfig()->getMediaEntities(
  236. 'Magento_Catalog',
  237. Image::MEDIA_TYPE_CONFIG_NODE
  238. );
  239. }
  240. return $this->imageConfig;
  241. }
  242. /**
  243. * Image url /m/a/magento.png return ['name' => 'magento.png', 'path => '/m/a']
  244. *
  245. * @param string $imageUrl
  246. * @return array
  247. */
  248. protected function prepareFileName($imageUrl)
  249. {
  250. $fileArray = explode('/', $imageUrl);
  251. $fileName = array_pop($fileArray);
  252. $filePath = implode('/', $fileArray);
  253. return ['name' => $fileName, 'path' => $filePath];
  254. }
  255. /**
  256. * Url type http://url/pub/media/attribute/swatch/
  257. *
  258. * @return string
  259. */
  260. public function getSwatchMediaUrl()
  261. {
  262. return $this->storeManager
  263. ->getStore()
  264. ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . $this->getSwatchMediaPath();
  265. }
  266. /**
  267. * Return example: attribute/swatch/m/a/magento.jpg
  268. *
  269. * @param string $file
  270. * @return string
  271. */
  272. public function getAttributeSwatchPath($file)
  273. {
  274. return $this->getSwatchMediaPath() . '/' . $this->prepareFile($file);
  275. }
  276. /**
  277. * Media swatch path
  278. *
  279. * @return string
  280. */
  281. public function getSwatchMediaPath()
  282. {
  283. return self::SWATCH_MEDIA_PATH;
  284. }
  285. /**
  286. * Media path with swatch_image or swatch_thumb folder
  287. *
  288. * @param string $swatchType
  289. * @return string
  290. */
  291. public function getSwatchCachePath($swatchType)
  292. {
  293. return self::SWATCH_MEDIA_PATH . '/' . $swatchType . '/';
  294. }
  295. /**
  296. * Prepare file for saving
  297. *
  298. * @param string $file
  299. * @return string
  300. */
  301. protected function prepareFile($file)
  302. {
  303. return ltrim(str_replace('\\', '/', $file), '/');
  304. }
  305. }