ClassLoader.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <?php
  2. namespace ClassPreloader;
  3. require_once __DIR__ . '/ClassNode.php';
  4. require_once __DIR__ . '/ClassList.php';
  5. /**
  6. * Creates an autoloader that intercepts and keeps track of each include in
  7. * order that files must be included. This autoloader proxies to all other
  8. * underlying autoloaders.
  9. */
  10. class ClassLoader
  11. {
  12. /**
  13. * @var ClassList List of loaded classes
  14. */
  15. public $classList;
  16. /**
  17. * Create the dependency list
  18. */
  19. public function __construct()
  20. {
  21. $this->classList = new ClassList();
  22. }
  23. /**
  24. * Wrap a block of code in the autoloader and get a list of loaded classes
  25. *
  26. * @param \Callable $func Callable function
  27. *
  28. * @return Config
  29. */
  30. public static function getIncludes($func)
  31. {
  32. $loader = new self();
  33. call_user_func($func, $loader);
  34. $loader->unregister();
  35. $config = new Config();
  36. foreach ($loader->getFilenames() as $file) {
  37. $config->addFile($file);
  38. }
  39. return $config;
  40. }
  41. /**
  42. * Registers this instance as an autoloader.
  43. *
  44. * @param bool $prepend Whether to prepend the autoloader or not
  45. */
  46. public function register()
  47. {
  48. spl_autoload_register(array($this, 'loadClass'), true, true);
  49. }
  50. /**
  51. * Unregisters this instance as an autoloader.
  52. */
  53. public function unregister()
  54. {
  55. spl_autoload_unregister(array($this, 'loadClass'));
  56. }
  57. /**
  58. * Loads the given class or interface.
  59. *
  60. * @param string $class The name of the class
  61. * @return bool|null True, if loaded
  62. */
  63. public function loadClass($class)
  64. {
  65. foreach (spl_autoload_functions() as $func) {
  66. if (is_array($func) && $func[0] === $this) {
  67. continue;
  68. }
  69. $this->classList->push($class);
  70. if (call_user_func($func, $class)) {
  71. break;
  72. }
  73. }
  74. $this->classList->next();
  75. return true;
  76. }
  77. /**
  78. * Get an array of loaded file names in order of loading
  79. *
  80. * @return array
  81. */
  82. public function getFilenames()
  83. {
  84. $files = array();
  85. foreach ($this->classList->getClasses() as $class) {
  86. // Push interfaces before classes if not already loaded
  87. $r = new \ReflectionClass($class);
  88. foreach ($r->getInterfaces() as $inf) {
  89. $name = $inf->getFileName();
  90. if ($name && !in_array($name, $files)) {
  91. $files[] = $name;
  92. }
  93. }
  94. $files[] = $r->getFileName();
  95. }
  96. return $files;
  97. }
  98. }