Trash /src/Loader/ClassLoader.php

Language PHP Lines 110
MD5 Hash 65c89e6b08c6779e710ed7109119b477
Repository https://github.com/Kakwen/Trash.git View Raw File
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
<?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();
    }

}
Back to Top