/src/Loader/ClassLoader.php
PHP | 109 lines | 71 code | 16 blank | 22 comment | 2 complexity | 65c89e6b08c6779e710ed7109119b477 MD5 | raw file
- <?php
- /**
- * @author
- * @version
- * @project
- * @since
- */
- namespace Trash\Loader;
- use Trash\Core\Singleton;
- class ClassLoader extends Singleton{
- const FILE_EXTENSION = '.php';
- const DIR_HIERARCHY_LEVEL = 3;
- private static $vendorMapping = array( //TODO pq? de static si singleton
- 'Trash' => 'Trash/src', //TODO
- 'TrashTest' => 'Trash/test/src',
- );
- private static $excludedFunctionNames = array( //TODO pq? de static si singleton
- 'class_exists',
- 'is_subclass_of',
- );
- /**
- * @return ClassLoader
- */
- public static function getInstance(){
- return parent::getInstance();
- }
- public function register(array $vendorMapping=array()){
- self::$vendorMapping += $vendorMapping;
- return spl_autoload_register(array(self::getInstance(), 'includeClassFile'));
- }
- public function unRegister(){
- return spl_autoload_unregister(array(self::getInstance(), 'includeClassFile'));
- }
- public function addVendor($vendorName, $vendorPath){
- self::$vendorMapping[(string) $vendorName] = (string) $vendorPath;
- }
- public function includeClassFile($className){
- $filePath = $this->getFilePath((string) $className);
- if(file_exists($filePath)){
- //clearstatcache(null, $filePath); //TODO: voir les perf!
- return require_once($filePath);
- }elseif($this->hasToDisplayError()){
- throw new LoaderException($className.' not found in "'.$filePath.'". Called by '.print_r($this->getBackTraceData(), true)); //TODO
- }
- return false;
- }
- public function getFilePath($className){
- // tester:
- // ClassName
- // Vendor\ClassName
- // Vendor\VendorClassName
- // Vendor_ClassName
- // Vendor_VendorClassName
- return realpath($this->getRootDir().$this->parseFilePath($this->resolveVendor($className)).self::FILE_EXTENSION);
- }
- private function getRootDir(){ //TODO devrait Жtre dans une classe mУre... en static? mais comment gжrer уa avec le singleton? est-ce que singleton ne devrait pas Жtre un trait? oui!!! :-D
- return str_pad(__DIR__.DIRECTORY_SEPARATOR, self::DIR_HIERARCHY_LEVEL, '..'.DIRECTORY_SEPARATOR, STR_PAD_RIGHT);//TODO voir si strpad c'est pas mieux!!
- // $result = __DIR__.DIRECTORY_SEPARATOR;
- // for($i=0; $i<$level; ++$i){
- // $result .= '..'.DIRECTORY_SEPARATOR;
- // }
- // return $result;
- }
- private function resolveVendor($className){
- //todo bug: strtr($className, self::$vendorMapping) si Vendor\VendorClassName, car on remplace toutes les occurences...
- return strtr($className, self::$vendorMapping);
- }
- private function parseFilePath($filePath){
- if(strpos($filePath, '_')!==false){
- return strtr($filePath, '_', DIRECTORY_SEPARATOR);
- }else{
- return strtr($filePath, '\\', DIRECTORY_SEPARATOR);
- }
- }
- private function hasToDisplayError(){
- $backtraceData = $this->getBackTraceData();
- return !(isset($backtraceData['function']) && in_array($backtraceData['function'], self::$excludedFunctionNames, true)); //si la mжthode qui a appelж l'autoload est class_exists, c'est qu'on a testДж si la classe existait => donc on ne doit surtout pas retourner d'erreur.
- }
- private static function getBackTraceData(){
- foreach(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $i => $backtrace){
- if(isset($backtrace['function']) && $backtrace['function']==='spl_autoload_call'){ //on est au niveau de l'appel de l'autoload.
- if(isset($backtraces[$i+1])){
- return $backtraces[$i+1]; //l'index suivant nous renseigne sur le context de la fonction qui a appelж l'autoload.
- }
- break;
- }
- }
- return array();
- }
- }