3030either expressed or implied, of the FreeBSD Project.
3131 */
3232
33+
3334require_once __DIR__ . '/exceptions.php ' ;
3435require_once __DIR__ . '/Settings.php ' ;
3536require_once __DIR__ . '/Process.php ' ;
3637require_once __DIR__ . '/Output.php ' ;
3738require_once __DIR__ . '/Error.php ' ;
3839
39-
40- class ArrayIterator extends \ArrayIterator
41- {
42- public function getNext ()
43- {
44- $ this ->next ();
45- return $ this ->current ();
46- }
47- }
48-
4940class Manager
5041{
5142 const CODE_OK = 0 ,
@@ -58,6 +49,7 @@ class Manager
5849 * @param array $arguments
5950 * @return Settings
6051 * @throws InvalidArgumentException
52+ * @throws Exception
6153 */
6254 public function parseArguments (array $ arguments )
6355 {
@@ -68,24 +60,30 @@ public function parseArguments(array $arguments)
6860 if ($ argument {0 } !== '- ' ) {
6961 $ setting ->paths [] = $ argument ;
7062 } else {
71- switch (substr ( $ argument, 1 ) ) {
72- case 'p ' :
63+ switch ($ argument ) {
64+ case '- p ' :
7365 $ setting ->phpExecutable = $ arguments ->getNext ();
7466 break ;
7567
76- case 'short ' :
68+ case '-s ' :
69+ case '--short ' :
7770 $ setting ->shortTag = true ;
7871 break ;
7972
80- case 'asp ' :
73+ case '-a ' :
74+ case '--asp ' :
8175 $ setting ->aspTags = true ;
8276 break ;
8377
84- case 'e ' :
78+ case '--exclude ' :
79+ $ setting ->excluded [] = $ arguments ->getNext ();
80+ break ;
81+
82+ case '-e ' :
8583 $ setting ->extensions = array_map ('trim ' , explode (', ' , $ arguments ->getNext ()));
8684 break ;
8785
88- case 'j ' :
86+ case '- j ' :
8987 $ setting ->parallelJobs = max ((int ) $ arguments ->getNext (), 1 );
9088 break ;
9189
@@ -95,6 +93,10 @@ public function parseArguments(array $arguments)
9593 }
9694 }
9795
96+ if (empty ($ setting ->paths )) {
97+ throw new Exception ('No path set. ' );
98+ }
99+
98100 return $ setting ;
99101 }
100102
@@ -106,13 +108,17 @@ public function parseArguments(array $arguments)
106108 public function run (Settings $ settings = null )
107109 {
108110 $ settings = $ settings ?: new Settings ;
111+ $ output = $ this ->output ?: new Output (new ConsoleWriter );
109112
110113 $ this ->checkPhpExecutableExists ($ settings ->phpExecutable );
111114
112115 $ cmdLine = $ this ->getCmdLine ($ settings );
113- $ files = $ this ->getFilesFromPaths ($ settings ->paths , $ settings ->extensions );
116+ $ files = $ this ->getFilesFromPaths ($ settings ->paths , $ settings ->extensions , $ settings ->excluded );
117+
118+ if (empty ($ files )) {
119+ throw new Exception ('No file found to check. ' );
120+ }
114121
115- $ output = $ this ->output ?: new Output (new ConsoleWriter );
116122 $ output ->setTotalFileCount (count ($ files ));
117123
118124 /** @var LintProcess[] $running */
@@ -216,10 +222,11 @@ protected function getCmdLine(Settings $settings)
216222 /**
217223 * @param array $paths
218224 * @param array $extensions
225+ * @param array $excluded
219226 * @return array
220227 * @throws NotExistsPathException
221228 */
222- protected function getFilesFromPaths (array $ paths , array $ extensions )
229+ protected function getFilesFromPaths (array $ paths , array $ extensions, array $ excluded = array () )
223230 {
224231 $ extensions = array_flip ($ extensions );
225232 $ files = array ();
@@ -228,11 +235,17 @@ protected function getFilesFromPaths(array $paths, array $extensions)
228235 if (is_file ($ path )) {
229236 $ files [] = $ path ;
230237 } else if (is_dir ($ path )) {
231- $ directoryFiles = new \RecursiveIteratorIterator (new \RecursiveDirectoryIterator ($ path ));
232- foreach ($ directoryFiles as $ directoryFile ) {
233- $ directoryFile = (string ) $ directoryFile ;
234- if (isset ($ extensions [pathinfo ($ directoryFile , PATHINFO_EXTENSION )])) {
235- $ files [] = $ directoryFile ;
238+
239+ $ iterator = new \RecursiveDirectoryIterator ($ path );
240+ if (!empty ($ excluded )) {
241+ $ iterator = new ExcludeRecursiveDirectoryIterator ($ iterator , $ excluded );
242+ }
243+ $ iterator = new \RecursiveIteratorIterator ($ iterator );
244+
245+ /** @var \SplFileInfo[] $iterator */
246+ foreach ($ iterator as $ directoryFile ) {
247+ if (isset ($ extensions [$ directoryFile ->getExtension ()])) {
248+ $ files [] = (string ) $ directoryFile ;
236249 }
237250 }
238251 } else {
@@ -242,4 +255,145 @@ protected function getFilesFromPaths(array $paths, array $extensions)
242255
243256 return $ files ;
244257 }
258+ }
259+
260+ class ArrayIterator extends \ArrayIterator
261+ {
262+ public function getNext ()
263+ {
264+ $ this ->next ();
265+ return $ this ->current ();
266+ }
267+ }
268+
269+ class ExcludeRecursiveDirectoryIterator implements \RecursiveIterator
270+ {
271+ /** @var array */
272+ private $ excluded = array ();
273+
274+ /** @var \RecursiveDirectoryIterator */
275+ private $ iterator ;
276+
277+ /**
278+ * @param array $excluded
279+ * @param \RecursiveDirectoryIterator $iterator
280+ */
281+ public function __construct (\RecursiveDirectoryIterator $ iterator , array $ excluded )
282+ {
283+ $ this ->iterator = $ iterator ;
284+ $ this ->excluded = array_map (array ($ this , 'normalizePath ' ), $ excluded );
285+ }
286+
287+ /**
288+ * (PHP 5 >= 5.0.0)<br/>
289+ * Return the current element
290+ * @link http://php.net/manual/en/iterator.current.php
291+ * @return mixed Can return any type.
292+ */
293+ public function current ()
294+ {
295+ return $ this ->iterator ->current ();
296+ }
297+
298+ /**
299+ * (PHP 5 >= 5.0.0)<br/>
300+ * Move forward to next element
301+ * @link http://php.net/manual/en/iterator.next.php
302+ * @return void Any returned value is ignored.
303+ */
304+ public function next ()
305+ {
306+ $ this ->iterator ->next ();
307+ }
308+
309+ /**
310+ * (PHP 5 >= 5.0.0)<br/>
311+ * Return the key of the current element
312+ * @link http://php.net/manual/en/iterator.key.php
313+ * @return mixed scalar on success, or null on failure.
314+ */
315+ public function key ()
316+ {
317+ return $ this ->iterator ->key ();
318+ }
319+
320+ /**
321+ * (PHP 5 >= 5.0.0)<br/>
322+ * Checks if current position is valid
323+ * @link http://php.net/manual/en/iterator.valid.php
324+ * @return boolean The return value will be casted to boolean and then evaluated.
325+ * Returns true on success or false on failure.
326+ */
327+ public function valid ()
328+ {
329+ return $ this ->iterator ->valid ();
330+ }
331+
332+ /**
333+ * (PHP 5 >= 5.0.0)<br/>
334+ * Rewind the Iterator to the first element
335+ * @link http://php.net/manual/en/iterator.rewind.php
336+ * @return void Any returned value is ignored.
337+ */
338+ public function rewind ()
339+ {
340+ $ this ->iterator ->rewind ();
341+ }
342+
343+ /**
344+ * (PHP 5 >= 5.1.0)<br/>
345+ * Returns if an iterator can be created for the current entry.
346+ * @link http://php.net/manual/en/recursiveiterator.haschildren.php
347+ * @return bool true if the current entry can be iterated over, otherwise returns false.
348+ */
349+ public function hasChildren ()
350+ {
351+ $ path = $ this ->normalizePath ($ this ->iterator ->getPathname ());
352+ foreach ($ this ->excluded as $ exc ) {
353+ if (strpos ($ path , $ exc ) === 0 ) {
354+ return false ;
355+ }
356+ }
357+
358+ return $ this ->iterator ->hasChildren ();
359+ }
360+
361+ /**
362+ * (PHP 5 >= 5.1.0)<br/>
363+ * Returns an iterator for the current entry.
364+ * @link http://php.net/manual/en/recursiveiterator.getchildren.php
365+ * @return \RecursiveIterator An iterator for the current entry.
366+ */
367+ public function getChildren ()
368+ {
369+ return new self ($ this ->iterator ->getChildren (), $ this ->excluded );
370+ }
371+
372+
373+ /**
374+ * Source: http://stackoverflow.com/questions/4774116/c-realpath-without-resolving-symlinks
375+ * @param string $path
376+ * @return string
377+ */
378+ private function normalizePath ($ path )
379+ {
380+ if (!isset ($ path [0 ]) || $ path [0 ] !== DIRECTORY_SEPARATOR ) {
381+ $ result = explode (DIRECTORY_SEPARATOR , getcwd ());
382+ } else {
383+ $ result = array ('' );
384+ }
385+
386+ $ parts = explode (DIRECTORY_SEPARATOR , $ path );
387+ foreach ($ parts as $ part ) {
388+ if ($ part === '' || $ part === '. ' ) {
389+ continue ;
390+ } if ($ part === '.. ' ) {
391+ array_pop ($ result );
392+ } else {
393+ $ result [] = $ part ;
394+ }
395+ }
396+
397+ return implode (DIRECTORY_SEPARATOR , $ result );
398+ }
245399}
0 commit comments