* @author Tanel Suurhans * @author Elan Ruusamäe * * @package autoload */ class PHP_Autoload { private static $excludes = array('.', '..', '.svn', 'CVS', 'data', 'cake', 'propel', 'phing', 'geshi', 'adodb'); private static $classes; private static $scandirs = array(); /** * array of directories already scanned */ private static $dirs = array(); public static function autoload($className) { if (class_exists($className, false) || interface_exists($className, false)) { return true; } // Zend framework -- we can optimize if (strpos($className, 'Zend') === 0){ require_once str_replace('_', '/', $className) . '.php'; return true; } // Smarty if ($className === 'Smarty') { require_once 'Smarty/Smarty.class.php'; return true; } if (!is_array(self::$classes)) { self::$classes = array(); // scan frameworks dir foreach (explode(PATH_SEPARATOR, get_include_path()) as $path) { if ($path == '.') { continue; } if ($path == PEAR_INSTALL_DIR) { self::scan($path, true); } else { self::scan($path); } } // scan additional project dirs if (!empty(self::$scandirs)) { foreach (self::$scandirs as $path) { self::scan($path); } } } // the rest if (array_key_exists($className, self::$classes)) { require_once self::$classes[$className]; return true; } } /** * Return scanned class => path mappings */ public static function get_classmap() { return self::$classes; } /** * Add project path to scan for additional classes. */ public static function add_path($dir) { self::$scandirs = array_merge(self::$scandirs, array($dir)); } private static function scan($path, $pear = false, $subdir = null) { $scandir = $subdir ? $path . DIRECTORY_SEPARATOR . $subdir : $path; if (array_key_exists($scandir, self::$dirs)) { return; } self::$dirs[$scandir] = true; $dh = opendir($scandir); while (($file = readdir($dh)) !== false) { // omit exclusions if (array_search($file, self::$excludes) !== false) { continue; } // exclude hidden paths if ($file[0] == '.') { continue; } // recurse if (is_dir($scandir. DIRECTORY_SEPARATOR . $file)) { self::scan($path, $pear, $subdir ? $subdir . DIRECTORY_SEPARATOR . $file : $file); continue; } // skip without .php extension if (substr($file, -4) != '.php') { continue; } $class = substr($file, 0, -4); // rewrite class.CLASSNAME.php if (substr($class, 0, 6) === 'class.') { $class = substr($class, 6); } if (strchr($class, '.') !== false || strchr($class, '-') !== false) { // TODO: class name can't contain those chars either: .!@#$%^&*+=-[](){} continue; } if ($pear && $subdir) { $pearclass = str_replace('/', '_', $subdir . DIRECTORY_SEPARATOR . $class); self::$classes[$pearclass] = $scandir . DIRECTORY_SEPARATOR . $file; } else { self::$classes[$class] = $scandir . DIRECTORY_SEPARATOR . $file; // XXX: Eventum $parts = array(); foreach (split('_', $class) as $part) { $parts[] = ucfirst($part); } $class = join('_', $parts); self::$classes[$class] = $scandir . DIRECTORY_SEPARATOR . $file; // XXX: Eventum: SCM class self::$classes[strtoupper($class)] = $f = $scandir . DIRECTORY_SEPARATOR . $file; } } closedir($dh); } } spl_autoload_register(array('PHP_Autoload', 'autoload'));