PageRenderTime 71ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/cakephp/lib/Cake/Utility/Folder.php

http://sistemaresidencias.codeplex.com
PHP | 795 lines | 633 code | 24 blank | 138 comment | 23 complexity | d8f4992145c2f288de69297c853d4d59 MD5 | raw file
  1. <?php
  2. /**
  3. * Convenience class for handling directories.
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package Cake.Utility
  16. * @since CakePHP(tm) v 0.2.9
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. /**
  20. * Folder structure browser, lists folders and files.
  21. * Provides an Object interface for Common directory related tasks.
  22. *
  23. * @package Cake.Utility
  24. */
  25. class Folder {
  26. /**
  27. * Path to Folder.
  28. *
  29. * @var string
  30. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::$path
  31. */
  32. public $path = null;
  33. /**
  34. * Sortedness. Whether or not list results
  35. * should be sorted by name.
  36. *
  37. * @var boolean
  38. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::$sort
  39. */
  40. public $sort = false;
  41. /**
  42. * Mode to be used on create. Does nothing on windows platforms.
  43. *
  44. * @var integer
  45. * http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::$mode
  46. */
  47. public $mode = 0755;
  48. /**
  49. * Holds messages from last method.
  50. *
  51. * @var array
  52. */
  53. protected $_messages = array();
  54. /**
  55. * Holds errors from last method.
  56. *
  57. * @var array
  58. */
  59. protected $_errors = array();
  60. /**
  61. * Holds array of complete directory paths.
  62. *
  63. * @var array
  64. */
  65. protected $_directories;
  66. /**
  67. * Holds array of complete file paths.
  68. *
  69. * @var array
  70. */
  71. protected $_files;
  72. /**
  73. * Constructor.
  74. *
  75. * @param string $path Path to folder
  76. * @param boolean $create Create folder if not found
  77. * @param mixed $mode Mode (CHMOD) to apply to created folder, false to ignore
  78. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder
  79. */
  80. public function __construct($path = false, $create = false, $mode = false) {
  81. if (empty($path)) {
  82. $path = TMP;
  83. }
  84. if ($mode) {
  85. $this->mode = $mode;
  86. }
  87. if (!file_exists($path) && $create === true) {
  88. $this->create($path, $this->mode);
  89. }
  90. if (!Folder::isAbsolute($path)) {
  91. $path = realpath($path);
  92. }
  93. if (!empty($path)) {
  94. $this->cd($path);
  95. }
  96. }
  97. /**
  98. * Return current path.
  99. *
  100. * @return string Current path
  101. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::pwd
  102. */
  103. public function pwd() {
  104. return $this->path;
  105. }
  106. /**
  107. * Change directory to $path.
  108. *
  109. * @param string $path Path to the directory to change to
  110. * @return string The new path. Returns false on failure
  111. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::cd
  112. */
  113. public function cd($path) {
  114. $path = $this->realpath($path);
  115. if (is_dir($path)) {
  116. return $this->path = $path;
  117. }
  118. return false;
  119. }
  120. /**
  121. * Returns an array of the contents of the current directory.
  122. * The returned array holds two arrays: One of directories and one of files.
  123. *
  124. * @param boolean $sort Whether you want the results sorted, set this and the sort property
  125. * to false to get unsorted results.
  126. * @param mixed $exceptions Either an array or boolean true will not grab dot files
  127. * @param boolean $fullPath True returns the full path
  128. * @return mixed Contents of current directory as an array, an empty array on failure
  129. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::read
  130. */
  131. public function read($sort = true, $exceptions = false, $fullPath = false) {
  132. $dirs = $files = array();
  133. if (!$this->pwd()) {
  134. return array($dirs, $files);
  135. }
  136. if (is_array($exceptions)) {
  137. $exceptions = array_flip($exceptions);
  138. }
  139. $skipHidden = isset($exceptions['.']) || $exceptions === true;
  140. try {
  141. $iterator = new DirectoryIterator($this->path);
  142. } catch (UnexpectedValueException $e) {
  143. return array($dirs, $files);
  144. }
  145. foreach ($iterator as $item) {
  146. if ($item->isDot()) {
  147. continue;
  148. }
  149. $name = $item->getFileName();
  150. if ($skipHidden && $name[0] === '.' || isset($exceptions[$name])) {
  151. continue;
  152. }
  153. if ($fullPath) {
  154. $name = $item->getPathName();
  155. }
  156. if ($item->isDir()) {
  157. $dirs[] = $name;
  158. } else {
  159. $files[] = $name;
  160. }
  161. }
  162. if ($sort || $this->sort) {
  163. sort($dirs);
  164. sort($files);
  165. }
  166. return array($dirs, $files);
  167. }
  168. /**
  169. * Returns an array of all matching files in current directory.
  170. *
  171. * @param string $regexpPattern Preg_match pattern (Defaults to: .*)
  172. * @param boolean $sort Whether results should be sorted.
  173. * @return array Files that match given pattern
  174. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::find
  175. */
  176. public function find($regexpPattern = '.*', $sort = false) {
  177. list($dirs, $files) = $this->read($sort);
  178. return array_values(preg_grep('/^' . $regexpPattern . '$/i', $files)); ;
  179. }
  180. /**
  181. * Returns an array of all matching files in and below current directory.
  182. *
  183. * @param string $pattern Preg_match pattern (Defaults to: .*)
  184. * @param boolean $sort Whether results should be sorted.
  185. * @return array Files matching $pattern
  186. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::findRecursive
  187. */
  188. public function findRecursive($pattern = '.*', $sort = false) {
  189. if (!$this->pwd()) {
  190. return array();
  191. }
  192. $startsOn = $this->path;
  193. $out = $this->_findRecursive($pattern, $sort);
  194. $this->cd($startsOn);
  195. return $out;
  196. }
  197. /**
  198. * Private helper function for findRecursive.
  199. *
  200. * @param string $pattern Pattern to match against
  201. * @param boolean $sort Whether results should be sorted.
  202. * @return array Files matching pattern
  203. */
  204. protected function _findRecursive($pattern, $sort = false) {
  205. list($dirs, $files) = $this->read($sort);
  206. $found = array();
  207. foreach ($files as $file) {
  208. if (preg_match('/^' . $pattern . '$/i', $file)) {
  209. $found[] = Folder::addPathElement($this->path, $file);
  210. }
  211. }
  212. $start = $this->path;
  213. foreach ($dirs as $dir) {
  214. $this->cd(Folder::addPathElement($start, $dir));
  215. $found = array_merge($found, $this->findRecursive($pattern, $sort));
  216. }
  217. return $found;
  218. }
  219. /**
  220. * Returns true if given $path is a Windows path.
  221. *
  222. * @param string $path Path to check
  223. * @return boolean true if windows path, false otherwise
  224. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::isWindowsPath
  225. */
  226. public static function isWindowsPath($path) {
  227. return (preg_match('/^[A-Z]:\\\\/i', $path) || substr($path, 0, 2) == '\\\\');
  228. }
  229. /**
  230. * Returns true if given $path is an absolute path.
  231. *
  232. * @param string $path Path to check
  233. * @return boolean true if path is absolute.
  234. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::isAbsolute
  235. */
  236. public static function isAbsolute($path) {
  237. return !empty($path) && ($path[0] === '/' || preg_match('/^[A-Z]:\\\\/i', $path) || substr($path, 0, 2) == '\\\\');
  238. }
  239. /**
  240. * Returns a correct set of slashes for given $path. (\\ for Windows paths and / for other paths.)
  241. *
  242. * @param string $path Path to check
  243. * @return string Set of slashes ("\\" or "/")
  244. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::normalizePath
  245. */
  246. public static function normalizePath($path) {
  247. return Folder::correctSlashFor($path);
  248. }
  249. /**
  250. * Returns a correct set of slashes for given $path. (\\ for Windows paths and / for other paths.)
  251. *
  252. * @param string $path Path to check
  253. * @return string Set of slashes ("\\" or "/")
  254. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::correctSlashFor
  255. */
  256. public static function correctSlashFor($path) {
  257. return (Folder::isWindowsPath($path)) ? '\\' : '/';
  258. }
  259. /**
  260. * Returns $path with added terminating slash (corrected for Windows or other OS).
  261. *
  262. * @param string $path Path to check
  263. * @return string Path with ending slash
  264. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::slashTerm
  265. */
  266. public static function slashTerm($path) {
  267. if (Folder::isSlashTerm($path)) {
  268. return $path;
  269. }
  270. return $path . Folder::correctSlashFor($path);
  271. }
  272. /**
  273. * Returns $path with $element added, with correct slash in-between.
  274. *
  275. * @param string $path Path
  276. * @param string $element Element to and at end of path
  277. * @return string Combined path
  278. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::addPathElement
  279. */
  280. public static function addPathElement($path, $element) {
  281. return rtrim($path, DS) . DS . $element;
  282. }
  283. /**
  284. * Returns true if the File is in a given CakePath.
  285. *
  286. * @param string $path The path to check.
  287. * @return boolean
  288. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::inCakePath
  289. */
  290. public function inCakePath($path = '') {
  291. $dir = substr(Folder::slashTerm(ROOT), 0, -1);
  292. $newdir = $dir . $path;
  293. return $this->inPath($newdir);
  294. }
  295. /**
  296. * Returns true if the File is in given path.
  297. *
  298. * @param string $path The path to check that the current pwd() resides with in.
  299. * @param boolean $reverse
  300. * @return boolean
  301. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::inPath
  302. */
  303. public function inPath($path = '', $reverse = false) {
  304. $dir = Folder::slashTerm($path);
  305. $current = Folder::slashTerm($this->pwd());
  306. if (!$reverse) {
  307. $return = preg_match('/^(.*)' . preg_quote($dir, '/') . '(.*)/', $current);
  308. } else {
  309. $return = preg_match('/^(.*)' . preg_quote($current, '/') . '(.*)/', $dir);
  310. }
  311. return (bool)$return;
  312. }
  313. /**
  314. * Change the mode on a directory structure recursively. This includes changing the mode on files as well.
  315. *
  316. * @param string $path The path to chmod
  317. * @param integer $mode octal value 0755
  318. * @param boolean $recursive chmod recursively, set to false to only change the current directory.
  319. * @param array $exceptions array of files, directories to skip
  320. * @return boolean Returns TRUE on success, FALSE on failure
  321. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::chmod
  322. */
  323. public function chmod($path, $mode = false, $recursive = true, $exceptions = array()) {
  324. if (!$mode) {
  325. $mode = $this->mode;
  326. }
  327. if ($recursive === false && is_dir($path)) {
  328. if (@chmod($path, intval($mode, 8))) {
  329. $this->_messages[] = __d('cake_dev', '%s changed to %s', $path, $mode);
  330. return true;
  331. }
  332. $this->_errors[] = __d('cake_dev', '%s NOT changed to %s', $path, $mode);
  333. return false;
  334. }
  335. if (is_dir($path)) {
  336. $paths = $this->tree($path);
  337. foreach ($paths as $type) {
  338. foreach ($type as $key => $fullpath) {
  339. $check = explode(DS, $fullpath);
  340. $count = count($check);
  341. if (in_array($check[$count - 1], $exceptions)) {
  342. continue;
  343. }
  344. if (@chmod($fullpath, intval($mode, 8))) {
  345. $this->_messages[] = __d('cake_dev', '%s changed to %s', $fullpath, $mode);
  346. } else {
  347. $this->_errors[] = __d('cake_dev', '%s NOT changed to %s', $fullpath, $mode);
  348. }
  349. }
  350. }
  351. if (empty($this->_errors)) {
  352. return true;
  353. }
  354. }
  355. return false;
  356. }
  357. /**
  358. * Returns an array of nested directories and files in each directory
  359. *
  360. * @param string $path the directory path to build the tree from
  361. * @param mixed $exceptions Array of files to exclude, false to exclude dot files.
  362. * @param string $type either file or dir. null returns both files and directories
  363. * @return mixed array of nested directories and files in each directory
  364. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::tree
  365. */
  366. public function tree($path = null, $exceptions = true, $type = null) {
  367. if ($path == null) {
  368. $path = $this->path;
  369. }
  370. $files = array();
  371. $directories = array($path);
  372. $skipHidden = false;
  373. if ($exceptions === false) {
  374. $skipHidden = true;
  375. }
  376. if (is_array($exceptions)) {
  377. $exceptions = array_flip($exceptions);
  378. if (isset($exceptions['.'])) {
  379. $skipHidden = true;
  380. unset($exceptions['.']);
  381. }
  382. }
  383. try {
  384. $directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME | RecursiveDirectoryIterator::CURRENT_AS_SELF | RecursiveDirectoryIterator::SKIP_DOTS);
  385. $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
  386. } catch (UnexpectedValueException $e) {
  387. if ($type === null) {
  388. return array(array(), array());
  389. }
  390. return array();
  391. }
  392. $pathLength = strlen($path);
  393. foreach ($iterator as $itemPath => $fsIterator) {
  394. if ($skipHidden) {
  395. $subPathName = $fsIterator->getSubPathname();
  396. if ($subPathName{0} == '.' || strpos($subPathName, DS . '.') !== false) {
  397. continue;
  398. }
  399. }
  400. $item = $fsIterator->current();
  401. if (!empty($exceptions) && isset($exceptions[$item->getFilename()])) {
  402. continue;
  403. }
  404. if ($item->isFile()) {
  405. $files[] = $itemPath;
  406. } elseif ($item->isDir()) {
  407. $directories[] = $itemPath;
  408. }
  409. }
  410. if ($type === null) {
  411. return array($directories, $files);
  412. }
  413. if ($type === 'dir') {
  414. return $directories;
  415. }
  416. return $files;
  417. }
  418. /**
  419. * Private method to list directories and files in each directory
  420. *
  421. * @param string $path The Path to read.
  422. * @param mixed $exceptions Array of files to exclude from the read that will be performed.
  423. * @return void
  424. */
  425. protected function _tree($path, $exceptions) {
  426. $this->path = $path;
  427. list($dirs, $files) = $this->read(false, $exceptions, true);
  428. $this->_directories = array_merge($this->_directories, $dirs);
  429. $this->_files = array_merge($this->_files, $files);
  430. }
  431. /**
  432. * Create a directory structure recursively. Can be used to create
  433. * deep path structures like `/foo/bar/baz/shoe/horn`
  434. *
  435. * @param string $pathname The directory structure to create
  436. * @param integer $mode octal value 0755
  437. * @return boolean Returns TRUE on success, FALSE on failure
  438. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::create
  439. */
  440. public function create($pathname, $mode = false) {
  441. if (is_dir($pathname) || empty($pathname)) {
  442. return true;
  443. }
  444. if (!$mode) {
  445. $mode = $this->mode;
  446. }
  447. if (is_file($pathname)) {
  448. $this->_errors[] = __d('cake_dev', '%s is a file', $pathname);
  449. return false;
  450. }
  451. $pathname = rtrim($pathname, DS);
  452. $nextPathname = substr($pathname, 0, strrpos($pathname, DS));
  453. if ($this->create($nextPathname, $mode)) {
  454. if (!file_exists($pathname)) {
  455. $old = umask(0);
  456. if (mkdir($pathname, $mode)) {
  457. umask($old);
  458. $this->_messages[] = __d('cake_dev', '%s created', $pathname);
  459. return true;
  460. } else {
  461. umask($old);
  462. $this->_errors[] = __d('cake_dev', '%s NOT created', $pathname);
  463. return false;
  464. }
  465. }
  466. }
  467. return false;
  468. }
  469. /**
  470. * Returns the size in bytes of this Folder and its contents.
  471. *
  472. * @return integer size in bytes of current folder
  473. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::dirsize
  474. */
  475. public function dirsize() {
  476. $size = 0;
  477. $directory = Folder::slashTerm($this->path);
  478. $stack = array($directory);
  479. $count = count($stack);
  480. for ($i = 0, $j = $count; $i < $j; ++$i) {
  481. if (is_file($stack[$i])) {
  482. $size += filesize($stack[$i]);
  483. } elseif (is_dir($stack[$i])) {
  484. $dir = dir($stack[$i]);
  485. if ($dir) {
  486. while (false !== ($entry = $dir->read())) {
  487. if ($entry === '.' || $entry === '..') {
  488. continue;
  489. }
  490. $add = $stack[$i] . $entry;
  491. if (is_dir($stack[$i] . $entry)) {
  492. $add = Folder::slashTerm($add);
  493. }
  494. $stack[] = $add;
  495. }
  496. $dir->close();
  497. }
  498. }
  499. $j = count($stack);
  500. }
  501. return $size;
  502. }
  503. /**
  504. * Recursively Remove directories if the system allows.
  505. *
  506. * @param string $path Path of directory to delete
  507. * @return boolean Success
  508. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::delete
  509. */
  510. public function delete($path = null) {
  511. if (!$path) {
  512. $path = $this->pwd();
  513. }
  514. if (!$path) {
  515. return null;
  516. }
  517. $path = Folder::slashTerm($path);
  518. if (is_dir($path) === true) {
  519. $normalFiles = glob($path . '*');
  520. $hiddenFiles = glob($path . '\.?*');
  521. $normalFiles = $normalFiles ? $normalFiles : array();
  522. $hiddenFiles = $hiddenFiles ? $hiddenFiles : array();
  523. $files = array_merge($normalFiles, $hiddenFiles);
  524. if (is_array($files)) {
  525. foreach ($files as $file) {
  526. if (preg_match('/(\.|\.\.)$/', $file)) {
  527. continue;
  528. }
  529. if (is_file($file) === true) {
  530. if (@unlink($file)) {
  531. $this->_messages[] = __d('cake_dev', '%s removed', $file);
  532. } else {
  533. $this->_errors[] = __d('cake_dev', '%s NOT removed', $file);
  534. }
  535. } elseif (is_dir($file) === true && $this->delete($file) === false) {
  536. return false;
  537. }
  538. }
  539. }
  540. $path = substr($path, 0, strlen($path) - 1);
  541. if (rmdir($path) === false) {
  542. $this->_errors[] = __d('cake_dev', '%s NOT removed', $path);
  543. return false;
  544. } else {
  545. $this->_messages[] = __d('cake_dev', '%s removed', $path);
  546. }
  547. }
  548. return true;
  549. }
  550. /**
  551. * Recursive directory copy.
  552. *
  553. * ### Options
  554. *
  555. * - `to` The directory to copy to.
  556. * - `from` The directory to copy from, this will cause a cd() to occur, changing the results of pwd().
  557. * - `mode` The mode to copy the files/directories with.
  558. * - `skip` Files/directories to skip.
  559. *
  560. * @param mixed $options Either an array of options (see above) or a string of the destination directory.
  561. * @return boolean Success
  562. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::copy
  563. */
  564. public function copy($options = array()) {
  565. if (!$this->pwd()) {
  566. return false;
  567. }
  568. $to = null;
  569. if (is_string($options)) {
  570. $to = $options;
  571. $options = array();
  572. }
  573. $options = array_merge(array('to' => $to, 'from' => $this->path, 'mode' => $this->mode, 'skip' => array()), $options);
  574. $fromDir = $options['from'];
  575. $toDir = $options['to'];
  576. $mode = $options['mode'];
  577. if (!$this->cd($fromDir)) {
  578. $this->_errors[] = __d('cake_dev', '%s not found', $fromDir);
  579. return false;
  580. }
  581. if (!is_dir($toDir)) {
  582. $this->create($toDir, $mode);
  583. }
  584. if (!is_writable($toDir)) {
  585. $this->_errors[] = __d('cake_dev', '%s not writable', $toDir);
  586. return false;
  587. }
  588. $exceptions = array_merge(array('.', '..', '.svn'), $options['skip']);
  589. if ($handle = @opendir($fromDir)) {
  590. while (false !== ($item = readdir($handle))) {
  591. if (!in_array($item, $exceptions)) {
  592. $from = Folder::addPathElement($fromDir, $item);
  593. $to = Folder::addPathElement($toDir, $item);
  594. if (is_file($from)) {
  595. if (copy($from, $to)) {
  596. chmod($to, intval($mode, 8));
  597. touch($to, filemtime($from));
  598. $this->_messages[] = __d('cake_dev', '%s copied to %s', $from, $to);
  599. } else {
  600. $this->_errors[] = __d('cake_dev', '%s NOT copied to %s', $from, $to);
  601. }
  602. }
  603. if (is_dir($from) && !file_exists($to)) {
  604. $old = umask(0);
  605. if (mkdir($to, $mode)) {
  606. umask($old);
  607. $old = umask(0);
  608. chmod($to, $mode);
  609. umask($old);
  610. $this->_messages[] = __d('cake_dev', '%s created', $to);
  611. $options = array_merge($options, array('to' => $to, 'from' => $from));
  612. $this->copy($options);
  613. } else {
  614. $this->_errors[] = __d('cake_dev', '%s not created', $to);
  615. }
  616. }
  617. }
  618. }
  619. closedir($handle);
  620. } else {
  621. return false;
  622. }
  623. if (!empty($this->_errors)) {
  624. return false;
  625. }
  626. return true;
  627. }
  628. /**
  629. * Recursive directory move.
  630. *
  631. * ### Options
  632. *
  633. * - `to` The directory to copy to.
  634. * - `from` The directory to copy from, this will cause a cd() to occur, changing the results of pwd().
  635. * - `chmod` The mode to copy the files/directories with.
  636. * - `skip` Files/directories to skip.
  637. *
  638. * @param array $options (to, from, chmod, skip)
  639. * @return boolean Success
  640. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::move
  641. */
  642. public function move($options) {
  643. $to = null;
  644. if (is_string($options)) {
  645. $to = $options;
  646. $options = (array)$options;
  647. }
  648. $options = array_merge(
  649. array('to' => $to, 'from' => $this->path, 'mode' => $this->mode, 'skip' => array()),
  650. $options
  651. );
  652. if ($this->copy($options)) {
  653. if ($this->delete($options['from'])) {
  654. return (bool)$this->cd($options['to']);
  655. }
  656. }
  657. return false;
  658. }
  659. /**
  660. * get messages from latest method
  661. *
  662. * @return array
  663. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::messages
  664. */
  665. public function messages() {
  666. return $this->_messages;
  667. }
  668. /**
  669. * get error from latest method
  670. *
  671. * @return array
  672. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::errors
  673. */
  674. public function errors() {
  675. return $this->_errors;
  676. }
  677. /**
  678. * Get the real path (taking ".." and such into account)
  679. *
  680. * @param string $path Path to resolve
  681. * @return string The resolved path
  682. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::realpath
  683. */
  684. public function realpath($path) {
  685. $path = str_replace('/', DS, trim($path));
  686. if (strpos($path, '..') === false) {
  687. if (!Folder::isAbsolute($path)) {
  688. $path = Folder::addPathElement($this->path, $path);
  689. }
  690. return $path;
  691. }
  692. $parts = explode(DS, $path);
  693. $newparts = array();
  694. $newpath = '';
  695. if ($path[0] === DS) {
  696. $newpath = DS;
  697. }
  698. while (($part = array_shift($parts)) !== NULL) {
  699. if ($part === '.' || $part === '') {
  700. continue;
  701. }
  702. if ($part === '..') {
  703. if (!empty($newparts)) {
  704. array_pop($newparts);
  705. continue;
  706. } else {
  707. return false;
  708. }
  709. }
  710. $newparts[] = $part;
  711. }
  712. $newpath .= implode(DS, $newparts);
  713. return Folder::slashTerm($newpath);
  714. }
  715. /**
  716. * Returns true if given $path ends in a slash (i.e. is slash-terminated).
  717. *
  718. * @param string $path Path to check
  719. * @return boolean true if path ends with slash, false otherwise
  720. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::isSlashTerm
  721. */
  722. public static function isSlashTerm($path) {
  723. $lastChar = $path[strlen($path) - 1];
  724. return $lastChar === '/' || $lastChar === '\\';
  725. }
  726. }