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.5 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.5
      • 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 bool
 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 int
 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 bool $create Create folder if not found
107:  * @param string|bool $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 bool $sort Whether you want the results sorted, set this and the sort property
159:  *   to false to get unsorted results.
160:  * @param array|bool $exceptions Either an array or boolean true will not grab dot files
161:  * @param bool $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 bool $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 bool $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 bool $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 bool 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 bool 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|array $element Element to add 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:         $element = (array)$element;
330:         array_unshift($element, rtrim($path, DS));
331:         return implode(DS, $element);
332:     }
333: 
334: /**
335:  * Returns true if the File is in a given CakePath.
336:  *
337:  * @param string $path The path to check.
338:  * @return bool
339:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::inCakePath
340:  */
341:     public function inCakePath($path = '') {
342:         $dir = substr(Folder::slashTerm(ROOT), 0, -1);
343:         $newdir = $dir . $path;
344: 
345:         return $this->inPath($newdir);
346:     }
347: 
348: /**
349:  * Returns true if the File is in given path.
350:  *
351:  * @param string $path The path to check that the current pwd() resides with in.
352:  * @param bool $reverse Reverse the search, check that pwd() resides within $path.
353:  * @return bool
354:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::inPath
355:  */
356:     public function inPath($path = '', $reverse = false) {
357:         $dir = Folder::slashTerm($path);
358:         $current = Folder::slashTerm($this->pwd());
359: 
360:         if (!$reverse) {
361:             $return = preg_match('/^(.*)' . preg_quote($dir, '/') . '(.*)/', $current);
362:         } else {
363:             $return = preg_match('/^(.*)' . preg_quote($current, '/') . '(.*)/', $dir);
364:         }
365:         return (bool)$return;
366:     }
367: 
368: /**
369:  * Change the mode on a directory structure recursively. This includes changing the mode on files as well.
370:  *
371:  * @param string $path The path to chmod.
372:  * @param int $mode Octal value, e.g. 0755.
373:  * @param bool $recursive Chmod recursively, set to false to only change the current directory.
374:  * @param array $exceptions Array of files, directories to skip.
375:  * @return bool Success.
376:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::chmod
377:  */
378:     public function chmod($path, $mode = false, $recursive = true, $exceptions = array()) {
379:         if (!$mode) {
380:             $mode = $this->mode;
381:         }
382: 
383:         if ($recursive === false && is_dir($path)) {
384:             //@codingStandardsIgnoreStart
385:             if (@chmod($path, intval($mode, 8))) {
386:                 //@codingStandardsIgnoreEnd
387:                 $this->_messages[] = __d('cake_dev', '%s changed to %s', $path, $mode);
388:                 return true;
389:             }
390: 
391:             $this->_errors[] = __d('cake_dev', '%s NOT changed to %s', $path, $mode);
392:             return false;
393:         }
394: 
395:         if (is_dir($path)) {
396:             $paths = $this->tree($path);
397: 
398:             foreach ($paths as $type) {
399:                 foreach ($type as $fullpath) {
400:                     $check = explode(DS, $fullpath);
401:                     $count = count($check);
402: 
403:                     if (in_array($check[$count - 1], $exceptions)) {
404:                         continue;
405:                     }
406: 
407:                     //@codingStandardsIgnoreStart
408:                     if (@chmod($fullpath, intval($mode, 8))) {
409:                         //@codingStandardsIgnoreEnd
410:                         $this->_messages[] = __d('cake_dev', '%s changed to %s', $fullpath, $mode);
411:                     } else {
412:                         $this->_errors[] = __d('cake_dev', '%s NOT changed to %s', $fullpath, $mode);
413:                     }
414:                 }
415:             }
416: 
417:             if (empty($this->_errors)) {
418:                 return true;
419:             }
420:         }
421:         return false;
422:     }
423: 
424: /**
425:  * Returns an array of nested directories and files in each directory
426:  *
427:  * @param string $path the directory path to build the tree from
428:  * @param array|bool $exceptions Either an array of files/folder to exclude
429:  *   or boolean true to not grab dot files/folders
430:  * @param string $type either 'file' or 'dir'. null returns both files and directories
431:  * @return mixed array of nested directories and files in each directory
432:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::tree
433:  */
434:     public function tree($path = null, $exceptions = false, $type = null) {
435:         if (!$path) {
436:             $path = $this->path;
437:         }
438:         $files = array();
439:         $directories = array($path);
440: 
441:         if (is_array($exceptions)) {
442:             $exceptions = array_flip($exceptions);
443:         }
444:         $skipHidden = false;
445:         if ($exceptions === true) {
446:             $skipHidden = true;
447:         } elseif (isset($exceptions['.'])) {
448:             $skipHidden = true;
449:             unset($exceptions['.']);
450:         }
451: 
452:         try {
453:             $directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME | RecursiveDirectoryIterator::CURRENT_AS_SELF);
454:             $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
455:         } catch (Exception $e) {
456:             if ($type === null) {
457:                 return array(array(), array());
458:             }
459:             return array();
460:         }
461: 
462:         foreach ($iterator as $itemPath => $fsIterator) {
463:             if ($skipHidden) {
464:                 $subPathName = $fsIterator->getSubPathname();
465:                 if ($subPathName{0} === '.' || strpos($subPathName, DS . '.') !== false) {
466:                     continue;
467:                 }
468:             }
469:             $item = $fsIterator->current();
470:             if (!empty($exceptions) && isset($exceptions[$item->getFilename()])) {
471:                 continue;
472:             }
473: 
474:             if ($item->isFile()) {
475:                 $files[] = $itemPath;
476:             } elseif ($item->isDir() && !$item->isDot()) {
477:                 $directories[] = $itemPath;
478:             }
479:         }
480:         if ($type === null) {
481:             return array($directories, $files);
482:         }
483:         if ($type === 'dir') {
484:             return $directories;
485:         }
486:         return $files;
487:     }
488: 
489: /**
490:  * Create a directory structure recursively.
491:  *
492:  * Can be used to create deep path structures like `/foo/bar/baz/shoe/horn`
493:  *
494:  * @param string $pathname The directory structure to create. Either an absolute or relative
495:  *   path. If the path is relative and exists in the process' cwd it will not be created.
496:  *   Otherwise relative paths will be prefixed with the current pwd().
497:  * @param int $mode octal value 0755
498:  * @return bool Returns TRUE on success, FALSE on failure
499:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::create
500:  */
501:     public function create($pathname, $mode = false) {
502:         if (is_dir($pathname) || empty($pathname)) {
503:             return true;
504:         }
505: 
506:         if (!self::isAbsolute($pathname)) {
507:             $pathname = self::addPathElement($this->pwd(), $pathname);
508:         }
509: 
510:         if (!$mode) {
511:             $mode = $this->mode;
512:         }
513: 
514:         if (is_file($pathname)) {
515:             $this->_errors[] = __d('cake_dev', '%s is a file', $pathname);
516:             return false;
517:         }
518:         $pathname = rtrim($pathname, DS);
519:         $nextPathname = substr($pathname, 0, strrpos($pathname, DS));
520: 
521:         if ($this->create($nextPathname, $mode)) {
522:             if (!file_exists($pathname)) {
523:                 $old = umask(0);
524:                 if (mkdir($pathname, $mode)) {
525:                     umask($old);
526:                     $this->_messages[] = __d('cake_dev', '%s created', $pathname);
527:                     return true;
528:                 }
529:                 umask($old);
530:                 $this->_errors[] = __d('cake_dev', '%s NOT created', $pathname);
531:                 return false;
532:             }
533:         }
534:         return false;
535:     }
536: 
537: /**
538:  * Returns the size in bytes of this Folder and its contents.
539:  *
540:  * @return int size in bytes of current folder
541:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::dirsize
542:  */
543:     public function dirsize() {
544:         $size = 0;
545:         $directory = Folder::slashTerm($this->path);
546:         $stack = array($directory);
547:         $count = count($stack);
548:         for ($i = 0, $j = $count; $i < $j; ++$i) {
549:             if (is_file($stack[$i])) {
550:                 $size += filesize($stack[$i]);
551:             } elseif (is_dir($stack[$i])) {
552:                 $dir = dir($stack[$i]);
553:                 if ($dir) {
554:                     while (false !== ($entry = $dir->read())) {
555:                         if ($entry === '.' || $entry === '..') {
556:                             continue;
557:                         }
558:                         $add = $stack[$i] . $entry;
559: 
560:                         if (is_dir($stack[$i] . $entry)) {
561:                             $add = Folder::slashTerm($add);
562:                         }
563:                         $stack[] = $add;
564:                     }
565:                     $dir->close();
566:                 }
567:             }
568:             $j = count($stack);
569:         }
570:         return $size;
571:     }
572: 
573: /**
574:  * Recursively Remove directories if the system allows.
575:  *
576:  * @param string $path Path of directory to delete
577:  * @return bool Success
578:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::delete
579:  */
580:     public function delete($path = null) {
581:         if (!$path) {
582:             $path = $this->pwd();
583:         }
584:         if (!$path) {
585:             return null;
586:         }
587:         $path = Folder::slashTerm($path);
588:         if (is_dir($path)) {
589:             try {
590:                 $directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::CURRENT_AS_SELF);
591:                 $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::CHILD_FIRST);
592:             } catch (Exception $e) {
593:                 return false;
594:             }
595: 
596:             foreach ($iterator as $item) {
597:                 $filePath = $item->getPathname();
598:                 if ($item->isFile() || $item->isLink()) {
599:                     //@codingStandardsIgnoreStart
600:                     if (@unlink($filePath)) {
601:                         //@codingStandardsIgnoreEnd
602:                         $this->_messages[] = __d('cake_dev', '%s removed', $filePath);
603:                     } else {
604:                         $this->_errors[] = __d('cake_dev', '%s NOT removed', $filePath);
605:                     }
606:                 } elseif ($item->isDir() && !$item->isDot()) {
607:                     //@codingStandardsIgnoreStart
608:                     if (@rmdir($filePath)) {
609:                         //@codingStandardsIgnoreEnd
610:                         $this->_messages[] = __d('cake_dev', '%s removed', $filePath);
611:                     } else {
612:                         $this->_errors[] = __d('cake_dev', '%s NOT removed', $filePath);
613:                         return false;
614:                     }
615:                 }
616:             }
617: 
618:             $path = rtrim($path, DS);
619:             //@codingStandardsIgnoreStart
620:             if (@rmdir($path)) {
621:                 //@codingStandardsIgnoreEnd
622:                 $this->_messages[] = __d('cake_dev', '%s removed', $path);
623:             } else {
624:                 $this->_errors[] = __d('cake_dev', '%s NOT removed', $path);
625:                 return false;
626:             }
627:         }
628:         return true;
629:     }
630: 
631: /**
632:  * Recursive directory copy.
633:  *
634:  * ### Options
635:  *
636:  * - `to` The directory to copy to.
637:  * - `from` The directory to copy from, this will cause a cd() to occur, changing the results of pwd().
638:  * - `mode` The mode to copy the files/directories with as integer, e.g. 0775.
639:  * - `skip` Files/directories to skip.
640:  * - `scheme` Folder::MERGE, Folder::OVERWRITE, Folder::SKIP
641:  *
642:  * @param array|string $options Either an array of options (see above) or a string of the destination directory.
643:  * @return bool Success.
644:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::copy
645:  */
646:     public function copy($options) {
647:         if (!$this->pwd()) {
648:             return false;
649:         }
650:         $to = null;
651:         if (is_string($options)) {
652:             $to = $options;
653:             $options = array();
654:         }
655:         $options += array(
656:             'to' => $to,
657:             'from' => $this->path,
658:             'mode' => $this->mode,
659:             'skip' => array(),
660:             'scheme' => Folder::MERGE
661:         );
662: 
663:         $fromDir = $options['from'];
664:         $toDir = $options['to'];
665:         $mode = $options['mode'];
666: 
667:         if (!$this->cd($fromDir)) {
668:             $this->_errors[] = __d('cake_dev', '%s not found', $fromDir);
669:             return false;
670:         }
671: 
672:         if (!is_dir($toDir)) {
673:             $this->create($toDir, $mode);
674:         }
675: 
676:         if (!is_writable($toDir)) {
677:             $this->_errors[] = __d('cake_dev', '%s not writable', $toDir);
678:             return false;
679:         }
680: 
681:         $exceptions = array_merge(array('.', '..', '.svn'), $options['skip']);
682:         //@codingStandardsIgnoreStart
683:         if ($handle = @opendir($fromDir)) {
684:             //@codingStandardsIgnoreEnd
685:             while (($item = readdir($handle)) !== false) {
686:                 $to = Folder::addPathElement($toDir, $item);
687:                 if (($options['scheme'] != Folder::SKIP || !is_dir($to)) && !in_array($item, $exceptions)) {
688:                     $from = Folder::addPathElement($fromDir, $item);
689:                     if (is_file($from) && (!is_file($to) || $options['scheme'] != Folder::SKIP)) {
690:                         if (copy($from, $to)) {
691:                             chmod($to, intval($mode, 8));
692:                             touch($to, filemtime($from));
693:                             $this->_messages[] = __d('cake_dev', '%s copied to %s', $from, $to);
694:                         } else {
695:                             $this->_errors[] = __d('cake_dev', '%s NOT copied to %s', $from, $to);
696:                         }
697:                     }
698: 
699:                     if (is_dir($from) && file_exists($to) && $options['scheme'] === Folder::OVERWRITE) {
700:                         $this->delete($to);
701:                     }
702: 
703:                     if (is_dir($from) && !file_exists($to)) {
704:                         $old = umask(0);
705:                         if (mkdir($to, $mode)) {
706:                             umask($old);
707:                             $old = umask(0);
708:                             chmod($to, $mode);
709:                             umask($old);
710:                             $this->_messages[] = __d('cake_dev', '%s created', $to);
711:                             $options = array('to' => $to, 'from' => $from) + $options;
712:                             $this->copy($options);
713:                         } else {
714:                             $this->_errors[] = __d('cake_dev', '%s not created', $to);
715:                         }
716:                     } elseif (is_dir($from) && $options['scheme'] === Folder::MERGE) {
717:                         $options = array('to' => $to, 'from' => $from) + $options;
718:                         $this->copy($options);
719:                     }
720:                 }
721:             }
722:             closedir($handle);
723:         } else {
724:             return false;
725:         }
726: 
727:         if (!empty($this->_errors)) {
728:             return false;
729:         }
730:         return true;
731:     }
732: 
733: /**
734:  * Recursive directory move.
735:  *
736:  * ### Options
737:  *
738:  * - `to` The directory to copy to.
739:  * - `from` The directory to copy from, this will cause a cd() to occur, changing the results of pwd().
740:  * - `chmod` The mode to copy the files/directories with.
741:  * - `skip` Files/directories to skip.
742:  * - `scheme` Folder::MERGE, Folder::OVERWRITE, Folder::SKIP
743:  *
744:  * @param array $options (to, from, chmod, skip, scheme)
745:  * @return bool Success
746:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::move
747:  */
748:     public function move($options) {
749:         $to = null;
750:         if (is_string($options)) {
751:             $to = $options;
752:             $options = (array)$options;
753:         }
754:         $options += array('to' => $to, 'from' => $this->path, 'mode' => $this->mode, 'skip' => array());
755: 
756:         if ($this->copy($options)) {
757:             if ($this->delete($options['from'])) {
758:                 return (bool)$this->cd($options['to']);
759:             }
760:         }
761:         return false;
762:     }
763: 
764: /**
765:  * get messages from latest method
766:  *
767:  * @param bool $reset Reset message stack after reading
768:  * @return array
769:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::messages
770:  */
771:     public function messages($reset = true) {
772:         $messages = $this->_messages;
773:         if ($reset) {
774:             $this->_messages = array();
775:         }
776:         return $messages;
777:     }
778: 
779: /**
780:  * get error from latest method
781:  *
782:  * @param bool $reset Reset error stack after reading
783:  * @return array
784:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::errors
785:  */
786:     public function errors($reset = true) {
787:         $errors = $this->_errors;
788:         if ($reset) {
789:             $this->_errors = array();
790:         }
791:         return $errors;
792:     }
793: 
794: /**
795:  * Get the real path (taking ".." and such into account)
796:  *
797:  * @param string $path Path to resolve
798:  * @return string The resolved path
799:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::realpath
800:  */
801:     public function realpath($path) {
802:         $path = str_replace('/', DS, trim($path));
803:         if (strpos($path, '..') === false) {
804:             if (!Folder::isAbsolute($path)) {
805:                 $path = Folder::addPathElement($this->path, $path);
806:             }
807:             return $path;
808:         }
809:         $parts = explode(DS, $path);
810:         $newparts = array();
811:         $newpath = '';
812:         if ($path[0] === DS) {
813:             $newpath = DS;
814:         }
815: 
816:         while (($part = array_shift($parts)) !== null) {
817:             if ($part === '.' || $part === '') {
818:                 continue;
819:             }
820:             if ($part === '..') {
821:                 if (!empty($newparts)) {
822:                     array_pop($newparts);
823:                     continue;
824:                 }
825:                 return false;
826:             }
827:             $newparts[] = $part;
828:         }
829:         $newpath .= implode(DS, $newparts);
830: 
831:         return Folder::slashTerm($newpath);
832:     }
833: 
834: /**
835:  * Returns true if given $path ends in a slash (i.e. is slash-terminated).
836:  *
837:  * @param string $path Path to check
838:  * @return bool true if path ends with slash, false otherwise
839:  * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::isSlashTerm
840:  */
841:     public static function isSlashTerm($path) {
842:         $lastChar = $path[strlen($path) - 1];
843:         return $lastChar === '/' || $lastChar === '\\';
844:     }
845: 
846: }
847: 
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