1 <?php
  2 
  3 /**
  4  * Class for handling directories.
  5  *
  6  * @author gharlan
  7  *
  8  * @package redaxo\core
  9  */
 10 class rex_dir
 11 {
 12     /**
 13      * Creates a directory.
 14      *
 15      * @param string $dir       Path of the new directory
 16      * @param bool   $recursive When FALSE, nested directories won't be created
 17      *
 18      * @return bool TRUE on success, FALSE on failure
 19      */
 20     public static function create($dir, $recursive = true)
 21     {
 22         if (is_dir($dir)) {
 23             return true;
 24         }
 25 
 26         $parent = dirname($dir);
 27         if (!is_dir($parent) && (!$recursive || !self::create($parent))) {
 28             return false;
 29         }
 30 
 31         if (self::isWritable($parent) && mkdir($dir, rex::getDirPerm())) {
 32             @chmod($dir, rex::getDirPerm());
 33             return true;
 34         }
 35 
 36         return false;
 37     }
 38 
 39     /**
 40      * Returns wether the directory is writable.
 41      *
 42      * @param string $dir Path of the directory
 43      *
 44      * @return bool
 45      */
 46     public static function isWritable($dir)
 47     {
 48         $dir = rtrim($dir, DIRECTORY_SEPARATOR);
 49         return @is_dir($dir) && @is_writable($dir . DIRECTORY_SEPARATOR . '.');
 50     }
 51 
 52     /**
 53      * Copies a directory.
 54      *
 55      * @param string $srcdir Path of the source directory
 56      * @param string $dstdir Path of the destination directory
 57      *
 58      * @return bool TRUE on success, FALSE on failure
 59      */
 60     public static function copy($srcdir, $dstdir)
 61     {
 62         $srcdir = rtrim($srcdir, DIRECTORY_SEPARATOR);
 63         $dstdir = rtrim($dstdir, DIRECTORY_SEPARATOR);
 64 
 65         if (!self::create($dstdir)) {
 66             return false;
 67         }
 68 
 69         $state = true;
 70 
 71         foreach (rex_finder::factory($srcdir)->recursive() as $srcfilepath => $srcfile) {
 72             $dstfile = $dstdir . substr($srcfilepath, strlen($srcdir));
 73             if ($srcfile->isDir()) {
 74                 $state = self::create($dstfile) && $state;
 75             } else {
 76                 $state = rex_file::copy($srcfilepath, $dstfile) && $state;
 77             }
 78         }
 79 
 80         return $state;
 81     }
 82 
 83     /**
 84      * Deletes a directory.
 85      *
 86      * @param string $dir        Path of the directory
 87      * @param bool   $deleteSelf When FALSE, only subdirectories and files will be deleted
 88      *
 89      * @return bool TRUE on success, FALSE on failure
 90      */
 91     public static function delete($dir, $deleteSelf = true)
 92     {
 93         return !is_dir($dir) || self::deleteIterator(rex_finder::factory($dir)->recursive()->childFirst()->ignoreSystemStuff(false)) && (!$deleteSelf || rmdir($dir));
 94     }
 95 
 96     /**
 97      * Deletes the files in a directory.
 98      *
 99      * @param string $dir       Path of the directory
100      * @param bool   $recursive When FALSE, files in subdirectories won't be deleted
101      *
102      * @return bool TRUE on success, FALSE on failure
103      */
104     public static function deleteFiles($dir, $recursive = true)
105     {
106         $iterator = rex_finder::factory($dir)->recursive($recursive)->filesOnly()->ignoreSystemStuff(false);
107         return self::deleteIterator($iterator);
108     }
109 
110     /**
111      * Deletes files and directories by a rex_dir_iterator.
112      *
113      * @param Traversable $iterator Iterator, $iterator->current() must return a SplFileInfo-Object
114      *
115      * @return bool TRUE on success, FALSE on failure
116      */
117     public static function deleteIterator(Traversable $iterator)
118     {
119         $state = true;
120 
121         foreach ($iterator as $file) {
122             if ($file->isDir()) {
123                 $state = rmdir($file) && $state;
124             } else {
125                 $state = rex_file::delete($file) && $state;
126             }
127         }
128 
129         return $state;
130     }
131 }
132