PageRenderTime 51ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Loader/ClassLoader.php

https://github.com/Kakwen/Trash
PHP | 109 lines | 71 code | 16 blank | 22 comment | 2 complexity | 65c89e6b08c6779e710ed7109119b477 MD5 | raw file
  1. <?php
  2. /**
  3. * @author
  4. * @version
  5. * @project
  6. * @since
  7. */
  8. namespace Trash\Loader;
  9. use Trash\Core\Singleton;
  10. class ClassLoader extends Singleton{
  11. const FILE_EXTENSION = '.php';
  12. const DIR_HIERARCHY_LEVEL = 3;
  13. private static $vendorMapping = array( //TODO pq? de static si singleton
  14. 'Trash' => 'Trash/src', //TODO
  15. 'TrashTest' => 'Trash/test/src',
  16. );
  17. private static $excludedFunctionNames = array( //TODO pq? de static si singleton
  18. 'class_exists',
  19. 'is_subclass_of',
  20. );
  21. /**
  22. * @return ClassLoader
  23. */
  24. public static function getInstance(){
  25. return parent::getInstance();
  26. }
  27. public function register(array $vendorMapping=array()){
  28. self::$vendorMapping += $vendorMapping;
  29. return spl_autoload_register(array(self::getInstance(), 'includeClassFile'));
  30. }
  31. public function unRegister(){
  32. return spl_autoload_unregister(array(self::getInstance(), 'includeClassFile'));
  33. }
  34. public function addVendor($vendorName, $vendorPath){
  35. self::$vendorMapping[(string) $vendorName] = (string) $vendorPath;
  36. }
  37. public function includeClassFile($className){
  38. $filePath = $this->getFilePath((string) $className);
  39. if(file_exists($filePath)){
  40. //clearstatcache(null, $filePath); //TODO: voir les perf!
  41. return require_once($filePath);
  42. }elseif($this->hasToDisplayError()){
  43. throw new LoaderException($className.' not found in "'.$filePath.'". Called by '.print_r($this->getBackTraceData(), true)); //TODO
  44. }
  45. return false;
  46. }
  47. public function getFilePath($className){
  48. // tester:
  49. // ClassName
  50. // Vendor\ClassName
  51. // Vendor\VendorClassName
  52. // Vendor_ClassName
  53. // Vendor_VendorClassName
  54. return realpath($this->getRootDir().$this->parseFilePath($this->resolveVendor($className)).self::FILE_EXTENSION);
  55. }
  56. 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
  57. return str_pad(__DIR__.DIRECTORY_SEPARATOR, self::DIR_HIERARCHY_LEVEL, '..'.DIRECTORY_SEPARATOR, STR_PAD_RIGHT);//TODO voir si strpad c'est pas mieux!!
  58. // $result = __DIR__.DIRECTORY_SEPARATOR;
  59. // for($i=0; $i<$level; ++$i){
  60. // $result .= '..'.DIRECTORY_SEPARATOR;
  61. // }
  62. // return $result;
  63. }
  64. private function resolveVendor($className){
  65. //todo bug: strtr($className, self::$vendorMapping) si Vendor\VendorClassName, car on remplace toutes les occurences...
  66. return strtr($className, self::$vendorMapping);
  67. }
  68. private function parseFilePath($filePath){
  69. if(strpos($filePath, '_')!==false){
  70. return strtr($filePath, '_', DIRECTORY_SEPARATOR);
  71. }else{
  72. return strtr($filePath, '\\', DIRECTORY_SEPARATOR);
  73. }
  74. }
  75. private function hasToDisplayError(){
  76. $backtraceData = $this->getBackTraceData();
  77. 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.
  78. }
  79. private static function getBackTraceData(){
  80. foreach(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $i => $backtrace){
  81. if(isset($backtrace['function']) && $backtrace['function']==='spl_autoload_call'){ //on est au niveau de l'appel de l'autoload.
  82. if(isset($backtraces[$i+1])){
  83. return $backtraces[$i+1]; //l'index suivant nous renseigne sur le context de la fonction qui a appelж l'autoload.
  84. }
  85. break;
  86. }
  87. }
  88. return array();
  89. }
  90. }