1: <?php
2: /**
3: * This file contains the the static directory handler class.
4: *
5: * @package Core
6: * @subpackage Util
7: * @version SVN Revision $Rev:$
8: *
9: * @author Frederic Schneider
10: * @copyright four for business AG <www.4fb.de>
11: * @license http://www.contenido.org/license/LIZENZ.txt
12: * @link http://www.4fb.de
13: * @link http://www.contenido.org
14: */
15: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
16:
17: /**
18: * Class for directory handling.
19: * Provides functions for dealing with directories.
20: *
21: * @package Core
22: * @subpackage Util
23: */
24: class cDirHandler {
25:
26: /**
27: * Creates a new dir.
28: *
29: * @param string $pathname the name and path of the new dir
30: * @param bool $recursive
31: * @return bool Returns true on success or false on failure.
32: */
33: public static function create($pathname, $recursive = false) {
34: // skip if dir already exists
35: if (self::exists($pathname)) {
36: return true;
37: }
38: // reset umask and store old umask
39: $oldumask = umask(0);
40: // calc mode from setting or default
41: $mode = cRegistry::getConfigValue('default_perms', 'directory', 0777);
42: // create dir with given mode
43: $success = mkdir($pathname, $mode, $recursive);
44: // reset umask to old umask
45: umask($oldumask);
46: // return success
47: return $success;
48: }
49:
50: /**
51: * Removes a dir from the filesystem
52: *
53: * @param string $dirname The path to the directory
54: * @throws cInvalidArgumentException if the dir with the given dirname
55: * does not exist
56: * @return bool Returns true on success or false on failure.
57: */
58: public static function remove($dirname) {
59: if (!self::exists($dirname)) {
60: throw new cInvalidArgumentException('The directory ' . $dirname . ' could not be accessed because it does not exist.');
61: }
62: return rmdir($dirname);
63: }
64:
65: /**
66: * Moves a dir
67: *
68: * @param string $dirname The path and name of the directory
69: * @param string $destination the destination. Note that the dir can also
70: * be renamed in the process of moving it
71: * @throws cInvalidArgumentException if the dir with the given dirname
72: * does not exist
73: * @return bool Returns true on success or false on failure.
74: */
75: public static function move($dirname, $destination) {
76: if (!self::exists($dirname)) {
77: throw new cInvalidArgumentException('The directory ' . $dirname . ' could not be accessed because it does not exist.');
78: }
79:
80: $success = rename($dirname, $destination);
81:
82: if ($success) {
83: self::setDefaultDirPerms($destination);
84: }
85:
86: return $success;
87: }
88:
89: /**
90: * Renames a dir
91: *
92: * @param string $dirname the name and path of the dir
93: * @param string $new_dirname the new name of the dir
94: */
95: public static function rename($dirname, $new_dirname) {
96: self::move($dirname, $new_dirname);
97: }
98:
99: /**
100: * Changes the dir permissions
101: *
102: * @param string $dirname the name and path of the dir
103: * @param int $mode the new access mode : php chmod needs octal value
104: * @throws cInvalidArgumentException if the dir with the given dirname
105: * does not exist
106: * @return bool Returns true on success or false on failure.
107: */
108: public static function chmod($dirname, $mode) {
109: if (!cFileHandler::exists($dirname)) {
110: throw new cInvalidArgumentException('The directory ' . $dirname . ' could not be accessed because it does not exist.');
111: }
112: // chmod needs octal value for correct execution.
113: $mode = intval($mode, 8);
114: return @chmod($dirname, $mode);
115: }
116:
117: /**
118: * Sets the default directory permissions on the given directory.
119: *
120: * @param string $dirname the name of the directory
121: * @return bool Returns true on success or false on failure.
122: */
123: public static function setDefaultDirPerms($dirname) {
124: $cfg = cRegistry::getConfig();
125: $dirPerms = $cfg['default_perms']['directory'];
126:
127: return self::chmod($dirname, $dirPerms);
128: }
129:
130: /**
131: * Deletes a directory and all of its content.
132: *
133: * @param string $dirname the name of the directory which should be deleted
134: * @throws cInvalidArgumentException if dirname is empty
135: * @return bool Returns true on success or false on failure.
136: */
137: public static function recursiveRmdir($dirname) {
138: if ($dirname == '') {
139: throw new cInvalidArgumentException('Directory name must not be empty.');
140: }
141:
142: // make sure $dirname ends with a slash
143: if (substr($dirname, -1) !== '/') {
144: $dirname .= '/';
145: }
146:
147: foreach (new DirectoryIterator($dirname) as $file) {
148: if ($file != "." && $file != "..") {
149: $file = $dirname . $file;
150: if (is_dir($file)) {
151: self::recursiveRmdir($file);
152: } else {
153: unlink($file);
154: }
155: }
156: }
157:
158: return rmdir($dirname);
159: }
160:
161: /**
162: * Copies a directory and all of its subfolders.
163: *
164: * @param string $dirname the name and path of the file
165: * @param string $destination the destination. Note that existing files get
166: * overwritten
167: * @throws cInvalidArgumentException if the file with the given filename
168: * does not exist
169: * @return bool true on success
170: */
171: public static function recursiveCopy($dirname, $destination) {
172: if (!self::exists($dirname)) {
173: throw new cInvalidArgumentException('The directory ' . $dirname . ' could not be accessed because it does not exist.');
174: }
175:
176: if (!cFileHandler::exists($destination)) {
177: if (!mkdir($destination)) {
178: return false;
179: }
180: if (!self::chmod($destination, "777")) {
181: return false;
182: }
183: }
184:
185: foreach ($iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirname), RecursiveIteratorIterator::SELF_FIRST) as $item) {
186: // workaround for RecursiveDirectoryIterator::SKIP_DOTS, this was
187: // not available in PHP 5.2
188: if ($item->getFilename() == '.' || $item->getFilename() == '..') {
189: continue;
190: }
191:
192: if ($item->isDir()) {
193: if (!mkdir($destination . DIRECTORY_SEPARATOR . $iterator->getSubPathName())) {
194: return false;
195: }
196: if (!self::chmod($destination . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), "777")) {
197: return false;
198: }
199: } else {
200: if (!copy($item, $destination . DIRECTORY_SEPARATOR . $iterator->getSubPathName())) {
201: return false;
202: }
203: if (!self::chmod($destination . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), "777")) {
204: return false;
205: }
206: }
207: }
208:
209: return true;
210: }
211:
212: /**
213: * Checks if a directory is empty
214: *
215: * @param string $dir Name of the directory
216: * @return boolean true if the directory is empty
217: */
218: public static function isDirectoryEmpty($dir) {
219: if (!is_readable($dir)) {
220: return false;
221: }
222: if (is_dir($dir)) {
223: if ($handle = opendir($dir)) {
224: while (false !== ($entry = readdir($handle))) {
225: if ($entry != "." && $entry != "..") {
226: return false;
227: }
228: }
229: }
230: closedir($handle);
231: }
232: return true;
233: }
234:
235: /**
236: * This functions reads the content from given directory.
237: * Optionally options are to read the directory recursive or to list only
238: * directories.
239: *
240: * @param string $dirName directory
241: * @param bool $recursive flag to read recursive
242: * @param bool $dirOnly flag to list only directories
243: * @param bool $fileOnly flag to list only files if $dirOnly is set to false
244: * @return mixed Ambigous multitype: array containing file names as string, false on error
245: */
246: public static function read($dirName, $recursive = false, $dirOnly = false, $fileOnly = false) {
247: if (!self::exists($dirName)) {
248: return false;
249: }
250:
251: $dirContent = array();
252: if ($recursive == false) {
253: $dirHandle = opendir($dirName);
254: $dirContent = array();
255: while (false !== ($file = readdir($dirHandle))) {
256: if (!cFileHandler::fileNameIsDot($file)) {
257:
258: if ($dirOnly == true) { // get only directories
259:
260: if (is_dir($dirName . $file)) {
261: $dirContent[] = $file;
262: }
263: // bugfix: is_dir only checked file name without path, thus returning everything most of the time
264: } else if ($fileOnly === true) { // get only files
265:
266: if (is_file($dirName . $file)) {
267: $dirContent[] = $file;
268: }
269: } else { // get everything
270: $dirContent[] = $file;
271: }
272: }
273: }
274: closedir($dirHandle);
275: } else {
276: $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirName), RecursiveIteratorIterator::SELF_FIRST);
277: foreach ($objects as $name => $file) {
278:
279: if (!cFileHandler::fileNameIsDot($file)) {
280: $fileName = str_replace("\\", "/", $file->getPathName());
281:
282: // get only directories
283: if ($dirOnly === true && is_dir($fileName)) {
284: $dirContent[] = $fileName;
285: // get only files
286: } else if ($fileOnly === true && is_file($fileName)) {
287: $dirContent[] = $fileName;
288: } else {
289: $dirContent[] = $fileName;
290: }
291: }
292: }
293: }
294:
295: return $dirContent;
296: }
297:
298: /**
299: * Checks if a directory exists
300: *
301: * @param string $dirname the name and path of the directory
302: * @return bool true if the directory exists
303: */
304: public static function exists($dirname) {
305: return is_dir($dirname);
306: }
307:
308: /**
309: *
310: * @see cFileHandler::fileNameIsDot()
311: * @deprecated 2013-11-11 - Use the class cFileHandler instead.
312: */
313: public static function fileNameIsDot($fileName) {
314: cDeprecated("Use the class cFileHandler instead.");
315: return cFileHandler::fileNameIsDot($fileName);
316: }
317:
318: }
319: