PageRenderTime 49ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/user/plugins/gantry5/src/classes/Gantry/Component/Filesystem/Folder.php

https://gitlab.com/akbaryu/project_magang_blog_grav
PHP | 346 lines | 228 code | 33 blank | 85 comment | 26 complexity | 230b90ddcd465669f18c4c7ccaa36ecb MD5 | raw file
  1. <?php
  2. /**
  3. * @package Gantry5
  4. * @author RocketTheme http://www.rockettheme.com
  5. * @copyright Copyright (C) 2007 - 2016 RocketTheme, LLC
  6. * @license Dual License: MIT or GNU/GPLv2 and later
  7. *
  8. * http://opensource.org/licenses/MIT
  9. * http://www.gnu.org/licenses/gpl-2.0.html
  10. *
  11. * Gantry Framework code that extends GPL code is considered GNU/GPLv2 and later
  12. */
  13. namespace Gantry\Component\Filesystem;
  14. /**
  15. * Folder helper class.
  16. *
  17. * @author RocketTheme
  18. * @license MIT
  19. */
  20. abstract class Folder
  21. {
  22. /**
  23. * Recursively find the last modified time under given path.
  24. *
  25. * @param string $path
  26. * @return int
  27. */
  28. public static function lastModifiedFolder($path)
  29. {
  30. $last_modified = 0;
  31. $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
  32. $iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
  33. /** @var \RecursiveDirectoryIterator $file */
  34. foreach ($iterator as $file) {
  35. $dir_modified = $file->getMTime();
  36. if ($dir_modified > $last_modified) {
  37. $last_modified = $dir_modified;
  38. }
  39. }
  40. return $last_modified;
  41. }
  42. /**
  43. * Get relative path between target and base path. If path isn't relative, return full path.
  44. *
  45. * @param string $path
  46. * @param string $base
  47. * @return string
  48. */
  49. public static function getRelativePath($path, $base = GANTRY5_ROOT)
  50. {
  51. $base = preg_replace('![\\\/]+!', '/', $base);
  52. $path = preg_replace('![\\\/]+!', '/', $path);
  53. if (strpos($path, $base) === 0) {
  54. $path = ltrim(substr($path, strlen($base)), '/');
  55. }
  56. return $path;
  57. }
  58. /**
  59. * Get relative path between target and base path. If path isn't relative, return full path.
  60. *
  61. * @param string $path
  62. * @param string $base
  63. * @return string
  64. */
  65. public static function getRelativePathDotDot($path, $base)
  66. {
  67. $base = preg_replace('![\\\/]+!', '/', $base);
  68. $path = preg_replace('![\\\/]+!', '/', $path);
  69. if ($path === $base) {
  70. return '';
  71. }
  72. $baseParts = explode('/', isset($base[0]) && '/' === $base[0] ? substr($base, 1) : $base);
  73. $pathParts = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path);
  74. array_pop($baseParts);
  75. $lastPart = array_pop($pathParts);
  76. foreach ($baseParts as $i => $directory) {
  77. if (isset($pathParts[$i]) && $pathParts[$i] === $directory) {
  78. unset($baseParts[$i], $pathParts[$i]);
  79. } else {
  80. break;
  81. }
  82. }
  83. $pathParts[] = $lastPart;
  84. $path = str_repeat('../', count($baseParts)) . implode('/', $pathParts);
  85. return '' === $path
  86. || '/' === $path[0]
  87. || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
  88. ? "./$path" : $path;
  89. }
  90. /**
  91. * Shift first directory out of the path.
  92. *
  93. * @param string $path
  94. * @return string
  95. */
  96. public static function shift(&$path)
  97. {
  98. $parts = explode('/', trim($path, '/'), 2);
  99. $result = array_shift($parts);
  100. $path = array_shift($parts);
  101. return $result ?: null;
  102. }
  103. /**
  104. * Return recursive list of all files and directories under given path.
  105. *
  106. * @param string $path
  107. * @param array $params
  108. * @return array
  109. * @throws \RuntimeException
  110. */
  111. public static function all($path, array $params = array())
  112. {
  113. if ($path === false) {
  114. throw new \RuntimeException("Path to {$path} doesn't exist.");
  115. }
  116. $compare = isset($params['compare']) ? 'get' . $params['compare'] : null;
  117. $pattern = isset($params['pattern']) ? $params['pattern'] : null;
  118. $filters = isset($params['filters']) ? $params['filters'] : null;
  119. $recursive = isset($params['recursive']) ? $params['recursive'] : true;
  120. $levels = isset($params['levels']) ? $params['levels'] : -1;
  121. $key = isset($params['key']) ? 'get' . $params['key'] : null;
  122. $value = isset($params['value']) ? 'get' . $params['value'] : ($recursive ? 'getSubPathname' : 'getFilename');
  123. $folders = isset($params['folders']) ? $params['folders'] : true;
  124. $files = isset($params['files']) ? $params['files'] : true;
  125. if ($recursive) {
  126. $directory = new \RecursiveDirectoryIterator($path,
  127. \RecursiveDirectoryIterator::SKIP_DOTS + \FilesystemIterator::UNIX_PATHS + \FilesystemIterator::CURRENT_AS_SELF);
  128. $iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
  129. $iterator->setMaxDepth(max($levels, -1));
  130. } else {
  131. $iterator = new \FilesystemIterator($path);
  132. }
  133. $results = array();
  134. /** @var \RecursiveDirectoryIterator $file */
  135. foreach ($iterator as $file) {
  136. // Ignore hidden files.
  137. if ($file->getFilename()[0] == '.') {
  138. continue;
  139. }
  140. if (!$folders && $file->isDir()) {
  141. continue;
  142. }
  143. if (!$files && $file->isFile()) {
  144. continue;
  145. }
  146. if ($compare && $pattern && !preg_match($pattern, $file->{$compare}())) {
  147. continue;
  148. }
  149. $fileKey = $key ? $file->{$key}() : null;
  150. $filePath = $file->{$value}();
  151. if ($filters) {
  152. if (isset($filters['key'])) {
  153. $pre = !empty($filters['pre-key']) ? $filters['pre-key'] : '';
  154. $fileKey = $pre . preg_replace($filters['key'], '', $fileKey);
  155. }
  156. if (isset($filters['value'])) {
  157. $filter = $filters['value'];
  158. if (is_callable($filter)) {
  159. $filePath = call_user_func($filter, $file);
  160. } else {
  161. $filePath = preg_replace($filter, '', $filePath);
  162. }
  163. }
  164. }
  165. if ($fileKey !== null) {
  166. $results[$fileKey] = $filePath;
  167. } else {
  168. $results[] = $filePath;
  169. }
  170. }
  171. return $results;
  172. }
  173. /**
  174. * Recursively copy directory in filesystem.
  175. *
  176. * @param string $source
  177. * @param string $target
  178. * @param string $ignore Ignore files matching pattern (regular expression).
  179. * @throws \RuntimeException
  180. */
  181. public static function copy($source, $target, $ignore = null)
  182. {
  183. $source = rtrim($source, '\\/');
  184. $target = rtrim($target, '\\/');
  185. if (!is_dir($source)) {
  186. throw new \RuntimeException('Cannot copy non-existing folder.');
  187. }
  188. // Make sure that path to the target exists before copying.
  189. self::create($target);
  190. $success = true;
  191. // Go through all sub-directories and copy everything.
  192. $files = self::all($source);
  193. foreach ($files as $file) {
  194. if ($ignore && preg_match($ignore, $file)) {
  195. continue;
  196. }
  197. $src = $source .'/'. $file;
  198. $dst = $target .'/'. $file;
  199. if (is_dir($src)) {
  200. // Create current directory (if it doesn't exist).
  201. if (!is_dir($dst)) {
  202. $success &= @mkdir($dst, 0777, true);
  203. }
  204. } else {
  205. // Or copy current file.
  206. $success &= @copy($src, $dst);
  207. }
  208. }
  209. if (!$success) {
  210. $error = error_get_last();
  211. throw new \RuntimeException($error['message']);
  212. }
  213. // Make sure that the change will be detected when caching.
  214. @touch(dirname($target));
  215. }
  216. /**
  217. * Move directory in filesystem.
  218. *
  219. * @param string $source
  220. * @param string $target
  221. * @throws \RuntimeException
  222. */
  223. public static function move($source, $target)
  224. {
  225. if (!is_dir($source)) {
  226. throw new \RuntimeException('Cannot move non-existing folder.');
  227. }
  228. // Make sure that path to the target exists before moving.
  229. self::create(dirname($target));
  230. // Just rename the directory.
  231. $success = @rename($source, $target);
  232. if (!$success) {
  233. $error = error_get_last();
  234. throw new \RuntimeException($error['message']);
  235. }
  236. // Make sure that the change will be detected when caching.
  237. @touch(dirname($source));
  238. @touch(dirname($target));
  239. }
  240. /**
  241. * Recursively delete directory from filesystem.
  242. *
  243. * @param string $target
  244. * @param bool $include_target
  245. * @throws \RuntimeException
  246. */
  247. public static function delete($target, $include_target = true)
  248. {
  249. if (!$target) { return; }
  250. if (!is_dir($target)) {
  251. throw new \RuntimeException('Cannot delete non-existing folder.');
  252. }
  253. $success = self::doDelete($target, $include_target);
  254. if (!$success) {
  255. $error = error_get_last();
  256. throw new \RuntimeException($error['message']);
  257. }
  258. // Make sure that the change will be detected when caching.
  259. if ($include_target) {
  260. @touch(dirname($target));
  261. } else {
  262. @touch($target);
  263. }
  264. }
  265. /**
  266. * @param string $folder
  267. * @throws \RuntimeException
  268. * @internal
  269. */
  270. public static function create($folder)
  271. {
  272. if (is_dir($folder)) {
  273. return;
  274. }
  275. $success = @mkdir($folder, 0777, true);
  276. if (!$success) {
  277. $error = error_get_last();
  278. throw new \RuntimeException($error['message']);
  279. }
  280. }
  281. /**
  282. * @param string $folder
  283. * @param bool $include_target
  284. * @return bool
  285. * @internal
  286. */
  287. protected static function doDelete($folder, $include_target = true)
  288. {
  289. // Special case for symbolic links.
  290. if (is_link($folder)) {
  291. return @unlink($folder);
  292. }
  293. // Go through all items in filesystem and recursively remove everything.
  294. $files = array_diff(scandir($folder), array('.', '..'));
  295. foreach ($files as $file) {
  296. $path = "{$folder}/{$file}";
  297. (is_dir($path)) ? self::doDelete($path) : @unlink($path);
  298. }
  299. return $include_target ? @rmdir($folder) : true;
  300. }
  301. }