root

Changeset 760

Show
Ignore:
Timestamp:
03/08/10 13:32:45 (5 months ago)
Author:
wbond
Message:

BackwardsCompatibilityBreak - fixed ticket #376 - fDirectory::scan() and fDirectory::scanRecursive() to strip the current directory's path before matching the $filter. Also added support for glob style matching.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • fDirectory.php

    r758 r760 Hide Line Numbers
    1111 * @link       http://flourishlib.com/fDirectory 
    1212 *  
    13  * @version    1.0.0b9 
    14  * @changes    1.0.0b9  Changed the way directories deleted in a filesystem transaction are handled, including improvements to the exception that is thrown [wb+wb-imarc, 2010-03-05] 
    15  * @changes    1.0.0b8  Backwards Compatibility Break - renamed ::getFilesize() to ::getSize(), added ::move() [wb, 2009-12-16] 
    16  * @changes    1.0.0b7  Fixed ::__construct() to throw an fValidationException when the directory does not exist [wb, 2009-08-21] 
    17  * @changes    1.0.0b6  Fixed a bug where deleting a directory would prevent any future operations in the same script execution on a file or directory with the same path [wb, 2009-08-20] 
    18  * @changes    1.0.0b5  Added the ability to skip checks in ::__construct() for better performance in conjunction with fFilesystem::createObject() [wb, 2009-08-06] 
    19  * @changes    1.0.0b4  Refactored ::scan() to use the new fFilesystem::createObject() method [wb, 2009-01-21] 
    20  * @changes    1.0.0b3  Added the $regex_filter parameter to ::scan() and ::scanRecursive(), fixed bug in ::scanRecursive() [wb, 2009-01-05] 
    21  * @changes    1.0.0b2  Removed some unnecessary error suppresion operators [wb, 2008-12-11] 
    22  * @changes    1.0.0b   The initial implementation [wb, 2007-12-21] 
     13 * @version    1.0.0b10 
     14 * @changes    1.0.0b10  BackwardsCompatibilityBreak - Fixed ::scan() and ::scanRecursive() to strip the current directory's path before matching, added support for glob style matching [wb, 2010-03-05] 
     15 * @changes    1.0.0b9   Changed the way directories deleted in a filesystem transaction are handled, including improvements to the exception that is thrown [wb+wb-imarc, 2010-03-05] 
     16 * @changes    1.0.0b8   Backwards Compatibility Break - renamed ::getFilesize() to ::getSize(), added ::move() [wb, 2009-12-16] 
     17 * @changes    1.0.0b7   Fixed ::__construct() to throw an fValidationException when the directory does not exist [wb, 2009-08-21] 
     18 * @changes    1.0.0b6   Fixed a bug where deleting a directory would prevent any future operations in the same script execution on a file or directory with the same path [wb, 2009-08-20] 
     19 * @changes    1.0.0b5   Added the ability to skip checks in ::__construct() for better performance in conjunction with fFilesystem::createObject() [wb, 2009-08-06] 
     20 * @changes    1.0.0b4   Refactored ::scan() to use the new fFilesystem::createObject() method [wb, 2009-01-21] 
     21 * @changes    1.0.0b3   Added the $regex_filter parameter to ::scan() and ::scanRecursive(), fixed bug in ::scanRecursive() [wb, 2009-01-05] 
     22 * @changes    1.0.0b2   Removed some unnecessary error suppresion operators [wb, 2008-12-11] 
     23 * @changes    1.0.0b    The initial implementation [wb, 2007-12-21] 
    2324 */ 
    2425class fDirectory 
     
    415416     * Performs a [http://php.net/scandir scandir()] on a directory, removing the `.` and `..` entries 
    416417     *  
    417      * @param  string $regex_filter  A PCRE to filter files/directories by path, directories can be detected by checking for a trailing / (even on Windows) 
     418     * If the `$filter` looks like a valid PCRE pattern - matching delimeters 
     419     * (a delimeter can be any non-alphanumeric, non-backslash, non-whitespace 
     420     * character) followed by zero or more of the flags `i`, `m`, `s`, `x`, 
     421     * `e`, `A`, `D`,  `S`, `U`, `X`, `J`, `u` - then 
     422     * [http://php.net/preg_match `preg_match()`] will be used. 
     423     *  
     424     * Otherwise the `$filter` will do a case-sensitive match with `*` matching 
     425     * zero or more characters and `?` matching a single character. 
     426     *  
     427     * On all OSes (even Windows), directories will be separated by `/`s when 
     428     * comparing with the `$filter`. 
     429     *  
     430     * @param  string $filter  A PCRE or glob pattern to filter files/directories by path - directories can be detected by checking for a trailing / (even on Windows) 
    418431     * @return array  The fFile (or fImage) and fDirectory objects for the files/directories in this directory 
    419432     */ 
    420     public function scan($regex_filter=NULL) 
    421     { 
    422         $this->tossIfDeleted(); 
    423          
    424         $files = array_diff(scandir($this->directory), array('.', '..')); 
     433    public function scan($filter=NULL) 
     434    { 
     435        $this->tossIfDeleted(); 
     436         
     437        $files   = array_diff(scandir($this->directory), array('.', '..')); 
    425438        $objects = array(); 
    426439         
     440        if ($filter && !preg_match('#^([^a-zA-Z0-9\\\\\s]).*\1[imsxeADSUXJu]*$#D', $filter)) { 
     441            $filter = '#^' . strtr( 
     442                preg_quote($filter, '#'), 
     443                array( 
     444                    '\\*' => '.*', 
     445                    '\\?' => '.' 
     446                ) 
     447            ) . '$#D'; 
     448        } 
     449         
     450        natcasesort($files); 
     451         
    427452        foreach ($files as $file) { 
    428             $file = $this->directory . $file; 
     453            if ($filter) { 
     454                $test_path = (is_dir($file)) ? $file . '/' : $file; 
     455                if (!preg_match($filter, $test_path)) { 
     456                    continue; 
     457                } 
     458            } 
    429459             
    430             if ($regex_filter) { 
    431                 $test_path = (is_dir($file)) ? $file . '/' : $file; 
    432                 if (!preg_match($regex_filter, $test_path)) { 
    433                     continue;    
    434                 } 
     460            $objects[] = fFilesystem::createObject($this->directory . $file); 
     461        } 
     462         
     463        return $objects; 
     464    } 
     465     
     466     
     467    /** 
     468     * Performs a **recursive** [http://php.net/scandir scandir()] on a directory, removing the `.` and `..` entries 
     469     *  
     470     * @param  string $filter  A PCRE or glob pattern to filter files/directories by path - see ::scan() for details 
     471     * @return array  The fFile (or fImage) and fDirectory objects for the files/directories (listed recursively) in this directory 
     472     */ 
     473    public function scanRecursive($filter=NULL) 
     474    { 
     475        $this->tossIfDeleted(); 
     476         
     477        $objects = $this->scan(); 
     478         
     479        $total_files = sizeof($objects); 
     480        for ($i=0; $i < $total_files; $i++) { 
     481            if ($objects[$i] instanceof fDirectory) { 
     482                array_splice($objects, $i+1, 0, $objects[$i]->scanRecursive()); 
     483            } 
     484        } 
     485         
     486        if ($filter) { 
     487            if (!preg_match('#^([^a-zA-Z0-9\\\\\s*?^$]).*\1[imsxeADSUXJu]*$#D', $filter)) { 
     488                $filter = '#^' . strtr( 
     489                    preg_quote($filter, '#'), 
     490                    array( 
     491                        '\\*' => '.*', 
     492                        '\\?' => '.' 
     493                    ) 
     494                ) . '$#D'; 
    435495            } 
    436496             
    437             $objects[] = fFilesystem::createObject($file); 
    438         } 
    439          
    440         return $objects; 
    441     } 
    442      
    443      
    444     /** 
    445      * Performs a **recursive** [http://php.net/scandir scandir()] on a directory, removing the `.` and `..` entries 
    446      *  
    447      * @param  string $regex_filter  A PCRE to filter files/directories by path, directories can be detected by checking for a trailing / (even on Windows) 
    448      * @return array  The fFile and fDirectory objects for the files/directory (listed recursively) in this directory 
    449      */ 
    450     public function scanRecursive($regex_filter=NULL) 
    451     { 
    452         $this->tossIfDeleted(); 
    453          
    454         $files   = $this->scan(); 
    455         $objects = $files; 
    456          
    457         $total_files = sizeof($files); 
    458         for ($i=0; $i < $total_files; $i++) { 
    459             if ($files[$i] instanceof fDirectory) { 
    460                 array_splice($objects, $i+1, 0, $files[$i]->scanRecursive()); 
    461             } 
    462         } 
    463          
    464         if ($regex_filter) { 
    465             $new_objects = array(); 
     497            $new_objects  = array(); 
     498            $strip_length = strlen($this->getPath()); 
    466499            foreach ($objects as $object) { 
    467                 $test_path = ($object instanceof fDirectory) ? substr($object->getPath(), 0, -1) . '/' : $object->getPath(); 
    468                 if (!preg_match($regex_filter, $test_path)) { 
     500                $test_path = substr($object->getPath(), $strip_length); 
     501                $test_path = str_replace(DIRECTORY_SEPARATOR, '/', $test_path); 
     502                if (!preg_match($filter, $test_path)) { 
    469503                    continue;    
    470504                }