web/lib/Zend/File/ClassFileLocator.php
changeset 886 1e110b03ae96
parent 808 6b6c2214f778
child 1230 68c69c656a2c
equal deleted inserted replaced
885:2251fb41dbc7 886:1e110b03ae96
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_File
       
    17  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  */
       
    20 
       
    21 /**
       
    22  * Locate files containing PHP classes, interfaces, or abstracts
       
    23  * 
       
    24  * @package    Zend_File
       
    25  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
       
    26  * @license    New BSD {@link http://framework.zend.com/license/new-bsd}
       
    27  */
       
    28 class Zend_File_ClassFileLocator extends FilterIterator
       
    29 {
       
    30     /**
       
    31      * Create an instance of the locator iterator
       
    32      * 
       
    33      * Expects either a directory, or a DirectoryIterator (or its recursive variant) 
       
    34      * instance.
       
    35      * 
       
    36      * @param  string|DirectoryIterator $dirOrIterator 
       
    37      * @return void
       
    38      */
       
    39     public function __construct($dirOrIterator = '.')
       
    40     {
       
    41         if (is_string($dirOrIterator)) {
       
    42             if (!is_dir($dirOrIterator)) {
       
    43                 throw new InvalidArgumentException('Expected a valid directory name');
       
    44             }
       
    45 
       
    46             $dirOrIterator = new RecursiveDirectoryIterator($dirOrIterator);
       
    47         }
       
    48         if (!$dirOrIterator instanceof DirectoryIterator) {
       
    49             throw new InvalidArgumentException('Expected a DirectoryIterator');
       
    50         }
       
    51 
       
    52         if ($dirOrIterator instanceof RecursiveIterator) {
       
    53             $iterator = new RecursiveIteratorIterator($dirOrIterator);
       
    54         } else {
       
    55             $iterator = $dirOrIterator;
       
    56         }
       
    57 
       
    58         parent::__construct($iterator);
       
    59 
       
    60         // Forward-compat with PHP 5.3
       
    61         if (version_compare(PHP_VERSION, '5.3.0', '<')) {
       
    62             if (!defined('T_NAMESPACE')) {
       
    63                 define('T_NAMESPACE', 'namespace');
       
    64             }
       
    65             if (!defined('T_NS_SEPARATOR')) {
       
    66                 define('T_NS_SEPARATOR', '\\');
       
    67             }
       
    68         }
       
    69     }
       
    70 
       
    71     /**
       
    72      * Filter for files containing PHP classes, interfaces, or abstracts
       
    73      * 
       
    74      * @return bool
       
    75      */
       
    76     public function accept()
       
    77     {
       
    78         $file = $this->getInnerIterator()->current();
       
    79 
       
    80         // If we somehow have something other than an SplFileInfo object, just 
       
    81         // return false
       
    82         if (!$file instanceof SplFileInfo) {
       
    83             return false;
       
    84         }
       
    85 
       
    86         // If we have a directory, it's not a file, so return false
       
    87         if (!$file->isFile()) {
       
    88             return false;
       
    89         }
       
    90 
       
    91         // If not a PHP file, skip
       
    92         if ($file->getBasename('.php') == $file->getBasename()) {
       
    93             return false;
       
    94         }
       
    95 
       
    96         $contents = file_get_contents($file->getRealPath());
       
    97         $tokens   = token_get_all($contents);
       
    98         $count    = count($tokens);
       
    99         $i        = 0;
       
   100         while ($i < $count) {
       
   101             $token = $tokens[$i];
       
   102 
       
   103             if (!is_array($token)) {
       
   104                 // single character token found; skip
       
   105                 $i++;
       
   106                 continue;
       
   107             }
       
   108 
       
   109             list($id, $content, $line) = $token;
       
   110 
       
   111             switch ($id) {
       
   112                 case T_NAMESPACE:
       
   113                     // Namespace found; grab it for later
       
   114                     $namespace = '';
       
   115                     $done      = false;
       
   116                     do {
       
   117                         ++$i;
       
   118                         $token = $tokens[$i];
       
   119                         if (is_string($token)) {
       
   120                             if (';' === $token) {
       
   121                                 $done = true;
       
   122                             }
       
   123                             continue;
       
   124                         }
       
   125                         list($type, $content, $line) = $token;
       
   126                         switch ($type) {
       
   127                             case T_STRING:
       
   128                             case T_NS_SEPARATOR:
       
   129                                 $namespace .= $content;
       
   130                                 break;
       
   131                         }
       
   132                     } while (!$done && $i < $count);
       
   133 
       
   134                     // Set the namespace of this file in the object
       
   135                     $file->namespace = $namespace;
       
   136                     break;
       
   137                 case T_CLASS:
       
   138                 case T_INTERFACE:
       
   139                     // Abstract class, class, or interface found
       
   140 
       
   141                     // Get the classname
       
   142                     $class = '';
       
   143                     do {
       
   144                         ++$i;
       
   145                         $token = $tokens[$i];
       
   146                         if (is_string($token)) {
       
   147                             continue;
       
   148                         }
       
   149                         list($type, $content, $line) = $token;
       
   150                         switch ($type) {
       
   151                             case T_STRING:
       
   152                                 $class = $content;
       
   153                                 break;
       
   154                         }
       
   155                     } while (empty($class) && $i < $count);
       
   156 
       
   157                     // If a classname was found, set it in the object, and 
       
   158                     // return boolean true (found)
       
   159                     if (!empty($class)) {
       
   160                         $file->classname = $class;
       
   161                         return true;
       
   162                     }
       
   163                     break;
       
   164                 default:
       
   165                     break;
       
   166             }
       
   167             ++$i;
       
   168         }
       
   169 
       
   170         // No class-type tokens found; return false
       
   171         return false;
       
   172     }
       
   173 }