You've already forked qlg.tsgz.moe
							
							
		
			
				
	
	
		
			307 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
<?php
 | 
						|
class LtAutoloader
 | 
						|
{
 | 
						|
	public $conf = array(
 | 
						|
	/**
 | 
						|
	 * 是否自动加载定义了函数的文件
 | 
						|
	 *
 | 
						|
	 * 可选项: 
 | 
						|
	 * # true   自动加载 
 | 
						|
	 * # false  跳过函数,只自动加载定义了class或者interface的文件
 | 
						|
	 */
 | 
						|
		"load_function" => true,
 | 
						|
 | 
						|
	/**
 | 
						|
	 * 要扫描的文件类型
 | 
						|
	 *
 | 
						|
	 * 若该属性设置为array("php","inc","php3"), 
 | 
						|
	 * 则扩展名为"php","inc","php3"的文件会被扫描, 
 | 
						|
	 * 其它扩展名的文件会被忽略
 | 
						|
	 */
 | 
						|
		"allow_file_extension" => array("php", "inc"),
 | 
						|
 | 
						|
	/**
 | 
						|
	 * 不扫描的目录
 | 
						|
	 *
 | 
						|
	 * 若该属性设置为array(".svn", ".setting"), 
 | 
						|
	 * 则所有名为".setting"的目录也会被忽略
 | 
						|
	 */
 | 
						|
		"skip_dir_names" => array(".svn"),
 | 
						|
	);
 | 
						|
 | 
						|
	public $storeHandle;
 | 
						|
	public $autoloadPath;
 | 
						|
	protected $functionFileMapping;
 | 
						|
	protected $fileStore;
 | 
						|
 | 
						|
	public function init()
 | 
						|
	{
 | 
						|
		if (!is_object($this->storeHandle))
 | 
						|
		{
 | 
						|
			$this->storeHandle = new LtStoreMemory;
 | 
						|
			$this->fileStore = new LtStoreFile;
 | 
						|
			$this->fileStore->prefix = 'LtAutoloader-token-cache';
 | 
						|
			$this->fileStore->useSerialize = true;
 | 
						|
			$this->fileStore->init();
 | 
						|
		}
 | 
						|
		// Whether scanning directory
 | 
						|
		if (0 == $this->storeHandle->get(".class_total") && 0 == $this->storeHandle->get(".function_total"))
 | 
						|
		{
 | 
						|
			$this->storeHandle->add(".class_total", 0);
 | 
						|
			$this->storeHandle->add(".function_total", 0);
 | 
						|
			$this->storeHandle->add(".functions", array(), 0);
 | 
						|
			$autoloadPath = $this->preparePath($this->autoloadPath);
 | 
						|
			foreach($autoloadPath as $key => $path)
 | 
						|
			{
 | 
						|
				if (is_file($path))
 | 
						|
				{
 | 
						|
					$this->addFileMap($path);
 | 
						|
					unset($autoloadPath[$key]);
 | 
						|
				}
 | 
						|
			}
 | 
						|
			$this->scanDirs($autoloadPath);
 | 
						|
			unset($autoloadPath);
 | 
						|
		}
 | 
						|
		// Whether loading function files
 | 
						|
		if ($this->conf["load_function"])
 | 
						|
		{
 | 
						|
			$this->loadFunction();
 | 
						|
		}
 | 
						|
		spl_autoload_register(array($this, "loadClass"));
 | 
						|
	}
 | 
						|
 | 
						|
	public function loadFunction()
 | 
						|
	{
 | 
						|
		if ($functionFiles = $this->storeHandle->get(".functions"))
 | 
						|
		{
 | 
						|
			foreach ($functionFiles as $functionFile)
 | 
						|
			{
 | 
						|
				include($functionFile);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	public function loadClass($className)
 | 
						|
	{
 | 
						|
		if ($classFile = $this->storeHandle->get(strtolower($className)))
 | 
						|
		{
 | 
						|
			include($classFile);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	protected function convertPath($path)
 | 
						|
	{
 | 
						|
		$path = str_replace("\\", "/", $path);
 | 
						|
		if (!is_readable($path))
 | 
						|
		{
 | 
						|
			trigger_error("Directory is not exists/readable: {$path}");
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		$path = rtrim(realpath($path), '\\/');
 | 
						|
		if ("WINNT" != PHP_OS && preg_match("/\s/i", $path))
 | 
						|
		{
 | 
						|
			trigger_error("Directory contains space/tab/newline is not supported: {$path}");
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		return $path;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * The string or an Multidimensional array into a one-dimensional array
 | 
						|
	 *
 | 
						|
	 * @param array $ or string $var
 | 
						|
	 * @return array one-dimensional array
 | 
						|
	 */
 | 
						|
	protected function preparePath($var)
 | 
						|
	{
 | 
						|
		$ret = array();
 | 
						|
		if (!is_array($var))
 | 
						|
		{
 | 
						|
			$var = array($var);
 | 
						|
		}
 | 
						|
		$i = 0;
 | 
						|
		while (isset($var[$i]))
 | 
						|
		{
 | 
						|
			if (!is_array($var[$i]) && $path = $this->convertPath($var[$i]))
 | 
						|
			{
 | 
						|
				$ret[] = $path;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				foreach($var[$i] as $v)
 | 
						|
				{
 | 
						|
					$var[] = $v;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			unset($var[$i]);
 | 
						|
			$i ++;
 | 
						|
		}
 | 
						|
		return $ret;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Using iterative algorithm scanning subdirectories
 | 
						|
	 * save autoloader filemap
 | 
						|
	 *
 | 
						|
	 * @param array $dirs one-dimensional
 | 
						|
	 * @return
 | 
						|
	 */
 | 
						|
	protected function scanDirs($dirs)
 | 
						|
	{
 | 
						|
		$i = 0;
 | 
						|
		while (isset($dirs[$i]))
 | 
						|
		{
 | 
						|
			$dir = $dirs[$i];
 | 
						|
			$files = scandir($dir);
 | 
						|
			foreach ($files as $file)
 | 
						|
			{
 | 
						|
				if (in_array($file, array(".", "..")) || in_array($file, $this->conf["skip_dir_names"]))
 | 
						|
				{
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				$currentFile = $dir . DIRECTORY_SEPARATOR . $file;
 | 
						|
				if (is_file($currentFile))
 | 
						|
				{
 | 
						|
					$this->addFileMap($currentFile);
 | 
						|
				}
 | 
						|
				else if (is_dir($currentFile))
 | 
						|
				{
 | 
						|
					// if $currentFile is a directory, pass through the next loop.
 | 
						|
					$dirs[] = $currentFile;
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					trigger_error("$currentFile is not a file or a directory.");
 | 
						|
				}
 | 
						|
			} //end foreach
 | 
						|
			unset($dirs[$i]);
 | 
						|
			$i ++;
 | 
						|
		} //end while
 | 
						|
	}
 | 
						|
 | 
						|
	protected function parseLibNames($src)
 | 
						|
	{
 | 
						|
		$libNames = array();
 | 
						|
		$tokens = token_get_all($src);
 | 
						|
		$level = 0;
 | 
						|
		$found = false;
 | 
						|
		$name = '';
 | 
						|
		foreach ($tokens as $token)
 | 
						|
		{
 | 
						|
			if (is_string($token))
 | 
						|
			{
 | 
						|
				if ('{' == $token)
 | 
						|
				{
 | 
						|
					$level ++;
 | 
						|
				}
 | 
						|
				else if ('}' == $token)
 | 
						|
				{
 | 
						|
					$level --;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				list($id, $text) = $token;
 | 
						|
				if (T_CURLY_OPEN == $id || T_DOLLAR_OPEN_CURLY_BRACES == $id)
 | 
						|
				{
 | 
						|
					$level ++;
 | 
						|
				}
 | 
						|
				if (0 < $level)
 | 
						|
				{
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				switch ($id)
 | 
						|
				{
 | 
						|
					case T_STRING:
 | 
						|
						if ($found)
 | 
						|
						{
 | 
						|
							$libNames[strtolower($name)][] = $text;
 | 
						|
							$found = false;
 | 
						|
						}
 | 
						|
						break;
 | 
						|
					case T_CLASS:
 | 
						|
					case T_INTERFACE:
 | 
						|
					case T_FUNCTION:
 | 
						|
						$found = true;
 | 
						|
						$name = $text;
 | 
						|
						break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return $libNames;
 | 
						|
	}
 | 
						|
 | 
						|
	protected function addClass($className, $file)
 | 
						|
	{
 | 
						|
		$key = strtolower($className);
 | 
						|
		if ($existedClassFile = $this->storeHandle->get($key))
 | 
						|
		{
 | 
						|
			trigger_error("duplicate class [$className] found in:\n$existedClassFile\n$file\n");
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			$this->storeHandle->add($key, $file);
 | 
						|
			$this->storeHandle->update(".class_total", $this->storeHandle->get(".class_total") + 1);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	protected function addFunction($functionName, $file)
 | 
						|
	{
 | 
						|
		$functionName = strtolower($functionName);
 | 
						|
		if (isset($this->functionFileMapping[$functionName]))
 | 
						|
		{
 | 
						|
			$existedFunctionFile = $this->functionFileMapping[$functionName];
 | 
						|
			trigger_error("duplicate function [$functionName] found in:\n$existedFunctionFile\n$file\n");
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			$this->functionFileMapping[$functionName] = $file;
 | 
						|
			$this->storeHandle->update(".functions", array_unique(array_values($this->functionFileMapping)));
 | 
						|
			$this->storeHandle->update(".function_total", count($this->functionFileMapping));
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	protected function addFileMap($file)
 | 
						|
	{
 | 
						|
		if (!in_array(pathinfo($file, PATHINFO_EXTENSION), $this->conf["allow_file_extension"]))
 | 
						|
		{
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		$libNames = array();
 | 
						|
		if ($this->fileStore instanceof LtStore)
 | 
						|
		{
 | 
						|
			$cachedFileLastModified = (int) @filemtime($this->fileStore->getFilePath($file));
 | 
						|
			if ($cachedFileLastModified < filemtime($file) || !is_array(($libNames = $this->fileStore->get($file))))
 | 
						|
			{
 | 
						|
				$libNames = $this->parseLibNames(trim(file_get_contents($file)));
 | 
						|
				if (0 < $cachedFileLastModified)
 | 
						|
				{
 | 
						|
					$this->fileStore->update($file, $libNames);
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					$this->fileStore->add($file, $libNames);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			$libNames = $this->parseLibNames(trim(file_get_contents($file)));
 | 
						|
		}
 | 
						|
 | 
						|
		foreach ($libNames as $libType => $libArray)
 | 
						|
		{
 | 
						|
			$method = "function" == $libType ? "addFunction" : "addClass";
 | 
						|
			foreach ($libArray as $libName)
 | 
						|
			{
 | 
						|
				$this->$method($libName, $file);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
}
 |