* @package generis */ class common_legacy_LegacyAutoLoader { private static $singleton = null; /** * * @return common_legacy_LegacyAutoLoader */ private static function singleton() { if (self::$singleton == null) { self::$singleton = new self(); } return self::$singleton; } /** @var string[] */ private $legacyPrefixes = []; /** @var string */ private $generisPath; /** @var string */ private $rootPath; /** * protect the cunstructer, singleton pattern */ private function __construct() { $this->generisPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR; $this->rootPath = $this->generisPath . '..' . DIRECTORY_SEPARATOR; } /** * Register this instance of ClassLoader as a php autoloader * * @access public * @author Joel Bout */ public static function register() { // init the autloader for generis spl_autoload_register([self::singleton(), 'autoload']); } /** * add support for legacy prefix */ public static function supportLegacyPrefix($prefix, $namespace) { self::singleton()->legacyPrefixes[$prefix] = $namespace; } /** * Attempt to autload classes in tao * * @access public * @author Joel Bout * @param string pClassName * @return void */ public function autoload($pClassName): void { if (strpos($pClassName, '_') === false) { return; } $tokens = explode("_", $pClassName); $size = count($tokens); $path = ''; for ($i = 0; $i < $size - 1; $i++) { $path .= $tokens[$i] . '/'; } // Search for class.X.php $filePath = '/' . $path . 'class.' . $tokens[$size - 1] . '.php'; if (file_exists($this->generisPath . $filePath)) { require_once $this->generisPath . $filePath; return; } // Search for interface.X.php $filePathInterface = '/' . $path . 'interface.' . $tokens[$size - 1] . '.php'; if (file_exists($this->generisPath . $filePathInterface)) { require_once $this->generisPath . $filePathInterface; return; } // Search for trait.X.php $filePathTrait = '/' . $path . 'trait.' . $tokens[$size - 1] . '.php'; if (file_exists($this->generisPath . $filePathTrait)) { require_once $this->generisPath . $filePathTrait; return; } if (file_exists($this->rootPath . $filePath)) { require_once $this->rootPath . $filePath; return; } if (file_exists($this->rootPath . $filePathInterface)) { require_once $this->rootPath . $filePathInterface; return; } foreach ($this->legacyPrefixes as $key => $namespace) { if (substr($pClassName, 0, strlen($key)) == $key) { $newClass = $namespace . strtr(substr($pClassName, strlen($key)), '_', '\\'); $this->wrapClass($pClassName, $newClass); return; } } $this->loadFromRootExtension($tokens); } private function loadFromRootExtension(array $classNameTokens): void { $manifestPath = $this->rootPath . 'manifest.php'; if (!file_exists($manifestPath)) { return; } $manifest = new Manifest($manifestPath); if ($manifest->getName() !== reset($classNameTokens)) { return; } $path = implode(DIRECTORY_SEPARATOR, array_slice($classNameTokens, 1, -1)) . DIRECTORY_SEPARATOR; $classFilePath = $this->rootPath . $path . 'class.' . end($classNameTokens) . '.php'; if (file_exists($classFilePath)) { require_once $classFilePath; return; } $interfaceFilePath = $this->rootPath . $path . 'interface.' . end($classNameTokens) . '.php'; if (file_exists($interfaceFilePath)) { require_once $interfaceFilePath; } } private function wrapClass($legacyClass, $realClass) { common_Logger::w('Legacy classname "' . $legacyClass . '" referenced, please use "' . $realClass . '" instead'); if (preg_match('/[^A-Za-z0-9_\\\\]/', $legacyClass) || preg_match('/[^A-Za-z0-9_\\\\]/', $realClass)) { throw new Exception('Unknown characters in class name'); } $classDefinition = 'class ' . $legacyClass . ' extends ' . $realClass . ' {}'; eval($classDefinition); } } common_legacy_LegacyAutoLoader::register();