3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
12 use DirectoryIterator
;
14 use RecursiveDirectoryIterator
;
15 use RecursiveIterator
;
16 use RecursiveIteratorIterator
;
20 * Locate files containing PHP classes, interfaces, abstracts or traits
22 class ClassFileLocator
extends FilterIterator
25 * Create an instance of the locator iterator
27 * Expects either a directory, or a DirectoryIterator (or its recursive variant)
30 * @param string|DirectoryIterator $dirOrIterator
31 * @throws Exception\InvalidArgumentException
33 public function __construct($dirOrIterator = '.')
35 if (is_string($dirOrIterator)) {
36 if (!is_dir($dirOrIterator)) {
37 throw new Exception\
InvalidArgumentException('Expected a valid directory name');
40 $dirOrIterator = new RecursiveDirectoryIterator($dirOrIterator, RecursiveDirectoryIterator
::FOLLOW_SYMLINKS
);
41 } elseif (!$dirOrIterator instanceof DirectoryIterator
) {
42 throw new Exception\
InvalidArgumentException('Expected a DirectoryIterator');
45 if ($dirOrIterator instanceof RecursiveIterator
) {
46 $dirOrIterator = new RecursiveIteratorIterator($dirOrIterator);
49 parent
::__construct($dirOrIterator);
50 $this->setInfoClass('Zend\File\PhpClassFile');
54 * Filter for files containing PHP classes, interfaces, or abstracts
58 public function accept()
60 $file = $this->getInnerIterator()->current();
61 // If we somehow have something other than an SplFileInfo object, just
63 if (!$file instanceof SplFileInfo
) {
67 // If we have a directory, it's not a file, so return false
68 if (!$file->isFile()) {
72 // If not a PHP file, skip
73 if ($file->getBasename('.php') == $file->getBasename()) {
77 $contents = file_get_contents($file->getRealPath());
78 $tokens = token_get_all($contents);
79 $count = count($tokens);
80 $t_trait = defined('T_TRAIT') ? T_TRAIT
: -1; // For preserve PHP 5.3 compatibility
81 for ($i = 0; $i < $count; $i++
) {
83 if (!is_array($token)) {
84 // single character token found; skip
90 // Namespace found; grab it for later
92 for ($i++
; $i < $count; $i++
) {
94 if (is_string($token)) {
96 $saveNamespace = false;
100 $saveNamespace = true;
105 list($type, $content, $line) = $token;
109 $namespace .= $content;
113 if ($saveNamespace) {
114 $savedNamespace = $namespace;
120 // Abstract class, class, interface or trait found
123 for ($i++
; $i < $count; $i++
) {
124 $token = $tokens[$i];
125 if (is_string($token)) {
128 list($type, $content, $line) = $token;
129 if (T_STRING
== $type) {
130 // If a classname was found, set it in the object, and
131 // return boolean true (found)
132 if (!isset($namespace) ||
null === $namespace) {
133 if (isset($saveNamespace) && $saveNamespace) {
134 $namespace = $savedNamespace;
140 $class = (null === $namespace) ?
$content : $namespace . '\\' . $content;
141 $file->addClass($class);
143 $file->addNamespace($namespace);
154 $classes = $file->getClasses();
155 if (!empty($classes)) {
158 // No class-type tokens found; return false