private static function searchPath($prefix, $path, $conditions)
	{
		$result = [];
		
		$dir = new DirectoryIterator($path);
		foreach ( $dir as $entry ) {
			if ( $entry->isDot() ) {
				continue;
			}
			
			$de = $entry->getFilename();
			
			if ( $entry->isDir() && preg_match('/^[A-Za-z_]+$/', $de) ) {
				// it's a subdirectory, search it
				$result = array_merge($result, self::searchPath("$prefix\\$de", $path . DIRECTORY_SEPARATOR . $de, $conditions));
			}
			else if ( preg_match('/\.php$/', $de) ) {
				// FIXME I'm using a regex test here because that in theory is quicker than having
				// PHP parse the file. Also, this is deliberately designed to exclude abstract classes,
				// which will cause class_exists() to return (bool)true.
				
				$foundNamespace = $foundClass = false;
				$className = preg_replace('/\.php$/', '', $de);
				
				if ( $fp = @fopen($filePath = "$path/$de", 'r') ) {
					
					while ( !feof($fp) && ($line = fgets($fp)) ) {
						// FIXME PHP leaves pretty little room for error in the namespace declaration
						// line. This is still a little needlessly picky - if someone has a space between
						// the namespace name and the semicolon this test will fail, as well as dumber
						// stuff like the word "namespace" being mixed case/uppercase.
						if ( trim($line) === "namespace $prefix;" ) {
							$foundNamespace = true;
						}
						// This fairly complicated regexp covers "implements" with multiple inheritance,
						// "extends" and a fair amount of syntactical deviation.
						else if ( preg_match('/^\s*class ([A-Za-z0-9_]+)(?:\s+(?:extends|implements) [A-Za-z0-9_\\\\]+(?:\s*,\s*[A-Za-z0-9_]+)*)*\s*[\{,]?$/', trim($line), $match)
								&& ($match[1] === "\\$prefix\\$className" || $match[1] === $className) ) {
							$foundClass = true;
						}
						
						// if we have found the namespace declaration and the class declaration,
						// we no longer need any more information from this file, so break and
						// close the handle.
						if ( $foundNamespace && $foundClass ) {
							break;
						}
					}
					
					fclose($fp);
				}
				
				// if we found the namespace declaration and the class declaration, append
				// the discovered class to the result list.
				if ( $foundNamespace && $foundClass )
				{
					// fully qualified class name
					$fqcn = "$prefix\\$className";
					
					// conditions are an OR between each, AND within an individual condition
					$condCount = 0;
					
					// ReflectionClass instance - created only if necessary
					$rfl = null;
					foreach ( $conditions as $cond ) {
						$condResult = true;
						foreach ( $cond as $test => $value ) {
							switch($test) {
							case 'implements':
								if ( empty($rfl) ) {
									$rfl = new \ReflectionClass($fqcn);
								}
								if ( !$rfl->implementsInterface($value) ) {
									$condResult = false;
									break 2; // lazy evaluation
								}
								break;
							case 'extends':
								if ( empty($rfl) ) {
									$rfl = new \ReflectionClass($fqcn);
								}
								if ( $rfl->getParentClass()->getName() !== $value ) {
									$condResult = false;
									break 2; // lazy evaluation
								}
								break;
							case 'abstract':
								if ( empty($rfl) ) {
									$rfl = new \ReflectionClass($fqcn);
								}
								if ( $rfl->isAbstract() !== $value ) {
									$condResult = false;
									break 2; // lazy evaluation
								}
								break;
							}
						}
						if ( $condResult ) {
							$condCount++;
						}
					}
					
					if ( $condCount || count($conditions) === 0 ) {
						$result[] = $fqcn;
					}
				}
			}
		}
		
		return $result;
	}
private static function searchPath($prefix, $path, $conditions)
	{
		$result = [];
		
		$dir = new DirectoryIterator($path);
		foreach ( $dir as $entry ) {
			if ( $entry->isDot() ) {
				continue;
			}
			
			$de = $entry->getFilename();
			
			if ( $entry->isDir() && preg_match('/^[A-Za-z_]+$/', $de) ) {
				// it's a subdirectory, search it
				$result = array_merge($result, self::searchPath("$prefix\\$de", $path . DIRECTORY_SEPARATOR . $de, $conditions));
			}
			else if ( preg_match('/\.php$/', $de) ) {
				// FIXME I'm using a regex test here because that in theory is quicker than having
				// PHP parse the file. Also, this is deliberately designed to exclude abstract classes,
				// which will cause class_exists() to return (bool)true.
				
				$foundNamespace = $foundClass = false;
				$className = preg_replace('/\.php$/', '', $de);
				
				if ( $fp = @fopen($filePath = "$path/$de", 'r') ) {
					
					while ( !feof($fp) && ($line = fgets($fp)) ) {
						// FIXME PHP leaves pretty little room for error in the namespace declaration
						// line. This is still a little needlessly picky - if someone has a space between
						// the namespace name and the semicolon this test will fail, as well as dumber
						// stuff like the word "namespace" being mixed case/uppercase.
						if ( trim($line) === "namespace $prefix;" ) {
							$foundNamespace = true;
						}
						// This fairly complicated regexp covers "implements" with multiple inheritance,
						// "extends" and a fair amount of syntactical deviation.
						else if ( preg_match('/^\s*class ([A-Za-z0-9_]+)(?:\s+(?:extends|implements) [A-Za-z0-9_\\\\]+(?:\s*,\s*[A-Za-z0-9_]+)*)*\s*[\{,]?$/', trim($line), $match)
								&& ($match[1] === "\\$prefix\\$className" || $match[1] === $className) ) {
							$foundClass = true;
						}
						
						// if we have found the namespace declaration and the class declaration,
						// we no longer need any more information from this file, so break and
						// close the handle.
						if ( $foundNamespace && $foundClass ) {
							break;
						}
					}
					
					fclose($fp);
				}
				
				// if we found the namespace declaration and the class declaration, append
				// the discovered class to the result list.
				if ( $foundNamespace && $foundClass )
				{
					// fully qualified class name
					$fqcn = "$prefix\\$className";
					
					// conditions are an OR between each, AND within an individual condition
					$condCount = 0;
					
					// ReflectionClass instance - created only if necessary
					$rfl = null;
					foreach ( $conditions as $cond ) {
						$condResult = true;
						foreach ( $cond as $test => $value ) {
							switch($test) {
							case 'implements':
								if ( empty($rfl) ) {
									$rfl = new \ReflectionClass($fqcn);
								}
								if ( !$rfl->implementsInterface($value) ) {
									$condResult = false;
									break 2; // lazy evaluation
								}
								break;
							case 'extends':
								if ( empty($rfl) ) {
									$rfl = new \ReflectionClass($fqcn);
								}
								if ( $rfl->getParentClass()->getName() !== $value ) {
									$condResult = false;
									break 2; // lazy evaluation
								}
								break;
							case 'abstract':
								if ( empty($rfl) ) {
									$rfl = new \ReflectionClass($fqcn);
								}
								if ( $rfl->isAbstract() !== $value ) {
									$condResult = false;
									break 2; // lazy evaluation
								}
								break;
							}
						}
						if ( $condResult ) {
							$condCount++;
						}
					}
					
					if ( $condCount || count($conditions) === 0 ) {
						$result[] = $fqcn;
					}
				}
			}
		}
		
		return $result;
	}
