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
10 namespace Zend\Code\Scanner
;
12 use RecursiveDirectoryIterator
;
13 use RecursiveIteratorIterator
;
14 use Zend\Code\Exception
;
16 class DirectoryScanner
implements ScannerInterface
21 protected $isScanned = false;
24 * @var string[]|DirectoryScanner[]
26 protected $directories = array();
31 protected $fileScanners = array();
36 protected $classToFileScanner = null;
39 * @param null|string|array $directory
41 public function __construct($directory = null)
44 if (is_string($directory)) {
45 $this->addDirectory($directory);
46 } elseif (is_array($directory)) {
47 foreach ($directory as $d) {
48 $this->addDirectory($d);
55 * @param DirectoryScanner|string $directory
57 * @throws Exception\InvalidArgumentException
59 public function addDirectory($directory)
61 if ($directory instanceof DirectoryScanner
) {
62 $this->directories
[] = $directory;
63 } elseif (is_string($directory)) {
64 $realDir = realpath($directory);
65 if (!$realDir ||
!is_dir($realDir)) {
66 throw new Exception\
InvalidArgumentException(sprintf(
67 'Directory "%s" does not exist',
71 $this->directories
[] = $realDir;
73 throw new Exception\
InvalidArgumentException(
74 'The argument provided was neither a DirectoryScanner or directory path'
80 * @param DirectoryScanner $directoryScanner
83 public function addDirectoryScanner(DirectoryScanner
$directoryScanner)
85 $this->addDirectory($directoryScanner);
89 * @param FileScanner $fileScanner
92 public function addFileScanner(FileScanner
$fileScanner)
94 $this->fileScanners
[] = $fileScanner;
100 protected function scan()
102 if ($this->isScanned
) {
106 // iterate directories creating file scanners
107 foreach ($this->directories
as $directory) {
108 if ($directory instanceof DirectoryScanner
) {
110 if ($directory->fileScanners
) {
111 $this->fileScanners
= array_merge($this->fileScanners
, $directory->fileScanners
);
114 $rdi = new RecursiveDirectoryIterator($directory);
115 foreach (new RecursiveIteratorIterator($rdi) as $item) {
116 if ($item->isFile() && pathinfo($item->getRealPath(), PATHINFO_EXTENSION
) == 'php') {
117 $this->fileScanners
[] = new FileScanner($item->getRealPath());
123 $this->isScanned
= true;
127 * @todo implement method
129 public function getNamespaces()
135 * @param bool $returnFileScanners
138 public function getFiles($returnFileScanners = false)
143 foreach ($this->fileScanners
as $fileScanner) {
144 $return[] = ($returnFileScanners) ?
$fileScanner : $fileScanner->getFile();
153 public function getClassNames()
157 if ($this->classToFileScanner
=== null) {
158 $this->createClassToFileScannerCache();
161 return array_keys($this->classToFileScanner
);
165 * @param bool $returnDerivedScannerClass
168 public function getClasses($returnDerivedScannerClass = false)
172 if ($this->classToFileScanner
=== null) {
173 $this->createClassToFileScannerCache();
176 $returnClasses = array();
177 foreach ($this->classToFileScanner
as $className => $fsIndex) {
178 $classScanner = $this->fileScanners
[$fsIndex]->getClass($className);
179 if ($returnDerivedScannerClass) {
180 $classScanner = new DerivedClassScanner($classScanner, $this);
182 $returnClasses[] = $classScanner;
185 return $returnClasses;
189 * @param string $class
192 public function hasClass($class)
196 if ($this->classToFileScanner
=== null) {
197 $this->createClassToFileScannerCache();
200 return (isset($this->classToFileScanner
[$class]));
204 * @param string $class
205 * @param bool $returnDerivedScannerClass
206 * @return ClassScanner|DerivedClassScanner
207 * @throws Exception\InvalidArgumentException
209 public function getClass($class, $returnDerivedScannerClass = false)
213 if ($this->classToFileScanner
=== null) {
214 $this->createClassToFileScannerCache();
217 if (!isset($this->classToFileScanner
[$class])) {
218 throw new Exception\
InvalidArgumentException('Class not found.');
221 /** @var FileScanner $fs */
222 $fs = $this->fileScanners
[$this->classToFileScanner
[$class]];
223 $returnClass = $fs->getClass($class);
225 if (($returnClass instanceof ClassScanner
) && $returnDerivedScannerClass) {
226 return new DerivedClassScanner($returnClass, $this);
233 * Create class to file scanner cache
237 protected function createClassToFileScannerCache()
239 if ($this->classToFileScanner
!== null) {
243 $this->classToFileScanner
= array();
244 /** @var FileScanner $fileScanner */
245 foreach ($this->fileScanners
as $fsIndex => $fileScanner) {
246 $fsClasses = $fileScanner->getClassNames();
247 foreach ($fsClasses as $fsClassName) {
248 $this->classToFileScanner
[$fsClassName] = $fsIndex;
256 * @todo implement method
258 public static function export()
266 * @todo implement method
268 public function __toString()