1<?php 2/** 3 * Copyright since 2007 PrestaShop SA and Contributors 4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA 5 * 6 * NOTICE OF LICENSE 7 * 8 * This source file is subject to the Open Software License (OSL 3.0) 9 * that is bundled with this package in the file LICENSE.md. 10 * It is also available through the world-wide-web at this URL: 11 * https://opensource.org/licenses/OSL-3.0 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@prestashop.com so we can send you a copy immediately. 15 * 16 * DISCLAIMER 17 * 18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 19 * versions in the future. If you wish to customize PrestaShop for your 20 * needs please refer to https://devdocs.prestashop.com/ for more information. 21 * 22 * @author PrestaShop SA and Contributors <contact@prestashop.com> 23 * @copyright Since 2007 PrestaShop SA and Contributors 24 * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) 25 */ 26 27namespace PrestaShop\PrestaShop\Core\Foundation\Filesystem; 28 29use SplFileInfo; 30 31class FileSystem 32{ 33 /** 34 * Default mode for directories 35 */ 36 public const DEFAULT_MODE_FOLDER = 0755; 37 38 /** 39 * Default mode for files 40 */ 41 public const DEFAULT_MODE_FILE = 0644; 42 43 /** 44 * Replaces directory separators with the system's native one 45 * and trims the trailing separator. 46 */ 47 public function normalizePath($path) 48 { 49 return rtrim( 50 str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path), 51 DIRECTORY_SEPARATOR 52 ); 53 } 54 55 private function joinTwoPaths($a, $b) 56 { 57 return $this->normalizePath($a) . DIRECTORY_SEPARATOR . $this->normalizePath($b); 58 } 59 60 /** 61 * Joins an arbitrary number of paths, normalizing them along the way. 62 */ 63 public function joinPaths() 64 { 65 if (func_num_args() < 2) { 66 throw new Exception('joinPaths requires at least 2 arguments.'); 67 } 68 if (func_num_args() === 2) { 69 $arg_O = func_get_arg(0); 70 $arg_1 = func_get_arg(1); 71 72 return $this->joinTwoPaths($arg_O, $arg_1); 73 } 74 75 $func_args = func_get_args(); 76 $arg_0 = func_get_arg(0); 77 78 return $this->joinPaths( 79 $arg_0, 80 call_user_func_array( 81 [$this, 82 'joinPaths', ], 83 array_slice($func_args, 1) 84 ) 85 ); 86 } 87 88 /** 89 * Performs a depth first listing of directory entries. 90 * Throws exception if $path is not a file. 91 * If $path is a file and not a directory, just gets the file info for it 92 * and return it in an array. 93 * 94 * @param string $path 95 * 96 * @return SplFileInfo[] Array of SplFileInfo object indexed by file path 97 */ 98 public function listEntriesRecursively($path) 99 { 100 if (!file_exists($path)) { 101 throw new Exception(sprintf('No such file or directory: %s', $path)); 102 } 103 104 if (!is_dir($path)) { 105 throw new Exception(sprintf('%s is not a directory', $path)); 106 } 107 108 $entries = []; 109 110 foreach (scandir($path) as $entry) { 111 if ($entry === '.' || $entry === '..') { 112 continue; 113 } 114 115 $newPath = $this->joinPaths($path, $entry); 116 $info = new SplFileInfo($newPath); 117 118 $entries[$newPath] = $info; 119 120 if ($info->isDir()) { 121 $entries = array_merge( 122 $entries, 123 $this->listEntriesRecursively($newPath) 124 ); 125 } 126 } 127 128 return $entries; 129 } 130 131 /** 132 * Filter used by listFilesRecursively. 133 */ 134 private function matchOnlyFiles(SplFileInfo $info) 135 { 136 return $info->isFile(); 137 } 138 139 /** 140 * Same as listEntriesRecursively but returns only files. 141 */ 142 public function listFilesRecursively($path) 143 { 144 return array_filter( 145 $this->listEntriesRecursively($path), 146 [$this, 'matchOnlyFiles'] 147 ); 148 } 149} 150