CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.4 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.4
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

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

Generated using CakePHP API Docs