Storage.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\Cms\Model\Wysiwyg\Images;
  8. use Magento\Cms\Helper\Wysiwyg\Images;
  9. use Magento\Framework\App\Filesystem\DirectoryList;
  10. /**
  11. * Wysiwyg Images model.
  12. *
  13. * Tightly connected with controllers responsible for managing files so it uses session and is (sort of) a part
  14. * of the presentation layer.
  15. *
  16. * @SuppressWarnings(PHPMD.LongVariable)
  17. * @SuppressWarnings(PHPMD.TooManyFields)
  18. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  19. * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
  20. *
  21. * @api
  22. * @since 100.0.2
  23. */
  24. class Storage extends \Magento\Framework\DataObject
  25. {
  26. const DIRECTORY_NAME_REGEXP = '/^[a-z0-9\-\_]+$/si';
  27. const THUMBS_DIRECTORY_NAME = '.thumbs';
  28. const THUMB_PLACEHOLDER_PATH_SUFFIX = 'Magento_Cms::images/placeholder_thumbnail.jpg';
  29. /**
  30. * Config object
  31. *
  32. * @var \Magento\Framework\App\Config\Element
  33. */
  34. protected $_config;
  35. /**
  36. * Config object as array
  37. *
  38. * @var array
  39. */
  40. protected $_configAsArray;
  41. /**
  42. * @var \Magento\Framework\Filesystem\Directory\Write
  43. */
  44. protected $_directory;
  45. /**
  46. * @var \Magento\Framework\Image\AdapterFactory
  47. */
  48. protected $_imageFactory;
  49. /**
  50. * @var \Magento\Framework\View\Asset\Repository
  51. */
  52. protected $_assetRepo;
  53. /**
  54. * Core file storage database
  55. *
  56. * @var \Magento\MediaStorage\Helper\File\Storage\Database
  57. */
  58. protected $_coreFileStorageDb = null;
  59. /**
  60. * Cms wysiwyg images
  61. *
  62. * @var \Magento\Cms\Helper\Wysiwyg\Images
  63. */
  64. protected $_cmsWysiwygImages = null;
  65. /**
  66. * @var array
  67. */
  68. protected $_resizeParameters;
  69. /**
  70. * @var array
  71. */
  72. protected $_extensions;
  73. /**
  74. * @var array
  75. */
  76. protected $_dirs;
  77. /**
  78. * @var \Magento\Backend\Model\UrlInterface
  79. */
  80. protected $_backendUrl;
  81. /**
  82. * @var \Magento\Backend\Model\Session
  83. */
  84. protected $_session;
  85. /**
  86. * Directory database factory
  87. *
  88. * @var \Magento\MediaStorage\Model\File\Storage\Directory\DatabaseFactory
  89. */
  90. protected $_directoryDatabaseFactory;
  91. /**
  92. * Storage database factory
  93. *
  94. * @var \Magento\MediaStorage\Model\File\Storage\DatabaseFactory
  95. */
  96. protected $_storageDatabaseFactory;
  97. /**
  98. * Storage file factory
  99. *
  100. * @var \Magento\MediaStorage\Model\File\Storage\FileFactory
  101. */
  102. protected $_storageFileFactory;
  103. /**
  104. * Storage collection factory
  105. *
  106. * @var \Magento\Cms\Model\Wysiwyg\Images\Storage\CollectionFactory
  107. */
  108. protected $_storageCollectionFactory;
  109. /**
  110. * Uploader factory
  111. *
  112. * @var \Magento\MediaStorage\Model\File\UploaderFactory
  113. */
  114. protected $_uploaderFactory;
  115. /**
  116. * Construct
  117. *
  118. * @param \Magento\Backend\Model\Session $session
  119. * @param \Magento\Backend\Model\UrlInterface $backendUrl
  120. * @param \Magento\Cms\Helper\Wysiwyg\Images $cmsWysiwygImages
  121. * @param \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDb
  122. * @param \Magento\Framework\Filesystem $filesystem
  123. * @param \Magento\Framework\Image\AdapterFactory $imageFactory
  124. * @param \Magento\Framework\View\Asset\Repository $assetRepo
  125. * @param \Magento\Cms\Model\Wysiwyg\Images\Storage\CollectionFactory $storageCollectionFactory
  126. * @param \Magento\MediaStorage\Model\File\Storage\FileFactory $storageFileFactory
  127. * @param \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $storageDatabaseFactory
  128. * @param \Magento\MediaStorage\Model\File\Storage\Directory\DatabaseFactory $directoryDatabaseFactory
  129. * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory
  130. * @param array $resizeParameters
  131. * @param array $extensions
  132. * @param array $dirs
  133. * @param array $data
  134. *
  135. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  136. */
  137. public function __construct(
  138. \Magento\Backend\Model\Session $session,
  139. \Magento\Backend\Model\UrlInterface $backendUrl,
  140. \Magento\Cms\Helper\Wysiwyg\Images $cmsWysiwygImages,
  141. \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDb,
  142. \Magento\Framework\Filesystem $filesystem,
  143. \Magento\Framework\Image\AdapterFactory $imageFactory,
  144. \Magento\Framework\View\Asset\Repository $assetRepo,
  145. \Magento\Cms\Model\Wysiwyg\Images\Storage\CollectionFactory $storageCollectionFactory,
  146. \Magento\MediaStorage\Model\File\Storage\FileFactory $storageFileFactory,
  147. \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $storageDatabaseFactory,
  148. \Magento\MediaStorage\Model\File\Storage\Directory\DatabaseFactory $directoryDatabaseFactory,
  149. \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
  150. array $resizeParameters = [],
  151. array $extensions = [],
  152. array $dirs = [],
  153. array $data = []
  154. ) {
  155. $this->_session = $session;
  156. $this->_backendUrl = $backendUrl;
  157. $this->_cmsWysiwygImages = $cmsWysiwygImages;
  158. $this->_coreFileStorageDb = $coreFileStorageDb;
  159. $this->_directory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
  160. $this->_imageFactory = $imageFactory;
  161. $this->_assetRepo = $assetRepo;
  162. $this->_storageCollectionFactory = $storageCollectionFactory;
  163. $this->_storageFileFactory = $storageFileFactory;
  164. $this->_storageDatabaseFactory = $storageDatabaseFactory;
  165. $this->_directoryDatabaseFactory = $directoryDatabaseFactory;
  166. $this->_uploaderFactory = $uploaderFactory;
  167. $this->_resizeParameters = $resizeParameters;
  168. $this->_extensions = $extensions;
  169. $this->_dirs = $dirs;
  170. parent::__construct($data);
  171. }
  172. /**
  173. * Create sub directories if DB storage is used
  174. *
  175. * @param string $path
  176. * @return void
  177. */
  178. protected function createSubDirectories($path)
  179. {
  180. if ($this->_coreFileStorageDb->checkDbUsage()) {
  181. /** @var \Magento\MediaStorage\Model\File\Storage\Directory\Database $subDirectories */
  182. $subDirectories = $this->_directoryDatabaseFactory->create();
  183. $directories = $subDirectories->getSubdirectories($path);
  184. foreach ($directories as $directory) {
  185. $fullPath = rtrim($path, '/') . '/' . $directory['name'];
  186. $this->_directory->create($fullPath);
  187. }
  188. }
  189. }
  190. /**
  191. * Prepare and get conditions for exclude directories
  192. *
  193. * @return array
  194. */
  195. protected function getConditionsForExcludeDirs()
  196. {
  197. $conditions = ['reg_exp' => [], 'plain' => []];
  198. if ($this->_dirs['exclude']) {
  199. foreach ($this->_dirs['exclude'] as $dir) {
  200. $conditions[!empty($dir['regexp']) ? 'reg_exp' : 'plain'][$dir['name']] = true;
  201. }
  202. }
  203. // "include" section takes precedence and can revoke directory exclusion
  204. if ($this->_dirs['include']) {
  205. foreach ($this->_dirs['include'] as $dir) {
  206. unset($conditions['reg_exp'][$dir['name']], $conditions['plain'][$dir['name']]);
  207. }
  208. }
  209. return $conditions;
  210. }
  211. /**
  212. * Remove excluded directories from collection
  213. *
  214. * @param \Magento\Framework\Data\Collection\Filesystem $collection
  215. * @param array $conditions
  216. * @return \Magento\Framework\Data\Collection\Filesystem
  217. */
  218. protected function removeItemFromCollection($collection, $conditions)
  219. {
  220. $regExp = $conditions['reg_exp'] ? '~' . implode('|', array_keys($conditions['reg_exp'])) . '~i' : null;
  221. $storageRoot = $this->_cmsWysiwygImages->getStorageRoot();
  222. $storageRootLength = strlen($storageRoot);
  223. foreach ($collection as $key => $value) {
  224. $mediaSubPathname = substr($value->getFilename(), $storageRootLength);
  225. $rootChildParts = explode('/', '/' . ltrim($mediaSubPathname, '/'));
  226. if (array_key_exists($rootChildParts[1], $conditions['plain'])
  227. || ($regExp && preg_match($regExp, $value->getFilename()))) {
  228. $collection->removeItemByKey($key);
  229. }
  230. }
  231. return $collection;
  232. }
  233. /**
  234. * Return one-level child directories for specified path
  235. *
  236. * @param string $path Parent directory path
  237. * @return \Magento\Framework\Data\Collection\Filesystem
  238. */
  239. public function getDirsCollection($path)
  240. {
  241. $this->createSubDirectories($path);
  242. $collection = $this->getCollection($path)
  243. ->setCollectDirs(true)
  244. ->setCollectFiles(false)
  245. ->setCollectRecursively(false);
  246. $conditions = $this->getConditionsForExcludeDirs();
  247. return $this->removeItemFromCollection($collection, $conditions);
  248. }
  249. /**
  250. * Return files
  251. *
  252. * @param string $path Parent directory path
  253. * @param string $type Type of storage, e.g. image, media etc.
  254. * @return \Magento\Framework\Data\Collection\Filesystem
  255. */
  256. public function getFilesCollection($path, $type = null)
  257. {
  258. if ($this->_coreFileStorageDb->checkDbUsage()) {
  259. $files = $this->_storageDatabaseFactory->create()->getDirectoryFiles($path);
  260. /** @var \Magento\MediaStorage\Model\File\Storage\File $fileStorageModel */
  261. $fileStorageModel = $this->_storageFileFactory->create();
  262. foreach ($files as $file) {
  263. $fileStorageModel->saveFile($file);
  264. }
  265. }
  266. $collection = $this->getCollection(
  267. $path
  268. )->setCollectDirs(
  269. false
  270. )->setCollectFiles(
  271. true
  272. )->setCollectRecursively(
  273. false
  274. )->setOrder(
  275. 'mtime',
  276. \Magento\Framework\Data\Collection::SORT_ORDER_ASC
  277. );
  278. // Add files extension filter
  279. if ($allowed = $this->getAllowedExtensions($type)) {
  280. $collection->setFilesFilter('/\.(' . implode('|', $allowed) . ')$/i');
  281. }
  282. // prepare items
  283. foreach ($collection as $item) {
  284. $item->setId($this->_cmsWysiwygImages->idEncode($item->getBasename()));
  285. $item->setName($item->getBasename());
  286. $item->setShortName($this->_cmsWysiwygImages->getShortFilename($item->getBasename()));
  287. $item->setUrl($this->_cmsWysiwygImages->getCurrentUrl() . $item->getBasename());
  288. $item->setSize(filesize($item->getFilename()));
  289. $item->setMimeType(\mime_content_type($item->getFilename()));
  290. if ($this->isImage($item->getBasename())) {
  291. $thumbUrl = $this->getThumbnailUrl($item->getFilename(), true);
  292. // generate thumbnail "on the fly" if it does not exists
  293. if (!$thumbUrl) {
  294. $thumbUrl = $this->_backendUrl->getUrl('cms/*/thumbnail', ['file' => $item->getId()]);
  295. }
  296. $size = @getimagesize($item->getFilename());
  297. if (is_array($size)) {
  298. $item->setWidth($size[0]);
  299. $item->setHeight($size[1]);
  300. }
  301. } else {
  302. $thumbUrl = $this->_assetRepo->getUrl(self::THUMB_PLACEHOLDER_PATH_SUFFIX);
  303. }
  304. $item->setThumbUrl($thumbUrl);
  305. }
  306. return $collection;
  307. }
  308. /**
  309. * Storage collection
  310. *
  311. * @param string $path Path to the directory
  312. * @return \Magento\Cms\Model\Wysiwyg\Images\Storage\Collection
  313. */
  314. public function getCollection($path = null)
  315. {
  316. /** @var \Magento\Cms\Model\Wysiwyg\Images\Storage\Collection $collection */
  317. $collection = $this->_storageCollectionFactory->create();
  318. if ($path !== null) {
  319. $collection->addTargetDir($path);
  320. }
  321. return $collection;
  322. }
  323. /**
  324. * Create new directory in storage
  325. *
  326. * @param string $name New directory name
  327. * @param string $path Parent directory path
  328. * @return array New directory info
  329. * @throws \Magento\Framework\Exception\LocalizedException
  330. */
  331. public function createDirectory($name, $path)
  332. {
  333. if (!preg_match(self::DIRECTORY_NAME_REGEXP, $name)) {
  334. throw new \Magento\Framework\Exception\LocalizedException(
  335. __('Please rename the folder using only letters, numbers, underscores and dashes.')
  336. );
  337. }
  338. $relativePath = $this->_directory->getRelativePath($path);
  339. if (!$this->_directory->isDirectory($relativePath) || !$this->_directory->isWritable($relativePath)) {
  340. $path = $this->_cmsWysiwygImages->getStorageRoot();
  341. }
  342. $newPath = $path . '/' . $name;
  343. $relativeNewPath = $this->_directory->getRelativePath($newPath);
  344. if ($this->_directory->isDirectory($relativeNewPath)) {
  345. throw new \Magento\Framework\Exception\LocalizedException(
  346. __('We found a directory with the same name. Please try another folder name.')
  347. );
  348. }
  349. $this->_directory->create($relativeNewPath);
  350. try {
  351. if ($this->_coreFileStorageDb->checkDbUsage()) {
  352. $relativePath = $this->_coreFileStorageDb->getMediaRelativePath($newPath);
  353. $this->_directoryDatabaseFactory->create()->createRecursive($relativePath);
  354. }
  355. $result = [
  356. 'name' => $name,
  357. 'short_name' => $this->_cmsWysiwygImages->getShortFilename($name),
  358. 'path' => $newPath,
  359. 'id' => $this->_cmsWysiwygImages->convertPathToId($newPath),
  360. ];
  361. return $result;
  362. } catch (\Magento\Framework\Exception\FileSystemException $e) {
  363. throw new \Magento\Framework\Exception\LocalizedException(__('We cannot create a new directory.'));
  364. }
  365. }
  366. /**
  367. * Recursively delete directory from storage
  368. *
  369. * @param string $path Target dir
  370. * @return void
  371. * @throws \Magento\Framework\Exception\LocalizedException
  372. */
  373. public function deleteDirectory($path)
  374. {
  375. if ($this->_coreFileStorageDb->checkDbUsage()) {
  376. $this->_directoryDatabaseFactory->create()->deleteDirectory($path);
  377. }
  378. try {
  379. $this->_deleteByPath($path);
  380. $path = $this->getThumbnailRoot() . $this->_getRelativePathToRoot($path);
  381. $this->_deleteByPath($path);
  382. } catch (\Magento\Framework\Exception\FileSystemException $e) {
  383. throw new \Magento\Framework\Exception\LocalizedException(__('We cannot delete directory %1.', $path));
  384. }
  385. }
  386. /**
  387. * Delete by path
  388. *
  389. * @param string $path
  390. * @return void
  391. */
  392. protected function _deleteByPath($path)
  393. {
  394. $path = $this->_sanitizePath($path);
  395. if (!empty($path)) {
  396. $this->_validatePath($path);
  397. $this->_directory->delete($this->_directory->getRelativePath($path));
  398. }
  399. }
  400. /**
  401. * Delete file (and its thumbnail if exists) from storage
  402. *
  403. * @param string $target File path to be deleted
  404. * @return $this
  405. */
  406. public function deleteFile($target)
  407. {
  408. $relativePath = $this->_directory->getRelativePath($target);
  409. if ($this->_directory->isFile($relativePath)) {
  410. $this->_directory->delete($relativePath);
  411. }
  412. $this->_coreFileStorageDb->deleteFile($target);
  413. $thumb = $this->getThumbnailPath($target, true);
  414. $relativePathThumb = $this->_directory->getRelativePath($thumb);
  415. if ($thumb) {
  416. if ($this->_directory->isFile($relativePathThumb)) {
  417. $this->_directory->delete($relativePathThumb);
  418. }
  419. $this->_coreFileStorageDb->deleteFile($thumb);
  420. }
  421. return $this;
  422. }
  423. /**
  424. * Upload and resize new file
  425. *
  426. * @param string $targetPath Target directory
  427. * @param string $type Type of storage, e.g. image, media etc.
  428. * @return array File info Array
  429. * @throws \Magento\Framework\Exception\LocalizedException
  430. */
  431. public function uploadFile($targetPath, $type = null)
  432. {
  433. /** @var \Magento\MediaStorage\Model\File\Uploader $uploader */
  434. $uploader = $this->_uploaderFactory->create(['fileId' => 'image']);
  435. $allowed = $this->getAllowedExtensions($type);
  436. if ($allowed) {
  437. $uploader->setAllowedExtensions($allowed);
  438. }
  439. $uploader->setAllowRenameFiles(true);
  440. $uploader->setFilesDispersion(false);
  441. if (!$uploader->checkMimeType($this->getAllowedMimeTypes($type))) {
  442. throw new \Magento\Framework\Exception\LocalizedException(__('File validation failed.'));
  443. }
  444. $result = $uploader->save($targetPath);
  445. if (!$result) {
  446. throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t upload the file right now.'));
  447. }
  448. // create thumbnail
  449. $this->resizeFile($targetPath . '/' . $uploader->getUploadedFileName(), true);
  450. return $result;
  451. }
  452. /**
  453. * Thumbnail path getter
  454. *
  455. * @param string $filePath original file path
  456. * @param bool $checkFile OPTIONAL is it necessary to check file availability
  457. * @return string|false
  458. */
  459. public function getThumbnailPath($filePath, $checkFile = false)
  460. {
  461. $mediaRootDir = $this->_cmsWysiwygImages->getStorageRoot();
  462. if (strpos($filePath, $mediaRootDir) === 0) {
  463. $thumbPath = $this->getThumbnailRoot() . substr($filePath, strlen($mediaRootDir));
  464. if (!$checkFile || $this->_directory->isExist($this->_directory->getRelativePath($thumbPath))) {
  465. return $thumbPath;
  466. }
  467. }
  468. return false;
  469. }
  470. /**
  471. * Thumbnail URL getter
  472. *
  473. * @param string $filePath original file path
  474. * @param bool $checkFile OPTIONAL is it necessary to check file availability
  475. * @return string|false
  476. */
  477. public function getThumbnailUrl($filePath, $checkFile = false)
  478. {
  479. $mediaRootDir = $this->_cmsWysiwygImages->getStorageRoot();
  480. if (strpos($filePath, $mediaRootDir) === 0) {
  481. $thumbSuffix = self::THUMBS_DIRECTORY_NAME . substr($filePath, strlen($mediaRootDir));
  482. if (!$checkFile || $this->_directory->isExist(
  483. $this->_directory->getRelativePath($mediaRootDir . '/' . $thumbSuffix)
  484. )
  485. ) {
  486. $thumbSuffix = substr(
  487. $mediaRootDir,
  488. strlen($this->_directory->getAbsolutePath())
  489. ) . '/' . $thumbSuffix;
  490. $randomIndex = '?rand=' . time();
  491. return str_replace('\\', '/', $this->_cmsWysiwygImages->getBaseUrl() . $thumbSuffix) . $randomIndex;
  492. }
  493. }
  494. return false;
  495. }
  496. /**
  497. * Create thumbnail for image and save it to thumbnails directory
  498. *
  499. * @param string $source Image path to be resized
  500. * @param bool $keepRatio Keep aspect ratio or not
  501. * @return bool|string Resized filepath or false if errors were occurred
  502. */
  503. public function resizeFile($source, $keepRatio = true)
  504. {
  505. $realPath = $this->_directory->getRelativePath($source);
  506. if (!$this->_directory->isFile($realPath) || !$this->_directory->isExist($realPath)) {
  507. return false;
  508. }
  509. $targetDir = $this->getThumbsPath($source);
  510. $pathTargetDir = $this->_directory->getRelativePath($targetDir);
  511. if (!$this->_directory->isExist($pathTargetDir)) {
  512. $this->_directory->create($pathTargetDir);
  513. }
  514. if (!$this->_directory->isExist($pathTargetDir)) {
  515. return false;
  516. }
  517. $image = $this->_imageFactory->create();
  518. $image->open($source);
  519. $image->keepAspectRatio($keepRatio);
  520. $image->resize($this->_resizeParameters['width'], $this->_resizeParameters['height']);
  521. $dest = $targetDir . '/' . pathinfo($source, PATHINFO_BASENAME);
  522. $image->save($dest);
  523. if ($this->_directory->isFile($this->_directory->getRelativePath($dest))) {
  524. return $dest;
  525. }
  526. return false;
  527. }
  528. /**
  529. * Resize images on the fly in controller action
  530. *
  531. * @param string $filename File basename
  532. * @return bool|string Thumbnail path or false for errors
  533. */
  534. public function resizeOnTheFly($filename)
  535. {
  536. $path = $this->getSession()->getCurrentPath();
  537. if (!$path) {
  538. $path = $this->_cmsWysiwygImages->getCurrentPath();
  539. }
  540. return $this->resizeFile($path . '/' . $filename);
  541. }
  542. /**
  543. * Return thumbnails directory path for file/current directory
  544. *
  545. * @param bool|string $filePath Path to the file
  546. * @return string
  547. */
  548. public function getThumbsPath($filePath = false)
  549. {
  550. $mediaRootDir = $this->_cmsWysiwygImages->getStorageRoot();
  551. $thumbnailDir = $this->getThumbnailRoot();
  552. if ($filePath && strpos($filePath, $mediaRootDir) === 0) {
  553. $thumbnailDir .= dirname(substr($filePath, strlen($mediaRootDir)));
  554. }
  555. return $thumbnailDir;
  556. }
  557. /**
  558. * Storage session
  559. *
  560. * @return \Magento\Backend\Model\Session
  561. */
  562. public function getSession()
  563. {
  564. return $this->_session;
  565. }
  566. /**
  567. * Prepare allowed_extensions config settings
  568. *
  569. * @param string $type Type of storage, e.g. image, media etc.
  570. * @return array Array of allowed file extensions
  571. */
  572. public function getAllowedExtensions($type = null)
  573. {
  574. $allowed = $this->getExtensionsList($type);
  575. return array_keys(array_filter($allowed));
  576. }
  577. /**
  578. * Thumbnail root directory getter
  579. *
  580. * @return string
  581. */
  582. public function getThumbnailRoot()
  583. {
  584. return $this->_cmsWysiwygImages->getStorageRoot() . '/' . self::THUMBS_DIRECTORY_NAME;
  585. }
  586. /**
  587. * Simple way to check whether file is image or not based on extension
  588. *
  589. * @param string $filename
  590. * @return bool
  591. */
  592. public function isImage($filename)
  593. {
  594. if (!$this->hasData('_image_extensions')) {
  595. $this->setData('_image_extensions', $this->getAllowedExtensions('image'));
  596. }
  597. $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
  598. return in_array($ext, $this->_getData('_image_extensions'));
  599. }
  600. /**
  601. * Get resize width
  602. *
  603. * @return int
  604. */
  605. public function getResizeWidth()
  606. {
  607. return $this->_resizeParameters['width'];
  608. }
  609. /**
  610. * Get resize height
  611. *
  612. * @return int
  613. */
  614. public function getResizeHeight()
  615. {
  616. return $this->_resizeParameters['height'];
  617. }
  618. /**
  619. * Get cms wysiwyg images helper
  620. *
  621. * @return Images|null
  622. */
  623. public function getCmsWysiwygImages()
  624. {
  625. return $this->_cmsWysiwygImages;
  626. }
  627. /**
  628. * Is path under storage root directory
  629. *
  630. * @param string $path
  631. * @return void
  632. * @throws \Magento\Framework\Exception\LocalizedException
  633. */
  634. protected function _validatePath($path)
  635. {
  636. $root = $this->_sanitizePath($this->_cmsWysiwygImages->getStorageRoot());
  637. if ($root == $path) {
  638. throw new \Magento\Framework\Exception\LocalizedException(
  639. __('We can\'t delete root directory %1 right now.', $path)
  640. );
  641. }
  642. if (strpos($path, $root) !== 0) {
  643. throw new \Magento\Framework\Exception\LocalizedException(
  644. __('Directory %1 is not under storage root path.', $path)
  645. );
  646. }
  647. }
  648. /**
  649. * Sanitize path
  650. *
  651. * @param string $path
  652. * @return string
  653. */
  654. protected function _sanitizePath($path)
  655. {
  656. return rtrim(preg_replace('~[/\\\]+~', '/', $this->_directory->getDriver()->getRealPathSafety($path)), '/');
  657. }
  658. /**
  659. * Get path in root storage dir
  660. *
  661. * @param string $path
  662. * @return string|bool
  663. */
  664. protected function _getRelativePathToRoot($path)
  665. {
  666. return substr(
  667. $this->_sanitizePath($path),
  668. strlen($this->_sanitizePath($this->_cmsWysiwygImages->getStorageRoot()))
  669. );
  670. }
  671. /**
  672. * Prepare mime types config settings.
  673. *
  674. * @param string|null $type Type of storage, e.g. image, media etc.
  675. * @return array Array of allowed file extensions
  676. */
  677. private function getAllowedMimeTypes($type = null): array
  678. {
  679. $allowed = $this->getExtensionsList($type);
  680. return array_values(array_filter($allowed));
  681. }
  682. /**
  683. * Get list of allowed file extensions with mime type in values.
  684. *
  685. * @param string|null $type
  686. * @return array
  687. */
  688. private function getExtensionsList($type = null): array
  689. {
  690. if (is_string($type) && array_key_exists("{$type}_allowed", $this->_extensions)) {
  691. $allowed = $this->_extensions["{$type}_allowed"];
  692. } else {
  693. $allowed = $this->_extensions['allowed'];
  694. }
  695. return $allowed;
  696. }
  697. }