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

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