private static function searchPath ( $ prefix , $ path , $ conditions ) { $ result = [ ] ; $ dir = new DirectoryIterator ( $ path ) ; foreach ( $ dir as $ entry ) { if ( $ entry -> isDot ( ) ) { continue ; } $ de = $ entry -> getFilename ( ) ; if ( $ entry -> isDir ( ) && preg_match ( '/^[A-Za-z_]+$/' , $ de ) ) { // it's a subdirectory, search it $ result = array_merge ( $ result , self :: searchPath ( "$prefix\\$de" , $ path . DIRECTORY_SEPARATOR . $ de , $ conditions ) ) ; } else if ( preg_match ( '/\.php$/' , $ de ) ) { // FIXME I'm using a regex test here because that in theory is quicker than having // PHP parse the file. Also, this is deliberately designed to exclude abstract classes, // which will cause class_exists() to return (bool)true. $ foundNamespace = $ foundClass = false ; $ className = preg_replace ( '/\.php$/' , '' , $ de ) ; if ( $ fp = @ fopen ( $ filePath = "$path/$de" , 'r' ) ) { while ( ! feof ( $ fp ) && ( $ line = fgets ( $ fp ) ) ) { // FIXME PHP leaves pretty little room for error in the namespace declaration // line. This is still a little needlessly picky - if someone has a space between // the namespace name and the semicolon this test will fail, as well as dumber // stuff like the word "namespace" being mixed case/uppercase. if ( trim ( $ line ) === "namespace $prefix;" ) { $ foundNamespace = true ; } // This fairly complicated regexp covers "implements" with multiple inheritance, // "extends" and a fair amount of syntactical deviation. else if ( preg_match ( '/^\s*class ([A-Za-z0-9_]+)(?:\s+(?:extends|implements) [A-Za-z0-9_\\\\]+(?:\s*,\s*[A-Za-z0-9_]+)*)*\s*[\{,]?$/' , trim ( $ line ) , $ match ) && ( $ match [ 1 ] === "\\$prefix\\$className" || $ match [ 1 ] === $ className ) ) { $ foundClass = true ; } // if we have found the namespace declaration and the class declaration, // we no longer need any more information from this file, so break and // close the handle. if ( $ foundNamespace && $ foundClass ) { break ; } } fclose ( $ fp ) ; } // if we found the namespace declaration and the class declaration, append // the discovered class to the result list. if ( $ foundNamespace && $ foundClass ) { // fully qualified class name $ fqcn = "$prefix\\$className" ; // conditions are an OR between each, AND within an individual condition $ condCount = 0 ; // ReflectionClass instance - created only if necessary $ rfl = null ; foreach ( $ conditions as $ cond ) { $ condResult = true ; foreach ( $ cond as $ test => $ value ) { switch ( $ test ) { case 'implements' : if ( empty ( $ rfl ) ) { $ rfl = new \ ReflectionClass ( $ fqcn ) ; } if ( ! $ rfl -> implementsInterface ( $ value ) ) { $ condResult = false ; break 2 ; // lazy evaluation } break ; case 'extends' : if ( empty ( $ rfl ) ) { $ rfl = new \ ReflectionClass ( $ fqcn ) ; } if ( $ rfl -> getParentClass ( ) -> getName ( ) !== $ value ) { $ condResult = false ; break 2 ; // lazy evaluation } break ; case 'abstract' : if ( empty ( $ rfl ) ) { $ rfl = new \ ReflectionClass ( $ fqcn ) ; } if ( $ rfl -> isAbstract ( ) !== $ value ) { $ condResult = false ; break 2 ; // lazy evaluation } break ; } } if ( $ condResult ) { $ condCount ++ ; } } if ( $ condCount || count ( $ conditions ) === 0 ) { $ result [ ] = $ fqcn ; } } } } return $ result ; }
Search one directory recursively for classes belonging to a given namespace.
@param string Namespace to search for
@param string Directory to search
@param array Search conditions
@return array
@access private
@static
Search one directory recursively for classes belonging to a given namespace .