Improvements to DirectoryUtil
authorTim Düsterhus <timwolla@arcor.de>
Thu, 18 Aug 2011 12:54:10 +0000 (14:54 +0200)
committerTim Düsterhus <timwolla@arcor.de>
Thu, 18 Aug 2011 13:07:34 +0000 (15:07 +0200)
- Adding missing namespaces to documentation
- Moving FileUtil::unifyDirSeperator() into scanning to avoid duplicate work when fetching more than one list of file
- Fixing indentation -> Now matching code guidelines
- Some method moving -> More logical order
- Removed destroy() in favor of clearCaches()

wcfsetup/install/files/lib/util/DirectoryUtil.class.php

index c0bf6813f89657bd4f4653cf88e4c0cf2b951be0..5bad7831b4cedbac667a436f9d8c6282523810d6 100644 (file)
@@ -4,7 +4,7 @@ use wcf\system\exception\SystemException;
 
 /**
 * Contains directory-related functions
-*
+* 
 * @author      Tim Düsterhus
 * @copyright   2011 Tim Düsterhus
 * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
@@ -14,58 +14,89 @@ use wcf\system\exception\SystemException;
 */
 class DirectoryUtil {
        /**
-        * @var DirectoryIterator | RecursiveDirectoryIterator
+        * @var \DirectoryIterator | \RecursiveDirectoryIterator
         */
        protected $obj = null;
-
+       
        /**
         * all files with full path
+        * 
         * @var array<string>
         */
        protected $files = array();
-
+       
        /**
         * all files with filename as key and DirectoryIterator object as value
-        * @var array<DirectoryIterator>
+        * 
+        * @var array<\DirectoryIterator>
         */
        protected $filesObj = array();
-
+       
        /**
         * directory size in bytes
+        * 
         * @var integer
         */
        protected $size = 0;
-
+       
        /**
         * directory path
+        * 
         * @var string
         */
        protected $directory = '';
-
+       
        /**
         * determines whether scan should be recursive
+        * 
         * @var boolean
         */
        protected $recursive = true;
        
        /**
         * indicates that files won't be sorted
+        * 
         * @var integer
         */
        const SORT_NONE = -1;
-
+       
        /**
         * all recursive and non-recursive instances of DirectoryUtil
-        * @var array<array>
+        * 
+        * @var array<array>
         */
        protected static $instances = array(
                true => array(),        // recursive instances
                false => array()        // non-recursive instances
        );
-
+       
+       /**
+        * Returns an instance of DirectoryUtil (or child).
+        * 
+        * @param       string          $directory      path
+        * @param       boolean         $recursive      walk through sub-directories too
+        * @return      wcf\util\DirectoryUtil
+        */
+       public static function getInstance($tmpDirectory, $recursive = true) {
+               $directory = realpath(FileUtil::unifyDirSeperator($tmpDirectory));
+               // realpath returns false if the directory does not exist
+               if ($directory === false) {
+                       throw new SystemException("Unknown directory '".$tmpDirectory."'");
+               }
+               if (!is_dir($directory)) {
+                       throw new SystemException("'".$tmpDirectory."' is no directory");
+               }
+               
+               if (!isset(static::$instances[$recursive][$directory])) {
+                       static::$instances[$recursive][$directory] = new static($directory, $recursive);
+               }
+               
+               return static::$instances[$recursive][$directory];
+       }
+       
        /**
         * Creates a new instance of DirectoryUtil.
-        *
+        * 
         * @param       string          $directory      directory path
         * @param       boolean         $recursive      created a recursive directory iterator
         * @see         wcf\util\DirectoryUtil::getInstance()
@@ -73,7 +104,7 @@ class DirectoryUtil {
        protected function __construct($directory, $recursive = true) {
                $this->directory = $directory;
                $this->recursive = $recursive;
-
+               
                // handle iterator type
                if ($this->recursive) {
                        $this->obj = new \RecursiveDirectoryIterator($directory);
@@ -82,56 +113,15 @@ class DirectoryUtil {
                        $this->obj = new \DirectoryIterator($directory);
                }
        }
-
+       
        /**
         * @see wcf\util\DirectoryUtil::getInstance()
         */
        private final function __clone() {}
-
-       /**
-        * Clears an instance of DirectoryUtil.
-        *
-        * @param       string          $directory      directory path
-        * @param       boolean         $recursive      destroy a recursive instance
-        * @return      boolean                         success
-        */
-       public static function destroy($directory, $recursive = true) {
-               $directory = realpath(FileUtil::unifyDirSeperator($directory));
-               if (!isset(static::$instances[$recursive][$directory])) {
-                       return false;
-               }
-               
-               unset (static::$instances[$recursive][$directory]);
-               return true;
-       }
-
-       /**
-        * Returns an instance of DirectoryUtil (or child).
-        *
-        * @param       string          $directory      path
-        * @param       boolean         $recursive      walk through sub-directories too
-        * @return      static
-        */
-       public static function getInstance($tmpDirectory, $recursive = true) {
-               $directory = realpath(FileUtil::unifyDirSeperator($tmpDirectory));
-               // realpath returns false if the directory does not exist
-               if ($directory === false) {
-                       throw new SystemException("Unknown directory '".$tmpDirectory."'");
-               }
-               if (!is_dir($directory)) {
-                       throw new SystemException("'".$tmpDirectory."' is no directory");
-               }
-               
-               if (!isset(static::$instances[$recursive][$directory])) {
-                       static::$instances[$recursive][$directory] = new static($directory, $recursive);
-               }
-
-               return static::$instances[$recursive][$directory];
-       }
-
+       
        /**
         * Returns a sorted list of files.
-        *
+        * 
         * @param       integer         $order                  sort-order
         * @param       string          $pattern                pattern to match
         * @param       boolean         $negativeMatch          true if the pattern should be inversed
@@ -141,14 +131,14 @@ class DirectoryUtil {
                // scan the folder
                $this->scanFiles();
                $files = $this->files;
-
+               
                // sort out non matching files
                if (!empty($pattern)) {
                        foreach ($files as $filename => $value) {
-                               if (((bool) preg_match($pattern, FileUtil::unifyDirSeperator($filename))) == $negativeMatch) unset($files[$filename]);
+                               if (((bool) preg_match($pattern, $filename)) == $negativeMatch) unset($files[$filename]);
                        }
                }
-
+               
                if ($order == SORT_DESC) {
                        krsort($files, $order);
                }
@@ -161,30 +151,30 @@ class DirectoryUtil {
                else {
                        throw new SystemException('The given sorting is not supported');
                }
-
+               
                return $files;
        }
-
+       
        /**
         * Returns a sorted list of files, with DirectoryIterator object as value
-        *
+        * 
         * @param       integer                 $order                  sort order
         * @param       string                  $pattern                pattern to match
         * @param       boolean                 $negativeMatch          should the pattern be inversed
-        * @return      array<DirectoryIterator>
+        * @return      array<\DirectoryIterator>
         */
        public function getFilesObj($order = SORT_ASC, $pattern = '', $negativeMatch = false) {
                // scan the folder
                $this->scanFilesObj();
                $objects = $this->filesObj;
-
+               
                // sort out non matching files
                if (!empty($pattern)) {
                        foreach ($objects as $filename => $value) {
-                               if (((bool) preg_match($pattern, FileUtil::unifyDirSeperator($filename))) == $negativeMatch) unset($objects[$filename]);
+                               if (((bool) preg_match($pattern, $filename)) == $negativeMatch) unset($objects[$filename]);
                        }
                }
-
+               
                if ($order == SORT_DESC) {
                        krsort($objects, $order);
                }
@@ -197,85 +187,85 @@ class DirectoryUtil {
                else {
                        throw new SystemException('The given sorting is not supported');
                }
-
+               
                return $objects;
        }
-
+       
        /**
         * Fills the list of available files
         */
        protected function scanFiles() {
                // value is cached
                if (!empty($this->files)) return;
-
+               
                if ($this->recursive) {
                        $it = new \RecursiveIteratorIterator($this->obj, \RecursiveIteratorIterator::CHILD_FIRST);
-
+                       
                        foreach ($it as $filename => $obj) {
                                // ignore . and ..
                                if ($it->isDot()) continue;
-
-                               $this->files[$filename] = $filename;
+                               
+                               $this->files[FileUtil::unifyDirSeperator($filename)] = FileUtil::unifyDirSeperator($filename);
                        }
                }
                else {
                        foreach ($this->obj as $obj) {
                                // ignore . and ..
                                if ($this->obj->isDot()) continue;
-
-                               $this->files[$obj->getFilename()] = $obj->getFilename();
+                               
+                               $this->files[FileUtil::unifyDirSeperator($obj->getFilename())] = FileUtil::unifyDirSeperator($obj->getFilename());
                        }
                }
-
+               
                // add the directory itself
                $this->filesObj[$this->directory] = $this->directory;
        }
-
+       
        /**
         * Fills the list of available files, with DirectoryIterator object as value
         */
        protected function scanFilesObj() {
                // value is cached
                if (!empty($this->filesObj)) return;
-
+               
                if ($this->recursive) {
                        $it = new \RecursiveIteratorIterator($this->obj, \RecursiveIteratorIterator::CHILD_FIRST);
-
+                       
                        foreach ($it as $filename => $obj) {
                                // ignore . and ..
                                if ($it->isDot()) continue;
-
-                               $this->filesObj[$filename] = $obj;
+                               
+                               $this->filesObj[FileUtil::unifyDirSeperator($filename)] = $obj;
                        }
                }
                else {
                        foreach ($this->obj as $obj) {
                                // ignore . and ..
                                if ($this->obj->isDot()) continue;
-
-                               $this->filesObj[$obj->getFilename()] = $obj;
+                               
+                               $this->filesObj[FileUtil::unifyDirSeperator($obj->getFilename())] = $obj;
                        }
                }
-
+               
                // add the directory itself
                $this->filesObj[$this->directory] = new \SPLFileInfo($this->directory);
        }
        
        /**
         * Executes a callback on each file and returns false if callback is invalid.
-        *
+        * 
         * @param       callback        $callback       valid callback
         * @param       string          $pattern        callback is only applied to files matching the given pattern
         * @return      boolean
         */
        public function executeCallback($callback, $pattern = '') {
                if (!is_callable($callback)) return false;
-
+               
                $files = $this->getFilesObj(self::SORT_NONE, $pattern);
                foreach ($files as $filename => $obj) {
                        call_user_func($callback, $filename, $obj);
                }
-
+               
                return true;
        }
        
@@ -288,22 +278,22 @@ class DirectoryUtil {
                // destroy cached instance
                unset(static::$instances[$this->recursive][$this->directory]);
        }
-
+       
        /**
         * Removes all files that match the given pattern.
-        *
+        * 
         * @param       string          $pattern        pattern to match
         */
        public function removePattern($pattern) {
                if (!$this->recursive) throw new SystemException('Removing of files only works in recursive mode');
-
+               
                $files = $this->getFilesObj(self::SORT_NONE, $pattern);
-
+               
                foreach ($files as $filename => $obj) {
                        if (!is_writable($obj->getPath())) {
                                throw new SystemException("Could not remove directory: '".$obj->getPath()."' is not writable");
                        }
-
+                       
                        if ($obj->isDir()) {
                                rmdir($filename);
                        }
@@ -312,32 +302,37 @@ class DirectoryUtil {
                        }
                }
                
-               // clear cache
-               $this->filesObj = array();
-               $this->scanFilesObj();
-
-               $this->files = array();
-               $this->scanFiles();
+               $this->clearCaches();
        }
-
+       
        /**
         * Calculates the size of the directory.
-        *
+        * 
         * @return      integer         directory size in bytes
         */
        public function getSize() {
-               if (!$this->recursive) {
-                       throw new SystemException('Calculating of size only works in recursive mode');
-               }
+               if (!$this->recursive) throw new SystemException('Calculating of size only works in recursive mode');
                
                // read cached value first
                if ($this->size) return $this->size;
-
+               
                $files = $this->getFilesObj(self::SORT_NONE);
                foreach ($files as $obj) {
                        $this->size += $obj->getSize();
                }
-
+               
                return $this->size;
        }
+       
+       /**
+        * Clears the caches of the current instance
+        */
+       public function clearCaches() {
+               // clear cached list of files
+               $this->files = array();
+               $this->filesObj = array();
+               
+               // clear cached size
+               $this->size = 0;
+       }
 }