diff --git a/autoloader.php b/autoloader.php index 6de3529..129580a 100644 --- a/autoloader.php +++ b/autoloader.php @@ -2,21 +2,21 @@ /** * Example autoload implementation which uses the generated class map configuration * - * This file contains the class definition and the registration of the autoloader - * together for the sake of simplicity. This is up to you to separate the logic to + * This file contains the class definition and the registration of the autoloader + * together for the sake of simplicity. This is up to you to separate the logic to * your requirements/wishes. * * Usage: *
- * // include this file, e. g. at the beginning of your scripts or in a bootstrap 
+ * // include this file, e. g. at the beginning of your scripts or in a bootstrap
  * // implementation
  * require_once('/path/to/autoloader.php');
  * // ... then use your classes ...
  * 
* * @category Development - * @package mpAutoloaderClassMap - * @author Murat Purc + * @package mpAutoloaderClassMap + * @author Murat Purc * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 * @version $Id$ @@ -37,7 +37,7 @@ class myAutoloader /** * Autoloader implementation * @param string $name The required class name - * @throws Exception if autoloader couldn't set class map configuration in initial call + * @throws Exception if autoloader couldn't set class map configuration in initial call */ public static function autoload($name) { diff --git a/example.php b/example.php index 85b2902..c96e511 100644 --- a/example.php +++ b/example.php @@ -1,83 +1,83 @@ - - * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) - * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 - * @version $Id$ - */ - - -################################################################################ -##### Initialization/Settings - -// create a page context class, better than spamming global scope -$context = new stdClass(); - -// current path -$context->currentPath = str_replace('\\', '/', realpath(dirname(__FILE__) . '/')) . '/'; - -// the destination file where the class map configuration should be written in -$context->destinationFile = $context->currentPath . '/classmap.configuration.php'; - -// list of paths from where all class/interface names should be found -// NOTE: Path depends on used environment and should be adapted -$context->pathsToParse = array( - '/path/to/my/project' -); - -// list to collect class maps -$context->classMapList = array(); - -// class file finder options -$context->options = array( - // exclude following folder names - 'excludeDirs' => array('temp', 'session', 'docs', 'tests'), - // no specific file exclusion - 'excludeFiles' => array(), - // parse all files with '.php' extension - 'extensionsToParse' => '.php', - // disbale debugging - 'enableDebug' => false, -); - - -################################################################################ -##### Process - -// include required classes -include_once($context->currentPath . 'lib/mpClassTypeFinder.php'); -include_once($context->currentPath . 'lib/mpClassMapFileCreator.php'); - -// collect all found class/interface names with their paths -$context->classTypeFinder = new mpClassTypeFinder($context->options); -foreach ($context->pathsToParse as $pos => $dir) { - $classMap = $context->classTypeFinder->findInDir(new SplFileInfo($dir), true); - if ($classMap) { - $context->classMapList = array_merge($context->classMapList, $classMap); - } -} - -// uncomment following line to get some debug messages -#echo $context->classTypeFinder->getFormattedDebugMessages(); - - -// write the class map configuration -$context->classMapCreator = new mpClassMapFileCreator(); -$context->classMapCreator->create($context->classMapList, $context->destinationFile); - - -// cleanup + + * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) + * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 + * @version $Id$ + */ + + +################################################################################ +##### Initialization/Settings + +// create a page context class, better than spamming global scope +$context = new stdClass(); + +// current path +$context->currentPath = str_replace('\\', '/', realpath(dirname(__FILE__) . '/')) . '/'; + +// the destination file where the class map configuration should be written in +$context->destinationFile = $context->currentPath . '/classmap.configuration.php'; + +// list of paths from where all class/interface names should be found +// NOTE: Path depends on used environment and should be adapted +$context->pathsToParse = array( + '/path/to/my/project' +); + +// list to collect class maps +$context->classMapList = array(); + +// class file finder options +$context->options = array( + // exclude following folder names + 'excludeDirs' => array('temp', 'session', 'docs', 'tests'), + // no specific file exclusion + 'excludeFiles' => array(), + // parse all files with '.php' extension + 'extensionsToParse' => '.php', + // disbale debugging + 'enableDebug' => false, +); + + +################################################################################ +##### Process + +// include required classes +include_once($context->currentPath . 'lib/mpClassTypeFinder.php'); +include_once($context->currentPath . 'lib/mpClassMapFileCreator.php'); + +// collect all found class/interface names with their paths +$context->classTypeFinder = new mpClassTypeFinder($context->options); +foreach ($context->pathsToParse as $pos => $dir) { + $classMap = $context->classTypeFinder->findInDir(new SplFileInfo($dir), true); + if ($classMap) { + $context->classMapList = array_merge($context->classMapList, $classMap); + } +} + +// uncomment following line to get some debug messages +#echo $context->classTypeFinder->getFormattedDebugMessages(); + + +// write the class map configuration +$context->classMapCreator = new mpClassMapFileCreator(); +$context->classMapCreator->create($context->classMapList, $context->destinationFile); + + +// cleanup unset($context); \ No newline at end of file diff --git a/lib/mpClassMapFileCreator.php b/lib/mpClassMapFileCreator.php index d135c1e..b63afc7 100644 --- a/lib/mpClassMapFileCreator.php +++ b/lib/mpClassMapFileCreator.php @@ -1,135 +1,135 @@ - - * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) - * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 - * @version $Id$ - */ - - -/** - * Class to create a PHP file which contains a assoziative PHP array. - * - * Generated file will contain a PHP array as following: - * - * return array( - * '{classname}' => '{path_to_classfile}', - * '{classname2}' => '{path_to_classfile2}', - * ); - * - * - * @category Development - * @package mpAutoloaderClassMap - * @author Murat Purc - */ -class mpClassMapFileCreator -{ - /** - * Class map file template - * @var string - */ - protected $_template = ''; - - /** - * Template replacements - * @var stdClass - */ - protected $_data = ''; - - - /** - * Sets template and template replacements - * - * @return void - */ - public function __construct() - { - $this->_template = trim(' -_data = new stdClass(); - $this->_data->content = ''; - $this->_data->description = trim(' - * Autoloader classmap file. Contains all available classes/interfaces and - * related class files. - * - * NOTES: - * - Don\'t edit this file manually! - * - It was generated by ' . __CLASS__ . ' - * - Use ' . __CLASS__ . ' again, if you want to regenerate this file - *'); - - $this->_data->package = __CLASS__; - $this->_data->subpackage = 'Classmap'; - $this->_data->version = '0.1'; - $this->_data->author = 'System'; - $this->_data->copyright = 'Copyright (c) 2009-2011 Murat Purc (http://www.purc.de)'; - $this->_data->license = 'http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2'; - } - - - /** - * Creates classmap file with passed data list - * - * @param array $data Assoziative list which contains class type tokens and - * the related path to the class file. - * @param string $file Destination class map file - * @return void - */ - public function create(array $data, $file) - { - $this->_createClassMap($data); - return (bool) file_put_contents($file, $this->_renderTemplate()); - } - - - /** - * Fills template replacement variable with generated assoziative PHP array - * - * @var array $data Assoziative list with class type tokens and files - * @return void - */ - protected function _createClassMap(array $data) - { - $classMapTpl = "\nreturn array(\n%s\n);\n"; - $classMapContent = ''; - foreach ($data as $classToken => $path) { - $classMapContent .= sprintf(" '%s' => '%s',\n", addslashes($classToken), addslashes($path)); - } - $classMapContent = substr($classMapContent, 0, -2); - - $this->_data->content .= sprintf($classMapTpl, $classMapContent); - } - - - /** - * Replaces all wildcards in template with related template variables. - * - * @return string Replaced template - */ - protected function _renderTemplate() - { - $template = $this->_template; - foreach ($this->_data as $name => $value) { - $template = str_replace('{' . strtoupper($name) . '}', $value, $template); - } - return $template; - } - -} + + * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) + * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 + * @version $Id$ + */ + + +/** + * Class to create a PHP file which contains a assoziative PHP array. + * + * Generated file will contain a PHP array as following: + * + * return array( + * '{classname}' => '{path_to_classfile}', + * '{classname2}' => '{path_to_classfile2}', + * ); + * + * + * @category Development + * @package mpAutoloaderClassMap + * @author Murat Purc + */ +class mpClassMapFileCreator +{ + /** + * Class map file template + * @var string + */ + protected $_template = ''; + + /** + * Template replacements + * @var stdClass + */ + protected $_data = ''; + + + /** + * Sets template and template replacements + * + * @return void + */ + public function __construct() + { + $this->_template = trim(' +_data = new stdClass(); + $this->_data->content = ''; + $this->_data->description = trim(' + * Autoloader classmap file. Contains all available classes/interfaces and + * related class files. + * + * NOTES: + * - Don\'t edit this file manually! + * - It was generated by ' . __CLASS__ . ' + * - Use ' . __CLASS__ . ' again, if you want to regenerate this file + *'); + + $this->_data->package = __CLASS__; + $this->_data->subpackage = 'Classmap'; + $this->_data->version = '0.1'; + $this->_data->author = 'System'; + $this->_data->copyright = 'Copyright (c) 2009-2011 Murat Purc (http://www.purc.de)'; + $this->_data->license = 'http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2'; + } + + + /** + * Creates classmap file with passed data list + * + * @param array $data Assoziative list which contains class type tokens and + * the related path to the class file. + * @param string $file Destination class map file + * @return void + */ + public function create(array $data, $file) + { + $this->_createClassMap($data); + return (bool) file_put_contents($file, $this->_renderTemplate()); + } + + + /** + * Fills template replacement variable with generated assoziative PHP array + * + * @var array $data Assoziative list with class type tokens and files + * @return void + */ + protected function _createClassMap(array $data) + { + $classMapTpl = "\nreturn array(\n%s\n);\n"; + $classMapContent = ''; + foreach ($data as $classToken => $path) { + $classMapContent .= sprintf(" '%s' => '%s',\n", addslashes($classToken), addslashes($path)); + } + $classMapContent = substr($classMapContent, 0, -2); + + $this->_data->content .= sprintf($classMapTpl, $classMapContent); + } + + + /** + * Replaces all wildcards in template with related template variables. + * + * @return string Replaced template + */ + protected function _renderTemplate() + { + $template = $this->_template; + foreach ($this->_data as $name => $value) { + $template = str_replace('{' . strtoupper($name) . '}', $value, $template); + } + return $template; + } + +} diff --git a/lib/mpClassTypeFinder.php b/lib/mpClassTypeFinder.php index b17c60d..0e5e292 100644 --- a/lib/mpClassTypeFinder.php +++ b/lib/mpClassTypeFinder.php @@ -1,400 +1,400 @@ - - * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) - * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 - * @version $Id$ - */ - - -/** - * Class to find class type tokens - * - * @category Development - * @package mpAutoloaderClassMap - * @author Murat Purc - */ -class mpClassTypeFinder -{ - /** - * List of directories to ignore (note: is case insensitive) - * @var array - */ - protected $_excludeDirs = array('.svn', '.cvs'); - - /** - * List of files to ignore, regex pattern is also accepted (note: is case insensitive) - * @var array - */ - protected $_excludeFiles = array('/^~*.\.php$/', '/^~*.\.inc$/'); - - /** - * List of file extensions to parse (note: is case insensitive) - * @var array - */ - protected $_extensionsToParse = array('.php', '.inc'); - - /** - * Flag to enable debugging, all messages will be collected in property _debugMessages, - * if enabled - * @var bool - */ - protected $_enableDebug = false; - - /** - * List of debugging messages, will e filled, if debugging is active - * @var array - */ - protected $_debugMessages = array(); - - - /** - * Initializes class with passed options - * - * @param array $options Assoziative options array as follows: - * - excludeDirs: (array) List of directories to exclude, optional. - * Default values are '.svn' and '.cvs'. - * - excludeFiles: (array) List of files to exclude, optional. - * Default values are '/^~*.\.php$/' and '/^~*.\.inc$/'. - * - extensionsToParse: (array) List of file extensions to parse, optional. - * Default values are '.php' and '.inc'. - * - enableDebug: (bool) Flag to enable debugging, optional. - * Default value is false. - */ - public function __construct(array $options=array()) - { - if (isset($options['excludeDirs']) && is_array($options['excludeDirs'])) { - $this->setExcludeDirs($options['excludeDirs']); - } - if (isset($options['excludeFiles']) && is_array($options['excludeFiles'])) { - $this->setExcludeFiles($options['excludeFiles']); - } - if (isset($options['extensionsToParse']) && is_array($options['extensionsToParse'])) { - $this->setExtensionsToParse($options['extensionsToParse']); - } - if (isset($options['enableDebug']) && is_bool($options['enableDebug'])) { - $this->_enableDebug = $options['enableDebug']; - } - } - - - /** - * Sets directories to exclude - * - * @param array $excludeDirs - * @return void - */ - public function setExcludeDirs(array $excludeDirs) - { - $this->_excludeDirs = $excludeDirs; - } - - - /** - * Returns list of directories to exclude - * - * @return array - */ - public function getExcludeDirs() - { - return $this->_excludeDirs; - } - - - /** - * Sets files to exclude - * - * @param array $excludeFiles Feasible values are - * - temp.php (single file name) - * - ~*.php (with * wildcard) - * Will be replaced against regex '/^~.*\.php$/' - * @return void - */ - public function setExcludeFiles(array $excludeFiles) - { - foreach ($excludeFiles as $pos => $entry) { - if (strpos($entry, '*') !== false) { - $entry = '/^' . str_replace('*', '.*', preg_quote($entry)) . '$/'; - $excludeFiles[$pos] = $entry; - } - } - $this->_excludeFiles = $excludeFiles; - } - - - /** - * Returns list of files to exclude - * - * @return array - */ - public function getExcludeFiles() - { - return $this->_excludeFiles; - } - - - /** - * Sets file extensions to parse - * - * @param array $extensionsToParse - * @return void - */ - public function setExtensionsToParse(array $extensionsToParse) - { - $this->_extensionsToParse = $extensionsToParse; - } - - - /** - * Returns list of file extension to parse - * - * @return array - */ - public function getExtensionsToParse() - { - return $this->_extensionsToParse; - } - - - /** - * Detects all available class type tokens in found files inside passed directory. - * - * @param SplFileInfo $fileInfo - * @param bool $recursive Flag to parse directory recursive - * @return array|null Either a assoziative array where the key is the class - * type token and the value is the path or null. - */ - public function findInDir(SplFileInfo $fileInfo, $recursive=true) - { - if (!$fileInfo->isDir() || !$fileInfo->isReadable()) { - $this->_debug('findInDir: Invalid/Not readable directory ' . $fileInfo->getPathname()); - return null; - } - $this->_debug('findInDir: Processing dir ' . $fileInfo->getPathname() . ' (realpath: ' . $fileInfo->getRealPath() . ')'); - - $classTypeTokens = array(); - - $iterator = $this->_getDirIterator($fileInfo, $recursive); - - foreach ($iterator as $file) { - - if ($this->_isFileToProccess($file)) { - if ($foundTokens = $this->findInFile($file)) { - $classTypeTokens = array_merge($classTypeTokens, $foundTokens); - } - } - } - - return (count($classTypeTokens) > 0) ? $classTypeTokens : null; - } - - - /** - * Detects all available class type tokens in passed file - * - * @param SplFileInfo $fileInfo - * @return array|null Either a assoziative array where the key is the class - * type token and the value is the path or null. - */ - public function findInFile(SplFileInfo $fileInfo) - { - if (!$fileInfo->isFile() || !$fileInfo->isReadable()) { - $this->_debug('findInFile: Invalid/Not readable file ' . $fileInfo->getPathname()); - return null; - } - $this->_debug('findInFile: Processing file ' . $fileInfo->getPathname() . ' (realpath: ' . $fileInfo->getRealPath() . ')'); - - $classTypeTokens = array(); - - $tokens = token_get_all(file_get_contents($fileInfo->getRealPath())); - $prevTokenFound = false; - foreach ($tokens as $p => $token) { - if ($token[0] == T_INTERFACE) { - $this->_debug('findInFile: T_INTERFACE token found (token pos ' . $p . ')'); - $prevTokenFound = true; -# } elseif ($token[0] == T_ABSTRACT) { -# $this->_debug('findInFile: T_ABSTRACT token found (token pos ' . $p . ')'); -# $prevTokenFound = true; - } elseif ($token[0] == T_CLASS) { - $this->_debug('findInFile: T_CLASS token found (token pos ' . $p . ')'); - $prevTokenFound = true; - } - if ($prevTokenFound && $token[0] !== T_STRING) { - continue; - } elseif ($prevTokenFound && $token[0] == T_STRING) { - $classTypeTokens[$token[1]] = $this->_normalizePathSeparator($fileInfo->getRealPath()); - $prevTokenFound = false; - } - } - - return (count($classTypeTokens) > 0) ? $classTypeTokens : null; - } - - - /** - * Returns list of debug messages - * - * @return array - */ - public function getDebugMessages() - { - return $this->_debugMessages; - } - - - /** - * Returns debug messages in a formatted way. - * - * @param string $delemiter Delemiter between each message - * @param string $wrap String with %s type specifier used to wrap all - * messages - * @return string Formatted string - */ - public function getFormattedDebugMessages($delemiter="\n", $wrap='%s') - { - if (strpos($wrap, '%s') === false) { - throw new Exception('Missing type specifier %s in parameter wrap!'); - } - $messages = implode($delemiter, $this->_debugMessages); - return sprintf($wrap, $messages); - } - - - /** - * Adds passed message to debug list, if debugging is enabled - * - * @param string $msg - * @return void - */ - protected function _debug($msg) - { - if ($this->_enableDebug) { - $this->_debugMessages[] = $msg; - } - } - - - /** - * Returns directory iterator depending on $recursive parameter value - * - * @param SplFileInfo $file - * @param bool $recursive - * @return RecursiveIteratorIterator|DirectoryIterator - */ - protected function _getDirIterator(SplFileInfo $fileInfo, $recursive) - { - if ($recursive === true) { - return new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($fileInfo->getRealPath()), - RecursiveIteratorIterator::SELF_FIRST - ); - } else { - return new DirectoryIterator($fileInfo->getRealPath()); - } - } - - - /** - * Checks if file is to proccess - * - * @param SplFileInfo $file - * @return bool - */ - protected function _isFileToProccess(SplFileInfo $file) - { - if ($this->_isDirToExclude($file)) { - $this->_debug('_isFileToProccess: Dir to exclude ' . $file->getPathname() . ' (realpath: ' . $file->getRealPath() . ')'); - return false; - } - if ($this->_isFileToExclude($file)) { - $this->_debug('_isFileToProccess: File to exclude ' . $file->getPathname() . ' (realpath: ' . $file->getRealPath() . ')'); - return false; - } - if ($this->_isFileToParse($file)) { - $this->_debug('_isFileToProccess: File to parse ' . $file->getPathname() . ' (realpath: ' . $file->getRealPath() . ')'); - return true; - } - return false; - } - - - /** - * Checks if directory is to exclude - * - * @param SplFileInfo $file - * @return bool - */ - protected function _isDirToExclude(SplFileInfo $file) - { - $path = strtolower($this->_normalizePathSeparator($file->getRealPath())); - - foreach ($this->_excludeDirs as $item) { - if (strpos($path, $item) !== false) { - return true; - } - } - return false; - } - - - /** - * Checks if file is to exclude - * - * @param SplFileInfo $file - * @return bool - */ - protected function _isFileToExclude(SplFileInfo $file) - { - $path = strtolower($this->_normalizePathSeparator($file->getRealPath())); - - foreach ($this->_excludeFiles as $item) { - if (strlen($item) > 2 && substr($item, 0, 2) == '/^') { - if (preg_match($item, $path)) { - return true; - } - } else if (strpos($path, $item) !== false) { - return true; - } - } - return false; - } - - - /** - * Checks if file is to parse (if file extension matches) - * - * @param SplFileInfo $file - * @return bool - */ - protected function _isFileToParse(SplFileInfo $file) - { - $path = strtolower($this->_normalizePathSeparator($file->getRealPath())); - - foreach ($this->_extensionsToParse as $item) { - if (substr($path, -strlen($item)) == $item) { - return true; - } - } - return false; - } - - - /** - * Replaces windows style directory separator (backslash against slash) - * - * @param string - * @return string - */ - protected function _normalizePathSeparator($path) - { - if (DIRECTORY_SEPARATOR == '\\') { - $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); - } - return $path; - } - -} + + * @copyright Copyright (c) 2009-2011 Murat Purc (http://www.purc.de) + * @license http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2 + * @version $Id$ + */ + + +/** + * Class to find class type tokens + * + * @category Development + * @package mpAutoloaderClassMap + * @author Murat Purc + */ +class mpClassTypeFinder +{ + /** + * List of directories to ignore (note: is case insensitive) + * @var array + */ + protected $_excludeDirs = array('.svn', '.cvs'); + + /** + * List of files to ignore, regex pattern is also accepted (note: is case insensitive) + * @var array + */ + protected $_excludeFiles = array('/^~*.\.php$/', '/^~*.\.inc$/'); + + /** + * List of file extensions to parse (note: is case insensitive) + * @var array + */ + protected $_extensionsToParse = array('.php', '.inc'); + + /** + * Flag to enable debugging, all messages will be collected in property _debugMessages, + * if enabled + * @var bool + */ + protected $_enableDebug = false; + + /** + * List of debugging messages, will e filled, if debugging is active + * @var array + */ + protected $_debugMessages = array(); + + + /** + * Initializes class with passed options + * + * @param array $options Assoziative options array as follows: + * - excludeDirs: (array) List of directories to exclude, optional. + * Default values are '.svn' and '.cvs'. + * - excludeFiles: (array) List of files to exclude, optional. + * Default values are '/^~*.\.php$/' and '/^~*.\.inc$/'. + * - extensionsToParse: (array) List of file extensions to parse, optional. + * Default values are '.php' and '.inc'. + * - enableDebug: (bool) Flag to enable debugging, optional. + * Default value is false. + */ + public function __construct(array $options=array()) + { + if (isset($options['excludeDirs']) && is_array($options['excludeDirs'])) { + $this->setExcludeDirs($options['excludeDirs']); + } + if (isset($options['excludeFiles']) && is_array($options['excludeFiles'])) { + $this->setExcludeFiles($options['excludeFiles']); + } + if (isset($options['extensionsToParse']) && is_array($options['extensionsToParse'])) { + $this->setExtensionsToParse($options['extensionsToParse']); + } + if (isset($options['enableDebug']) && is_bool($options['enableDebug'])) { + $this->_enableDebug = $options['enableDebug']; + } + } + + + /** + * Sets directories to exclude + * + * @param array $excludeDirs + * @return void + */ + public function setExcludeDirs(array $excludeDirs) + { + $this->_excludeDirs = $excludeDirs; + } + + + /** + * Returns list of directories to exclude + * + * @return array + */ + public function getExcludeDirs() + { + return $this->_excludeDirs; + } + + + /** + * Sets files to exclude + * + * @param array $excludeFiles Feasible values are + * - temp.php (single file name) + * - ~*.php (with * wildcard) + * Will be replaced against regex '/^~.*\.php$/' + * @return void + */ + public function setExcludeFiles(array $excludeFiles) + { + foreach ($excludeFiles as $pos => $entry) { + if (strpos($entry, '*') !== false) { + $entry = '/^' . str_replace('*', '.*', preg_quote($entry)) . '$/'; + $excludeFiles[$pos] = $entry; + } + } + $this->_excludeFiles = $excludeFiles; + } + + + /** + * Returns list of files to exclude + * + * @return array + */ + public function getExcludeFiles() + { + return $this->_excludeFiles; + } + + + /** + * Sets file extensions to parse + * + * @param array $extensionsToParse + * @return void + */ + public function setExtensionsToParse(array $extensionsToParse) + { + $this->_extensionsToParse = $extensionsToParse; + } + + + /** + * Returns list of file extension to parse + * + * @return array + */ + public function getExtensionsToParse() + { + return $this->_extensionsToParse; + } + + + /** + * Detects all available class type tokens in found files inside passed directory. + * + * @param SplFileInfo $fileInfo + * @param bool $recursive Flag to parse directory recursive + * @return array|null Either a assoziative array where the key is the class + * type token and the value is the path or null. + */ + public function findInDir(SplFileInfo $fileInfo, $recursive=true) + { + if (!$fileInfo->isDir() || !$fileInfo->isReadable()) { + $this->_debug('findInDir: Invalid/Not readable directory ' . $fileInfo->getPathname()); + return null; + } + $this->_debug('findInDir: Processing dir ' . $fileInfo->getPathname() . ' (realpath: ' . $fileInfo->getRealPath() . ')'); + + $classTypeTokens = array(); + + $iterator = $this->_getDirIterator($fileInfo, $recursive); + + foreach ($iterator as $file) { + + if ($this->_isFileToProccess($file)) { + if ($foundTokens = $this->findInFile($file)) { + $classTypeTokens = array_merge($classTypeTokens, $foundTokens); + } + } + } + + return (count($classTypeTokens) > 0) ? $classTypeTokens : null; + } + + + /** + * Detects all available class type tokens in passed file + * + * @param SplFileInfo $fileInfo + * @return array|null Either a assoziative array where the key is the class + * type token and the value is the path or null. + */ + public function findInFile(SplFileInfo $fileInfo) + { + if (!$fileInfo->isFile() || !$fileInfo->isReadable()) { + $this->_debug('findInFile: Invalid/Not readable file ' . $fileInfo->getPathname()); + return null; + } + $this->_debug('findInFile: Processing file ' . $fileInfo->getPathname() . ' (realpath: ' . $fileInfo->getRealPath() . ')'); + + $classTypeTokens = array(); + + $tokens = token_get_all(file_get_contents($fileInfo->getRealPath())); + $prevTokenFound = false; + foreach ($tokens as $p => $token) { + if ($token[0] == T_INTERFACE) { + $this->_debug('findInFile: T_INTERFACE token found (token pos ' . $p . ')'); + $prevTokenFound = true; +# } elseif ($token[0] == T_ABSTRACT) { +# $this->_debug('findInFile: T_ABSTRACT token found (token pos ' . $p . ')'); +# $prevTokenFound = true; + } elseif ($token[0] == T_CLASS) { + $this->_debug('findInFile: T_CLASS token found (token pos ' . $p . ')'); + $prevTokenFound = true; + } + if ($prevTokenFound && $token[0] !== T_STRING) { + continue; + } elseif ($prevTokenFound && $token[0] == T_STRING) { + $classTypeTokens[$token[1]] = $this->_normalizePathSeparator($fileInfo->getRealPath()); + $prevTokenFound = false; + } + } + + return (count($classTypeTokens) > 0) ? $classTypeTokens : null; + } + + + /** + * Returns list of debug messages + * + * @return array + */ + public function getDebugMessages() + { + return $this->_debugMessages; + } + + + /** + * Returns debug messages in a formatted way. + * + * @param string $delemiter Delemiter between each message + * @param string $wrap String with %s type specifier used to wrap all + * messages + * @return string Formatted string + */ + public function getFormattedDebugMessages($delemiter="\n", $wrap='%s') + { + if (strpos($wrap, '%s') === false) { + throw new Exception('Missing type specifier %s in parameter wrap!'); + } + $messages = implode($delemiter, $this->_debugMessages); + return sprintf($wrap, $messages); + } + + + /** + * Adds passed message to debug list, if debugging is enabled + * + * @param string $msg + * @return void + */ + protected function _debug($msg) + { + if ($this->_enableDebug) { + $this->_debugMessages[] = $msg; + } + } + + + /** + * Returns directory iterator depending on $recursive parameter value + * + * @param SplFileInfo $file + * @param bool $recursive + * @return RecursiveIteratorIterator|DirectoryIterator + */ + protected function _getDirIterator(SplFileInfo $fileInfo, $recursive) + { + if ($recursive === true) { + return new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($fileInfo->getRealPath()), + RecursiveIteratorIterator::SELF_FIRST + ); + } else { + return new DirectoryIterator($fileInfo->getRealPath()); + } + } + + + /** + * Checks if file is to proccess + * + * @param SplFileInfo $file + * @return bool + */ + protected function _isFileToProccess(SplFileInfo $file) + { + if ($this->_isDirToExclude($file)) { + $this->_debug('_isFileToProccess: Dir to exclude ' . $file->getPathname() . ' (realpath: ' . $file->getRealPath() . ')'); + return false; + } + if ($this->_isFileToExclude($file)) { + $this->_debug('_isFileToProccess: File to exclude ' . $file->getPathname() . ' (realpath: ' . $file->getRealPath() . ')'); + return false; + } + if ($this->_isFileToParse($file)) { + $this->_debug('_isFileToProccess: File to parse ' . $file->getPathname() . ' (realpath: ' . $file->getRealPath() . ')'); + return true; + } + return false; + } + + + /** + * Checks if directory is to exclude + * + * @param SplFileInfo $file + * @return bool + */ + protected function _isDirToExclude(SplFileInfo $file) + { + $path = strtolower($this->_normalizePathSeparator($file->getRealPath())); + + foreach ($this->_excludeDirs as $item) { + if (strpos($path, $item) !== false) { + return true; + } + } + return false; + } + + + /** + * Checks if file is to exclude + * + * @param SplFileInfo $file + * @return bool + */ + protected function _isFileToExclude(SplFileInfo $file) + { + $path = strtolower($this->_normalizePathSeparator($file->getRealPath())); + + foreach ($this->_excludeFiles as $item) { + if (strlen($item) > 2 && substr($item, 0, 2) == '/^') { + if (preg_match($item, $path)) { + return true; + } + } else if (strpos($path, $item) !== false) { + return true; + } + } + return false; + } + + + /** + * Checks if file is to parse (if file extension matches) + * + * @param SplFileInfo $file + * @return bool + */ + protected function _isFileToParse(SplFileInfo $file) + { + $path = strtolower($this->_normalizePathSeparator($file->getRealPath())); + + foreach ($this->_extensionsToParse as $item) { + if (substr($path, -strlen($item)) == $item) { + return true; + } + } + return false; + } + + + /** + * Replaces windows style directory separator (backslash against slash) + * + * @param string + * @return string + */ + protected function _normalizePathSeparator($path) + { + if (DIRECTORY_SEPARATOR == '\\') { + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + } + return $path; + } + +} diff --git a/readme.txt b/readme.txt index 67521bd..ceb3c48 100644 --- a/readme.txt +++ b/readme.txt @@ -54,7 +54,7 @@ return array( ); // usage: -// a.) first you have to register a autoloader which loads required classes by +// a.) first you have to register a autoloader which loads required classes by // using the class map array structure. // b.) then you can use something like $foo = new Com_Foobar_Helloworld(); @@ -192,7 +192,7 @@ class myAutoloader /** * Autoloader implementation * @param string $name The required class name - * @throws Exception if autoloader couldn't set class map configuration in initial call + * @throws Exception if autoloader couldn't set class map configuration in initial call */ public static function autoload($name) {