<?php
/**
 * Klassenaamscanner inclusief voorbeeld
 *
 * @author Richard van Velzen
 */

/**
 * Scanner voor klasse- en interfacenamen in een bestand
 *
 * @param string $inputFile Bestand waarin namen gevonden moeten worden
 * @return array Array van klasse- en interfacenamen
 * @author Richard van Velzen
 */
function classNameScanner($inputFile) {
	if(!is_readable($inputFile)) {
		throw new InvalidArgumentException('Inputbestand is niet leesbaar');
	}

	$foundNames = array();
	// haal alle tokens uit het bestand op
	$tokens = token_get_all(file_get_contents($inputFile));
		
	for($i = 0, $length = count($tokens); $i !== $length; ++$i) {
		if(is_array($tokens[$i]) && ($tokens[$i][0] === T_CLASS || $tokens[$i][0] === T_INTERFACE)) {
			// begin te zoeken naar een T_STRING, en skip whitespace en comments
			for($j = $i + 1; $j !== $length; ++$j) {
				if(is_array($tokens[$j])) {
					if($tokens[$j][0] == T_STRING) {
						// we hebben een naam gevonden, gooi maar in de array
						$foundNames[] = $tokens[$j][1];
						continue 2;
					} elseif($tokens[$j][0] == T_WHITESPACE || $tokens[$j][0] == T_COMMENT || $tokens[$j][0] == T_DOC_COMMENT) {
						// whitespace en comments skippen we
						continue;
					}
				}
				
				// hier klopt iets niet, hier hadden we nooit moeten komen
				// gooi een exception aangezien de syntax niet klopt en dit
				// bestand dus nooit geinclude kan worden
				throw new RuntimeException('Syntaxfout: geen naam gevonden na "class" of "interface"');
			}
		}
	}
		
	return $foundNames;
}

// stel je eigen includepath hier in
set_include_path('framework' . PATH_SEPARATOR . get_include_path());

$classMap = array();

// we willen het hele includepath maar al te graag gebruiken :-)
foreach(explode(PATH_SEPARATOR, get_include_path()) as $includePath) {
	// OS specifieke directory separator gebruiken
	$includePath = str_replace('\/', DIRECTORY_SEPARATOR, $includePath);
	if(substr($includePath, - 1, 1) !== DIRECTORY_SEPARATOR) {
		$includePath .= DIRECTORY_SEPARATOR; 
	}
	
	// haal alle PHP en INC files op
	$files = glob($includePath . '*.{php,inc}', GLOB_BRACE);
	
	foreach($files as $file) {
		$file = realpath($file);
		foreach(classNameScanner($file) as $className) {
			$className = strtolower($className);
			if(!isset($classMap[$className])) {
				// alleen de eerste nemen, de rest zou nooit geinclude worden
				$classMap[$className] = $file;
			}
		}
	}
}

print_r($classMap);
?>