ClassLoader.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Autoload;
  12. /**
  13. * ClassLoader implements an PSR-0 class loader
  14. *
  15. * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
  16. *
  17. * $loader = new ComposerClassLoader();
  18. *
  19. * // register classes with namespaces
  20. * $loader->add('Symfony\Component' => __DIR__.'/component');
  21. * $loader->add('Symfony' => __DIR__.'/framework');
  22. *
  23. * // activate the autoloader
  24. * $loader->register();
  25. *
  26. * In this example, if you try to use a class in the Symfony\Component
  27. * namespace or one of its children (Symfony\Component\Console for instance),
  28. * the autoloader will first look for the class under the component/
  29. * directory, and it will then fallback to the framework/ directory if not
  30. * found before giving up.
  31. *
  32. * This class is loosely based on the Symfony UniversalClassLoader.
  33. *
  34. * @author Fabien Potencier <fabien@symfony.com>
  35. * @author Jordi Boggiano <j.boggiano@seld.be>
  36. */
  37. class ClassLoader
  38. {
  39. private $prefixes = array();
  40. private $fallbackDirs = array();
  41. public function getPrefixes()
  42. {
  43. return $this->prefixes;
  44. }
  45. public function getFallbackDirs()
  46. {
  47. return $this->fallbackDirs;
  48. }
  49. /**
  50. * Registers a set of classes
  51. *
  52. * @param string $prefix The classes prefix
  53. * @param array|string $paths The location(s) of the classes
  54. */
  55. public function add($prefix, $paths)
  56. {
  57. if (!$prefix) {
  58. $this->fallbackDirs = (array) $paths;
  59. return;
  60. }
  61. if (isset($this->prefixes[$prefix])) {
  62. $this->prefixes[$prefix] = array_merge(
  63. $this->prefixes[$prefix],
  64. (array) $paths
  65. );
  66. } else {
  67. $this->prefixes[$prefix] = (array) $paths;
  68. }
  69. }
  70. /**
  71. * Registers this instance as an autoloader.
  72. *
  73. * @param Boolean $prepend Whether to prepend the autoloader or not
  74. */
  75. public function register($prepend = false)
  76. {
  77. spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  78. }
  79. /**
  80. * Loads the given class or interface.
  81. *
  82. * @param string $class The name of the class
  83. * @return Boolean|null True, if loaded
  84. */
  85. public function loadClass($class)
  86. {
  87. if ($file = $this->findFile($class)) {
  88. require $file;
  89. return true;
  90. }
  91. }
  92. /**
  93. * Finds the path to the file where the class is defined.
  94. *
  95. * @param string $class The name of the class
  96. *
  97. * @return string|null The path, if found
  98. */
  99. public function findFile($class)
  100. {
  101. if ('\\' == $class[0]) {
  102. $class = substr($class, 1);
  103. }
  104. if (false !== $pos = strrpos($class, '\\')) {
  105. // namespaced class name
  106. $classPath = DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos));
  107. $className = substr($class, $pos + 1);
  108. } else {
  109. // PEAR-like class name
  110. $classPath = null;
  111. $className = $class;
  112. }
  113. $classPath .= DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
  114. foreach ($this->prefixes as $prefix => $dirs) {
  115. foreach ($dirs as $dir) {
  116. if (0 === strpos($class, $prefix)) {
  117. if (file_exists($dir . $classPath)) {
  118. return $dir . $classPath;
  119. }
  120. }
  121. }
  122. }
  123. foreach ($this->fallbackDirs as $dir) {
  124. if (file_exists($dir . $classPath)) {
  125. return $dir . $classPath;
  126. }
  127. }
  128. }
  129. }