PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/SyracavaPHP/syracava/ext/pear/File/Util.php

http://syracava.googlecode.com/
PHP | 482 lines | 310 code | 37 blank | 135 comment | 52 complexity | 386ba97cdc98371284a7eaa62abe127f MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-2.1
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * File::Util
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * LICENSE: This source file is subject to version 3.0 of the PHP license
  9. * that is available through the world-wide-web at the following URI:
  10. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  11. * the PHP License and are unable to obtain it through the web, please
  12. * send a note to license@php.net so we can mail you a copy immediately.
  13. *
  14. * @category File
  15. * @package File
  16. * @author Michael Wallner <mike@php.net>
  17. * @copyright 2004-2005 Michael Wallner
  18. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  19. * @version CVS: $Id: Util.php 125 2009-08-21 01:35:18Z takuji.mezawa $
  20. * @link http://pear.php.net/package/File
  21. */
  22. /**#@+
  23. * Sorting Constants
  24. */
  25. define('FILE_SORT_NONE', 0);
  26. define('FILE_SORT_REVERSE', 1);
  27. define('FILE_SORT_NAME', 2);
  28. define('FILE_SORT_SIZE', 4);
  29. define('FILE_SORT_DATE', 8);
  30. define('FILE_SORT_RANDOM', 16);
  31. /**#@-*/
  32. /**#@+
  33. * Listing Constants
  34. */
  35. define('FILE_LIST_FILES', 1);
  36. define('FILE_LIST_DIRS', 2);
  37. define('FILE_LIST_DOTS', 4);
  38. define('FILE_LIST_ALL', FILE_LIST_FILES | FILE_LIST_DIRS | FILE_LIST_DOTS);
  39. /**#@-*/
  40. /**
  41. * @ignore
  42. */
  43. define('FILE_WIN32', defined('OS_WINDOWS') ? OS_WINDOWS : !strncasecmp(PHP_OS, 'win', 3));
  44. /**
  45. * File_Util
  46. *
  47. * File and directory utility functions.
  48. *
  49. * @access public
  50. * @static
  51. */
  52. class File_Util
  53. {
  54. /**
  55. * Returns a string path built from the array $pathParts. Where a join
  56. * occurs multiple separators are removed. Joins using the optional
  57. * separator, defaulting to the PHP DIRECTORY_SEPARATOR constant.
  58. *
  59. * @static
  60. * @access public
  61. * @param array $parts Array containing the parts to be joined
  62. * @param string $separator The directory seperator
  63. */
  64. function buildPath($parts, $separator = DIRECTORY_SEPARATOR)
  65. {
  66. $qs = '/^'. preg_quote($separator, '/') .'+$/';
  67. for ($i = 0, $c = count($parts); $i < $c; $i++) {
  68. if (!strlen($parts[$i]) || preg_match($qs, $parts[$i])) {
  69. unset($parts[$i]);
  70. } elseif (0 == $i) {
  71. $parts[$i] = rtrim($parts[$i], $separator);
  72. } elseif ($c - 1 == $i) {
  73. $parts[$i] = ltrim($parts[$i], $separator);
  74. } else {
  75. $parts[$i] = trim($parts[$i], $separator);
  76. }
  77. }
  78. return implode($separator, $parts);
  79. }
  80. /**
  81. * Returns a path without leading / or C:\. If this is not
  82. * present the path is returned as is.
  83. *
  84. * @static
  85. * @access public
  86. * @param string $path The path to be processed
  87. * @return string The processed path or the path as is
  88. */
  89. function skipRoot($path)
  90. {
  91. if (File_Util::isAbsolute($path)) {
  92. if (FILE_WIN32) {
  93. return substr($path, $path{3} == '\\' ? 4 : 3);
  94. }
  95. return ltrim($path, '/');
  96. }
  97. return $path;
  98. }
  99. /**
  100. * Returns the temp directory according to either the TMP, TMPDIR, or
  101. * TEMP env variables. If these are not set it will also check for the
  102. * existence of /tmp, %WINDIR%\temp
  103. *
  104. * @static
  105. * @access public
  106. * @return string The system tmp directory
  107. */
  108. function tmpDir()
  109. {
  110. if (FILE_WIN32) {
  111. if (isset($_ENV['TEMP'])) {
  112. return $_ENV['TEMP'];
  113. }
  114. if (isset($_ENV['TMP'])) {
  115. return $_ENV['TMP'];
  116. }
  117. if (isset($_ENV['windir'])) {
  118. return $_ENV['windir'] . '\\temp';
  119. }
  120. if (isset($_ENV['SystemRoot'])) {
  121. return $_ENV['SystemRoot'] . '\\temp';
  122. }
  123. if (isset($_SERVER['TEMP'])) {
  124. return $_SERVER['TEMP'];
  125. }
  126. if (isset($_SERVER['TMP'])) {
  127. return $_SERVER['TMP'];
  128. }
  129. if (isset($_SERVER['windir'])) {
  130. return $_SERVER['windir'] . '\\temp';
  131. }
  132. if (isset($_SERVER['SystemRoot'])) {
  133. return $_SERVER['SystemRoot'] . '\\temp';
  134. }
  135. return '\temp';
  136. }
  137. if (isset($_ENV['TMPDIR'])) {
  138. return $_ENV['TMPDIR'];
  139. }
  140. if (isset($_SERVER['TMPDIR'])) {
  141. return $_SERVER['TMPDIR'];
  142. }
  143. return '/tmp';
  144. }
  145. /**
  146. * Returns a temporary filename using tempnam() and File::tmpDir().
  147. *
  148. * @static
  149. * @access public
  150. * @param string $dirname Optional directory name for the tmp file
  151. * @return string Filename and path of the tmp file
  152. */
  153. function tmpFile($dirname = null)
  154. {
  155. if (!isset($dirname)) {
  156. $dirname = File_Util::tmpDir();
  157. }
  158. return tempnam($dirname, 'temp.');
  159. }
  160. /**
  161. * Returns boolean based on whether given path is absolute or not.
  162. *
  163. * @static
  164. * @access public
  165. * @param string $path Given path
  166. * @return boolean True if the path is absolute, false if it is not
  167. */
  168. function isAbsolute($path)
  169. {
  170. if (preg_match('/(?:\/|\\\)\.\.(?=\/|$)/', $path)) {
  171. return false;
  172. }
  173. if (FILE_WIN32) {
  174. return preg_match('/^[a-zA-Z]:(\\\|\/)/', $path);
  175. }
  176. return ($path{0} == '/') || ($path{0} == '~');
  177. }
  178. /**
  179. * Checks for a file's existence, taking the current include path
  180. * into consideration
  181. *
  182. * This method can be called statically
  183. * (e.g., File_Util::isIncludable('config.php'))
  184. *
  185. * @param string $file
  186. * @param string $sep the directory separator (optional)
  187. * @return string the includable path
  188. * @access public
  189. * @static
  190. */
  191. function isIncludable($file, $sep = DIRECTORY_SEPARATOR)
  192. {
  193. foreach ((array) explode(PATH_SEPARATOR, ini_get('include_path')) as $path) {
  194. if (file_exists($path .= $sep . $file)) {
  195. return $path;
  196. }
  197. }
  198. if (file_exists($file)) {
  199. return $file;
  200. }
  201. return NULL;
  202. }
  203. /**
  204. * Get path relative to another path
  205. *
  206. * @static
  207. * @access public
  208. * @return string
  209. * @param string $path
  210. * @param string $root
  211. * @param string $separator
  212. */
  213. function relativePath($path, $root, $separator = DIRECTORY_SEPARATOR)
  214. {
  215. $path = File_Util::realpath($path, $separator);
  216. $root = File_Util::realpath($root, $separator);
  217. $dirs = explode($separator, $path);
  218. $comp = explode($separator, $root);
  219. if (FILE_WIN32) {
  220. if (strcasecmp($dirs[0], $comp[0])) {
  221. return $path;
  222. }
  223. unset($dirs[0], $comp[0]);
  224. }
  225. foreach ($comp as $i => $part) {
  226. if (isset($dirs[$i]) && $part == $dirs[$i]) {
  227. unset($dirs[$i], $comp[$i]);
  228. } else {
  229. break;
  230. }
  231. }
  232. return str_repeat('..' . $separator, count($comp)) . implode($separator, $dirs);
  233. }
  234. /**
  235. * Get real path (works with non-existant paths)
  236. *
  237. * @static
  238. * @access public
  239. * @return string
  240. * @param string $path
  241. * @param string $separator
  242. */
  243. function realPath($path, $separator = DIRECTORY_SEPARATOR)
  244. {
  245. if (!strlen($path)) {
  246. return $separator;
  247. }
  248. $drive = '';
  249. if (FILE_WIN32) {
  250. $path = preg_replace('/[\\\\\/]/', $separator, $path);
  251. if (preg_match('/([a-zA-Z]\:)(.*)/', $path, $matches)) {
  252. $drive = $matches[1];
  253. $path = $matches[2];
  254. } else {
  255. $cwd = getcwd();
  256. $drive = substr($cwd, 0, 2);
  257. if ($path{0} !== $separator{0}) {
  258. $path = substr($cwd, 3) . $separator . $path;
  259. }
  260. }
  261. } elseif ($path{0} !== $separator) {
  262. $path = getcwd() . $separator . $path;
  263. }
  264. $dirStack = array();
  265. foreach (explode($separator, $path) as $dir) {
  266. if (strlen($dir) && $dir !== '.') {
  267. if ($dir == '..') {
  268. array_pop($dirStack);
  269. } else {
  270. $dirStack[] = $dir;
  271. }
  272. }
  273. }
  274. return $drive . $separator . implode($separator, $dirStack);
  275. }
  276. /**
  277. * Check whether path is in root path
  278. *
  279. * @static
  280. * @access public
  281. * @return bool
  282. * @param string $path
  283. * @param string $root
  284. */
  285. function pathInRoot($path, $root)
  286. {
  287. static $realPaths = array();
  288. if (!isset($realPaths[$root])) {
  289. $realPaths[$root] = File_Util::realPath($root);
  290. }
  291. return false !== strstr(File_Util::realPath($path), $realPaths[$root]);
  292. }
  293. /**
  294. * List Directory
  295. *
  296. * The final argument, $cb, is a callback that either evaluates to true or
  297. * false and performs a filter operation, or it can also modify the
  298. * directory/file names returned. To achieve the latter effect use as
  299. * follows:
  300. *
  301. * <code>
  302. * <?php
  303. * function uc(&$filename) {
  304. * $filename = strtoupper($filename);
  305. * return true;
  306. * }
  307. * $entries = File_Util::listDir('.', FILE_LIST_ALL, FILE_SORT_NONE, 'uc');
  308. * foreach ($entries as $e) {
  309. * echo $e->name, "\n";
  310. * }
  311. * ?>
  312. * </code>
  313. *
  314. * @static
  315. * @access public
  316. * @return array
  317. * @param string $path
  318. * @param int $list
  319. * @param int $sort
  320. * @param mixed $cb
  321. */
  322. function listDir($path, $list = FILE_LIST_ALL, $sort = FILE_SORT_NONE, $cb = null)
  323. {
  324. if (!strlen($path) || !is_dir($path)) {
  325. return null;
  326. }
  327. $entries = array();
  328. for ($dir = dir($path); false !== $entry = $dir->read(); ) {
  329. if ($list & FILE_LIST_DOTS || $entry{0} !== '.') {
  330. $isRef = ($entry === '.' || $entry === '..');
  331. $isDir = $isRef || is_dir($path .'/'. $entry);
  332. if ( ((!$isDir && $list & FILE_LIST_FILES) ||
  333. ($isDir && $list & FILE_LIST_DIRS)) &&
  334. (!is_callable($cb) ||
  335. call_user_func_array($cb, array(&$entry)))) {
  336. $entries[] = (object) array(
  337. 'name' => $entry,
  338. 'size' => $isDir ? null : filesize($path .'/'. $entry),
  339. 'date' => filemtime($path .'/'. $entry),
  340. );
  341. }
  342. }
  343. }
  344. $dir->close();
  345. if ($sort) {
  346. $entries = File_Util::sortFiles($entries, $sort);
  347. }
  348. return $entries;
  349. }
  350. /**
  351. * Sort Files
  352. *
  353. * @static
  354. * @access public
  355. * @return array
  356. * @param array $files
  357. * @param int $sort
  358. */
  359. function sortFiles($files, $sort)
  360. {
  361. if (!$files) {
  362. return array();
  363. }
  364. if (!$sort) {
  365. return $files;
  366. }
  367. if ($sort === 1) {
  368. return array_reverse($files);
  369. }
  370. if ($sort & FILE_SORT_RANDOM) {
  371. shuffle($files);
  372. return $files;
  373. }
  374. $names = array();
  375. $sizes = array();
  376. $dates = array();
  377. if ($sort & FILE_SORT_NAME) {
  378. $r = &$names;
  379. } elseif ($sort & FILE_SORT_DATE) {
  380. $r = &$dates;
  381. } elseif ($sort & FILE_SORT_SIZE) {
  382. $r = &$sizes;
  383. } else {
  384. asort($files, SORT_REGULAR);
  385. return $files;
  386. }
  387. $sortFlags = array(
  388. FILE_SORT_NAME => SORT_STRING,
  389. FILE_SORT_DATE => SORT_NUMERIC,
  390. FILE_SORT_SIZE => SORT_NUMERIC,
  391. );
  392. foreach ($files as $file) {
  393. $names[] = $file->name;
  394. $sizes[] = $file->size;
  395. $dates[] = $file->date;
  396. }
  397. if ($sort & FILE_SORT_REVERSE) {
  398. arsort($r, $sortFlags[$sort & ~1]);
  399. } else {
  400. asort($r, $sortFlags[$sort]);
  401. }
  402. $result = array();
  403. foreach ($r as $i => $f) {
  404. $result[] = $files[$i];
  405. }
  406. return $result;
  407. }
  408. /**
  409. * Switch File Extension
  410. *
  411. * @static
  412. * @access public
  413. * @return string|array
  414. * @param string|array $filename
  415. * @param string $to new file extension
  416. * @param string $from change only files with this extension
  417. * @param bool $reverse change only files not having $from extension
  418. */
  419. function switchExt($filename, $to, $from = null, $reverse = false)
  420. {
  421. if (is_array($filename)) {
  422. foreach ($filename as $key => $file) {
  423. $filename[$key] = File_Util::switchExt($file, $to, $from);
  424. }
  425. return $filename;
  426. }
  427. if ($len = strlen($from)) {
  428. $ext = substr($filename, -$len - 1);
  429. $cfn = FILE_WIN32 ? 'strcasecmp' : 'strcmp';
  430. if (!$reverse == $cfn($ext, '.'. $from)) {
  431. return $filename;
  432. }
  433. return substr($filename, 0, -$len - 1) .'.'. $to;
  434. }
  435. if ($pos = strpos($filename, '.')) {
  436. return substr($filename, 0, $pos) .'.'. $to;
  437. }
  438. return $filename .'.'. $to;
  439. }
  440. }
  441. ?>