PageRenderTime 45ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/magento/framework/Filesystem/Driver/File.php

https://gitlab.com/daigiangaitu91/magento
PHP | 934 lines | 652 code | 34 blank | 248 comment | 50 complexity | 2fc1550027d62813251c8525325c9d62 MD5 | raw file
  1. <?php
  2. /**
  3. * Origin filesystem driver
  4. *
  5. * Copyright © 2015 Magento. All rights reserved.
  6. * See COPYING.txt for license details.
  7. */
  8. namespace Magento\Framework\Filesystem\Driver;
  9. use Magento\Framework\Exception\FileSystemException;
  10. use Magento\Framework\Filesystem\DriverInterface;
  11. /**
  12. * Class File
  13. * @package Magento\Framework\Filesystem\Driver
  14. * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
  15. */
  16. class File implements DriverInterface
  17. {
  18. /**
  19. * @var string
  20. */
  21. protected $scheme = '';
  22. /**
  23. * Returns last warning message string
  24. *
  25. * @return string
  26. */
  27. protected function getWarningMessage()
  28. {
  29. $warning = error_get_last();
  30. if ($warning && $warning['type'] == E_WARNING) {
  31. return 'Warning!' . $warning['message'];
  32. }
  33. return null;
  34. }
  35. /**
  36. * Is file or directory exist in file system
  37. *
  38. * @param string $path
  39. * @return bool
  40. * @throws FileSystemException
  41. */
  42. public function isExists($path)
  43. {
  44. clearstatcache();
  45. $result = @file_exists($this->getScheme() . $path);
  46. if ($result === null) {
  47. throw new FileSystemException(
  48. new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()])
  49. );
  50. }
  51. return $result;
  52. }
  53. /**
  54. * Gathers the statistics of the given path
  55. *
  56. * @param string $path
  57. * @return array
  58. * @throws FileSystemException
  59. */
  60. public function stat($path)
  61. {
  62. clearstatcache();
  63. $result = @stat($this->getScheme() . $path);
  64. if (!$result) {
  65. throw new FileSystemException(
  66. new \Magento\Framework\Phrase('Cannot gather stats! %1', [$this->getWarningMessage()])
  67. );
  68. }
  69. return $result;
  70. }
  71. /**
  72. * Check permissions for reading file or directory
  73. *
  74. * @param string $path
  75. * @return bool
  76. * @throws FileSystemException
  77. */
  78. public function isReadable($path)
  79. {
  80. clearstatcache();
  81. $result = @is_readable($this->getScheme() . $path);
  82. if ($result === null) {
  83. throw new FileSystemException(
  84. new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()])
  85. );
  86. }
  87. return $result;
  88. }
  89. /**
  90. * Tells whether the filename is a regular file
  91. *
  92. * @param string $path
  93. * @return bool
  94. * @throws FileSystemException
  95. */
  96. public function isFile($path)
  97. {
  98. clearstatcache();
  99. $result = @is_file($this->getScheme() . $path);
  100. if ($result === null) {
  101. throw new FileSystemException(
  102. new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()])
  103. );
  104. }
  105. return $result;
  106. }
  107. /**
  108. * Tells whether the filename is a regular directory
  109. *
  110. * @param string $path
  111. * @return bool
  112. * @throws FileSystemException
  113. */
  114. public function isDirectory($path)
  115. {
  116. clearstatcache();
  117. $result = @is_dir($this->getScheme() . $path);
  118. if ($result === null) {
  119. throw new FileSystemException(
  120. new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()])
  121. );
  122. }
  123. return $result;
  124. }
  125. /**
  126. * Retrieve file contents from given path
  127. *
  128. * @param string $path
  129. * @param string|null $flag
  130. * @param resource|null $context
  131. * @return string
  132. * @throws FileSystemException
  133. */
  134. public function fileGetContents($path, $flag = null, $context = null)
  135. {
  136. clearstatcache();
  137. $result = @file_get_contents($this->getScheme() . $path, $flag, $context);
  138. if (false === $result) {
  139. throw new FileSystemException(
  140. new \Magento\Framework\Phrase(
  141. 'Cannot read contents from file "%1" %2',
  142. [$path, $this->getWarningMessage()]
  143. )
  144. );
  145. }
  146. return $result;
  147. }
  148. /**
  149. * Check if given path is writable
  150. *
  151. * @param string $path
  152. * @return bool
  153. * @throws FileSystemException
  154. */
  155. public function isWritable($path)
  156. {
  157. clearstatcache();
  158. $result = @is_writable($this->getScheme() . $path);
  159. if ($result === null) {
  160. throw new FileSystemException(
  161. new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()])
  162. );
  163. }
  164. return $result;
  165. }
  166. /**
  167. * Returns parent directory's path
  168. *
  169. * @param string $path
  170. * @return string
  171. */
  172. public function getParentDirectory($path)
  173. {
  174. return dirname($this->getScheme() . $path);
  175. }
  176. /**
  177. * Create directory
  178. *
  179. * @param string $path
  180. * @param int $permissions
  181. * @return bool
  182. * @throws FileSystemException
  183. */
  184. public function createDirectory($path, $permissions)
  185. {
  186. return $this->mkdirRecursive($path, $permissions);
  187. }
  188. /**
  189. * Create a directory recursively taking into account race conditions
  190. *
  191. * @param string $path
  192. * @param int $permissions
  193. * @return bool
  194. * @throws FileSystemException
  195. */
  196. private function mkdirRecursive($path, $permissions)
  197. {
  198. $path = $this->getScheme() . $path;
  199. if (is_dir($path)) {
  200. return true;
  201. }
  202. $parentDir = dirname($path);
  203. while (!is_dir($parentDir)) {
  204. $this->mkdirRecursive($parentDir, $permissions);
  205. }
  206. $result = @mkdir($path, $permissions);
  207. if (!$result) {
  208. if (is_dir($path)) {
  209. $result = true;
  210. } else {
  211. throw new FileSystemException(
  212. new \Magento\Framework\Phrase(
  213. 'Directory "%1" cannot be created %2',
  214. [$path, $this->getWarningMessage()]
  215. )
  216. );
  217. }
  218. }
  219. return $result;
  220. }
  221. /**
  222. * Read directory
  223. *
  224. * @param string $path
  225. * @return string[]
  226. * @throws FileSystemException
  227. */
  228. public function readDirectory($path)
  229. {
  230. try {
  231. $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS;
  232. $iterator = new \FilesystemIterator($path, $flags);
  233. $result = [];
  234. /** @var \FilesystemIterator $file */
  235. foreach ($iterator as $file) {
  236. $result[] = $file->getPathname();
  237. }
  238. sort($result);
  239. return $result;
  240. } catch (\Exception $e) {
  241. throw new FileSystemException(new \Magento\Framework\Phrase($e->getMessage()), $e);
  242. }
  243. }
  244. /**
  245. * Search paths by given regex
  246. *
  247. * @param string $pattern
  248. * @param string $path
  249. * @return string[]
  250. * @throws FileSystemException
  251. */
  252. public function search($pattern, $path)
  253. {
  254. clearstatcache();
  255. $globPattern = rtrim($path, '/') . '/' . ltrim($pattern, '/');
  256. $result = @glob($globPattern, GLOB_BRACE);
  257. return is_array($result) ? $result : [];
  258. }
  259. /**
  260. * Renames a file or directory
  261. *
  262. * @param string $oldPath
  263. * @param string $newPath
  264. * @param DriverInterface|null $targetDriver
  265. * @return bool
  266. * @throws FileSystemException
  267. */
  268. public function rename($oldPath, $newPath, DriverInterface $targetDriver = null)
  269. {
  270. $result = false;
  271. $targetDriver = $targetDriver ?: $this;
  272. if (get_class($targetDriver) == get_class($this)) {
  273. $result = @rename($this->getScheme() . $oldPath, $newPath);
  274. } else {
  275. $content = $this->fileGetContents($oldPath);
  276. if (false !== $targetDriver->filePutContents($newPath, $content)) {
  277. $result = $this->deleteFile($newPath);
  278. }
  279. }
  280. if (!$result) {
  281. throw new FileSystemException(
  282. new \Magento\Framework\Phrase(
  283. 'The "%1" path cannot be renamed into "%2" %3',
  284. [$oldPath, $newPath, $this->getWarningMessage()]
  285. )
  286. );
  287. }
  288. return $result;
  289. }
  290. /**
  291. * Copy source into destination
  292. *
  293. * @param string $source
  294. * @param string $destination
  295. * @param DriverInterface|null $targetDriver
  296. * @return bool
  297. * @throws FileSystemException
  298. */
  299. public function copy($source, $destination, DriverInterface $targetDriver = null)
  300. {
  301. $targetDriver = $targetDriver ?: $this;
  302. if (get_class($targetDriver) == get_class($this)) {
  303. $result = @copy($this->getScheme() . $source, $destination);
  304. } else {
  305. $content = $this->fileGetContents($source);
  306. $result = $targetDriver->filePutContents($destination, $content);
  307. }
  308. if (!$result) {
  309. throw new FileSystemException(
  310. new \Magento\Framework\Phrase(
  311. 'The file or directory "%1" cannot be copied to "%2" %3',
  312. [
  313. $source,
  314. $destination,
  315. $this->getWarningMessage()
  316. ]
  317. )
  318. );
  319. }
  320. return $result;
  321. }
  322. /**
  323. * Create symlink on source and place it into destination
  324. *
  325. * @param string $source
  326. * @param string $destination
  327. * @param DriverInterface|null $targetDriver
  328. * @return bool
  329. * @throws FileSystemException
  330. */
  331. public function symlink($source, $destination, DriverInterface $targetDriver = null)
  332. {
  333. $result = false;
  334. if (get_class($targetDriver) == get_class($this)) {
  335. $result = @symlink($this->getScheme() . $source, $destination);
  336. }
  337. if (!$result) {
  338. throw new FileSystemException(
  339. new \Magento\Framework\Phrase(
  340. 'Cannot create a symlink for "%1" and place it to "%2" %3',
  341. [
  342. $source,
  343. $destination,
  344. $this->getWarningMessage()
  345. ]
  346. )
  347. );
  348. }
  349. return $result;
  350. }
  351. /**
  352. * Delete file
  353. *
  354. * @param string $path
  355. * @return bool
  356. * @throws FileSystemException
  357. */
  358. public function deleteFile($path)
  359. {
  360. $result = @unlink($this->getScheme() . $path);
  361. if (!$result) {
  362. throw new FileSystemException(
  363. new \Magento\Framework\Phrase('The file "%1" cannot be deleted %2', [$path, $this->getWarningMessage()])
  364. );
  365. }
  366. return $result;
  367. }
  368. /**
  369. * Recursive delete directory
  370. *
  371. * @param string $path
  372. * @return bool
  373. * @throws FileSystemException
  374. */
  375. public function deleteDirectory($path)
  376. {
  377. $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS;
  378. $iterator = new \FilesystemIterator($path, $flags);
  379. /** @var \FilesystemIterator $entity */
  380. foreach ($iterator as $entity) {
  381. if ($entity->isDir()) {
  382. $this->deleteDirectory($entity->getPathname());
  383. } else {
  384. $this->deleteFile($entity->getPathname());
  385. }
  386. }
  387. $result = @rmdir($this->getScheme() . $path);
  388. if (!$result) {
  389. throw new FileSystemException(
  390. new \Magento\Framework\Phrase(
  391. 'The directory "%1" cannot be deleted %2',
  392. [$path, $this->getWarningMessage()]
  393. )
  394. );
  395. }
  396. return $result;
  397. }
  398. /**
  399. * Change permissions of given path
  400. *
  401. * @param string $path
  402. * @param int $permissions
  403. * @return bool
  404. * @throws FileSystemException
  405. */
  406. public function changePermissions($path, $permissions)
  407. {
  408. $result = @chmod($this->getScheme() . $path, $permissions);
  409. if (!$result) {
  410. throw new FileSystemException(
  411. new \Magento\Framework\Phrase(
  412. 'Cannot change permissions for path "%1" %2',
  413. [$path, $this->getWarningMessage()]
  414. )
  415. );
  416. }
  417. return $result;
  418. }
  419. /**
  420. * Recursively change permissions of given path
  421. *
  422. * @param string $path
  423. * @param int $dirPermissions
  424. * @param int $filePermissions
  425. * @return bool
  426. * @throws FileSystemException
  427. */
  428. public function changePermissionsRecursively($path, $dirPermissions, $filePermissions)
  429. {
  430. $result = true;
  431. if ($this->isFile($path)) {
  432. $result = @chmod($path, $filePermissions);
  433. } else {
  434. $result = @chmod($path, $dirPermissions);
  435. }
  436. if (!$result) {
  437. throw new FileSystemException(
  438. new \Magento\Framework\Phrase(
  439. 'Cannot change permissions for path "%1" %2',
  440. [$path, $this->getWarningMessage()]
  441. )
  442. );
  443. }
  444. $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS;
  445. $iterator = new \RecursiveIteratorIterator(
  446. new \RecursiveDirectoryIterator($path, $flags),
  447. \RecursiveIteratorIterator::CHILD_FIRST
  448. );
  449. /** @var \FilesystemIterator $entity */
  450. foreach ($iterator as $entity) {
  451. if ($entity->isDir()) {
  452. $result = @chmod($entity->getPathname(), $dirPermissions);
  453. } else {
  454. $result = @chmod($entity->getPathname(), $filePermissions);
  455. }
  456. if (!$result) {
  457. throw new FileSystemException(
  458. new \Magento\Framework\Phrase(
  459. 'Cannot change permissions for path "%1" %2',
  460. [$path, $this->getWarningMessage()]
  461. )
  462. );
  463. }
  464. }
  465. return $result;
  466. }
  467. /**
  468. * Sets access and modification time of file.
  469. *
  470. * @param string $path
  471. * @param int|null $modificationTime
  472. * @return bool
  473. * @throws FileSystemException
  474. */
  475. public function touch($path, $modificationTime = null)
  476. {
  477. if (!$modificationTime) {
  478. $result = @touch($this->getScheme() . $path);
  479. } else {
  480. $result = @touch($this->getScheme() . $path, $modificationTime);
  481. }
  482. if (!$result) {
  483. throw new FileSystemException(
  484. new \Magento\Framework\Phrase(
  485. 'The file or directory "%1" cannot be touched %2',
  486. [$path, $this->getWarningMessage()]
  487. )
  488. );
  489. }
  490. return $result;
  491. }
  492. /**
  493. * Write contents to file in given path
  494. *
  495. * @param string $path
  496. * @param string $content
  497. * @param string|null $mode
  498. * @return int The number of bytes that were written.
  499. * @throws FileSystemException
  500. */
  501. public function filePutContents($path, $content, $mode = null)
  502. {
  503. $result = @file_put_contents($this->getScheme() . $path, $content, $mode);
  504. if (!$result) {
  505. throw new FileSystemException(
  506. new \Magento\Framework\Phrase(
  507. 'The specified "%1" file could not be written %2',
  508. [$path, $this->getWarningMessage()]
  509. )
  510. );
  511. }
  512. return $result;
  513. }
  514. /**
  515. * Open file
  516. *
  517. * @param string $path
  518. * @param string $mode
  519. * @return resource file
  520. * @throws FileSystemException
  521. */
  522. public function fileOpen($path, $mode)
  523. {
  524. $result = @fopen($this->getScheme() . $path, $mode);
  525. if (!$result) {
  526. throw new FileSystemException(
  527. new \Magento\Framework\Phrase('File "%1" cannot be opened %2', [$path, $this->getWarningMessage()])
  528. );
  529. }
  530. return $result;
  531. }
  532. /**
  533. * Reads the line content from file pointer (with specified number of bytes from the current position).
  534. *
  535. * @param resource $resource
  536. * @param int $length
  537. * @param string $ending [optional]
  538. * @return string
  539. * @throws FileSystemException
  540. */
  541. public function fileReadLine($resource, $length, $ending = null)
  542. {
  543. $result = @stream_get_line($resource, $length, $ending);
  544. if (false === $result) {
  545. throw new FileSystemException(
  546. new \Magento\Framework\Phrase('File cannot be read %1', [$this->getWarningMessage()])
  547. );
  548. }
  549. return $result;
  550. }
  551. /**
  552. * Reads the specified number of bytes from the current position.
  553. *
  554. * @param resource $resource
  555. * @param int $length
  556. * @return string
  557. * @throws FileSystemException
  558. */
  559. public function fileRead($resource, $length)
  560. {
  561. $result = @fread($resource, $length);
  562. if ($result === false) {
  563. throw new FileSystemException(
  564. new \Magento\Framework\Phrase('File cannot be read %1', [$this->getWarningMessage()])
  565. );
  566. }
  567. return $result;
  568. }
  569. /**
  570. * Reads one CSV row from the file
  571. *
  572. * @param resource $resource
  573. * @param int $length [optional]
  574. * @param string $delimiter [optional]
  575. * @param string $enclosure [optional]
  576. * @param string $escape [optional]
  577. * @return array|bool|null
  578. * @throws FileSystemException
  579. */
  580. public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\')
  581. {
  582. $result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape);
  583. if ($result === null) {
  584. throw new FileSystemException(
  585. new \Magento\Framework\Phrase('Wrong CSV handle %1', [$this->getWarningMessage()])
  586. );
  587. }
  588. return $result;
  589. }
  590. /**
  591. * Returns position of read/write pointer
  592. *
  593. * @param resource $resource
  594. * @return int
  595. * @throws FileSystemException
  596. */
  597. public function fileTell($resource)
  598. {
  599. $result = @ftell($resource);
  600. if ($result === null) {
  601. throw new FileSystemException(
  602. new \Magento\Framework\Phrase('Error occurred during execution %1', [$this->getWarningMessage()])
  603. );
  604. }
  605. return $result;
  606. }
  607. /**
  608. * Seeks to the specified offset
  609. *
  610. * @param resource $resource
  611. * @param int $offset
  612. * @param int $whence
  613. * @return int
  614. * @throws FileSystemException
  615. */
  616. public function fileSeek($resource, $offset, $whence = SEEK_SET)
  617. {
  618. $result = @fseek($resource, $offset, $whence);
  619. if ($result === -1) {
  620. throw new FileSystemException(
  621. new \Magento\Framework\Phrase(
  622. 'Error occurred during execution of fileSeek %1',
  623. [$this->getWarningMessage()]
  624. )
  625. );
  626. }
  627. return $result;
  628. }
  629. /**
  630. * Returns true if pointer at the end of file or in case of exception
  631. *
  632. * @param resource $resource
  633. * @return boolean
  634. */
  635. public function endOfFile($resource)
  636. {
  637. return feof($resource);
  638. }
  639. /**
  640. * Close file
  641. *
  642. * @param resource $resource
  643. * @return boolean
  644. * @throws FileSystemException
  645. */
  646. public function fileClose($resource)
  647. {
  648. $result = @fclose($resource);
  649. if (!$result) {
  650. throw new FileSystemException(
  651. new \Magento\Framework\Phrase(
  652. 'Error occurred during execution of fileClose %1',
  653. [$this->getWarningMessage()]
  654. )
  655. );
  656. }
  657. return $result;
  658. }
  659. /**
  660. * Writes data to file
  661. *
  662. * @param resource $resource
  663. * @param string $data
  664. * @return int
  665. * @throws FileSystemException
  666. */
  667. public function fileWrite($resource, $data)
  668. {
  669. $result = @fwrite($resource, $data);
  670. if (false === $result) {
  671. throw new FileSystemException(
  672. new \Magento\Framework\Phrase(
  673. 'Error occurred during execution of fileWrite %1',
  674. [$this->getWarningMessage()]
  675. )
  676. );
  677. }
  678. return $result;
  679. }
  680. /**
  681. * Writes one CSV row to the file.
  682. *
  683. * @param resource $resource
  684. * @param array $data
  685. * @param string $delimiter
  686. * @param string $enclosure
  687. * @return int
  688. * @throws FileSystemException
  689. */
  690. public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure = '"')
  691. {
  692. /**
  693. * Security enhancement for CSV data processing by Excel-like applications.
  694. * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702
  695. *
  696. * @var $value string|\Magento\Framework\Phrase
  697. */
  698. foreach ($data as $key => $value) {
  699. if (!is_string($value)) {
  700. $value = (string)$value;
  701. }
  702. if (isset($value[0]) && in_array($value[0], ['=', '+', '-'])) {
  703. $data[$key] = ' ' . $value;
  704. }
  705. }
  706. $result = @fputcsv($resource, $data, $delimiter, $enclosure);
  707. if (!$result) {
  708. throw new FileSystemException(
  709. new \Magento\Framework\Phrase(
  710. 'Error occurred during execution of filePutCsv %1',
  711. [$this->getWarningMessage()]
  712. )
  713. );
  714. }
  715. return $result;
  716. }
  717. /**
  718. * Flushes the output
  719. *
  720. * @param resource $resource
  721. * @return bool
  722. * @throws FileSystemException
  723. */
  724. public function fileFlush($resource)
  725. {
  726. $result = @fflush($resource);
  727. if (!$result) {
  728. throw new FileSystemException(
  729. new \Magento\Framework\Phrase(
  730. 'Error occurred during execution of fileFlush %1',
  731. [$this->getWarningMessage()]
  732. )
  733. );
  734. }
  735. return $result;
  736. }
  737. /**
  738. * Lock file in selected mode
  739. *
  740. * @param resource $resource
  741. * @param int $lockMode
  742. * @return bool
  743. * @throws FileSystemException
  744. */
  745. public function fileLock($resource, $lockMode = LOCK_EX)
  746. {
  747. $result = @flock($resource, $lockMode);
  748. if (!$result) {
  749. throw new FileSystemException(
  750. new \Magento\Framework\Phrase(
  751. 'Error occurred during execution of fileLock %1',
  752. [$this->getWarningMessage()]
  753. )
  754. );
  755. }
  756. return $result;
  757. }
  758. /**
  759. * Unlock file
  760. *
  761. * @param resource $resource
  762. * @return bool
  763. * @throws FileSystemException
  764. */
  765. public function fileUnlock($resource)
  766. {
  767. $result = @flock($resource, LOCK_UN);
  768. if (!$result) {
  769. throw new FileSystemException(
  770. new \Magento\Framework\Phrase(
  771. 'Error occurred during execution of fileUnlock %1',
  772. [$this->getWarningMessage()]
  773. )
  774. );
  775. }
  776. return $result;
  777. }
  778. /**
  779. * @param string $basePath
  780. * @param string $path
  781. * @param string|null $scheme
  782. * @return string
  783. */
  784. public function getAbsolutePath($basePath, $path, $scheme = null)
  785. {
  786. return $this->getScheme($scheme) . $basePath . ltrim($this->fixSeparator($path), '/');
  787. }
  788. /**
  789. * Retrieves relative path
  790. *
  791. * @param string $basePath
  792. * @param string $path
  793. * @return string
  794. */
  795. public function getRelativePath($basePath, $path = null)
  796. {
  797. $path = $this->fixSeparator($path);
  798. if (strpos($path, $basePath) === 0 || $basePath == $path . '/') {
  799. $result = substr($path, strlen($basePath));
  800. } else {
  801. $result = $path;
  802. }
  803. return $result;
  804. }
  805. /**
  806. * Fixes path separator
  807. * Utility method.
  808. *
  809. * @param string $path
  810. * @return string
  811. */
  812. protected function fixSeparator($path)
  813. {
  814. return str_replace('\\', '/', $path);
  815. }
  816. /**
  817. * Return path with scheme
  818. *
  819. * @param null|string $scheme
  820. * @return string
  821. */
  822. protected function getScheme($scheme = null)
  823. {
  824. return $scheme ? $scheme . '://' : '';
  825. }
  826. /**
  827. * Read directory recursively
  828. *
  829. * @param string $path
  830. * @return string[]
  831. * @throws FileSystemException
  832. */
  833. public function readDirectoryRecursively($path = null)
  834. {
  835. $result = [];
  836. $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS;
  837. try {
  838. $iterator = new \RecursiveIteratorIterator(
  839. new \RecursiveDirectoryIterator($path, $flags),
  840. \RecursiveIteratorIterator::CHILD_FIRST
  841. );
  842. /** @var \FilesystemIterator $file */
  843. foreach ($iterator as $file) {
  844. $result[] = $file->getPathname();
  845. }
  846. } catch (\Exception $e) {
  847. throw new FileSystemException(new \Magento\Framework\Phrase($e->getMessage()), $e);
  848. }
  849. return $result;
  850. }
  851. /**
  852. * Get real path
  853. *
  854. * @param string $path
  855. *
  856. * @return string|bool
  857. */
  858. public function getRealPath($path)
  859. {
  860. return realpath($path);
  861. }
  862. /**
  863. * Return correct path for link
  864. *
  865. * @param string $path
  866. * @return mixed
  867. */
  868. public function getRealPathSafety($path)
  869. {
  870. if (strpos($path, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) === false) {
  871. return $path;
  872. }
  873. $pathParts = explode(DIRECTORY_SEPARATOR, $path);
  874. $realPath = [];
  875. foreach ($pathParts as $pathPart) {
  876. if ($pathPart == '.') {
  877. continue;
  878. }
  879. if ($pathPart == '..') {
  880. array_pop($realPath);
  881. continue;
  882. }
  883. $realPath[] = $pathPart;
  884. }
  885. return implode(DIRECTORY_SEPARATOR, $realPath);
  886. }
  887. }