fork download
  1. <?php
  2.  
  3. /**
  4.  * A general-purpose implementation that includes the optional functionality
  5.  * of allowing multiple base directories for a single namespace prefix.
  6.  */
  7. class Psr4Autoloader
  8. {
  9. const EXTENSION = '.php';
  10. /**
  11.   * An associative array where the key is a namespace prefix and the value
  12.   * is an array of base directories for classes in that namespace.
  13.   *
  14.   * @var array
  15.   */
  16. protected $prefixes = [];
  17. /**
  18.   * Register loader with SPL autoloader stack.
  19.   *
  20.   * @param bool $prepend If true, will prepend the autoloader on
  21.   * the autoload queue instead of appending it.
  22.   * @return $this
  23.   */
  24. public function register($prepend = false)
  25. {
  26. spl_autoload_register([$this, 'loadClass'], true, $prepend);
  27. return $this;
  28. }
  29. /**
  30.   * Unregister loader with SPL autoloader stack.
  31.   *
  32.   * @return void
  33.   */
  34. public function unregister()
  35. {
  36. spl_autoload_unregister([$this, 'loadClass']);
  37. }
  38.  
  39. /**
  40.   * Adds a base directory for a namespace prefix.
  41.   *
  42.   * @param string $prefix The namespace prefix.
  43.   * @param string $baseDir A base directory for class files in the namespace.
  44.   * @param bool $prepend If true, prepend the base directory to the stack.
  45.   * instead of appending it, this causes it to be searched first rather than
  46.   * last.
  47.   * @return this
  48.   */
  49. public function addPrefix($prefix, $baseDir, $prepend = false)
  50. {
  51. // Normalize namespace prefix.
  52. $prefix = trim($prefix, '\\') . '\\';
  53. // Normalize the base directory with a trailing separator.
  54. $baseDir = realpath($baseDir) . DIRECTORY_SEPARATOR;
  55. // Initialize the namespace prefix array.
  56. if (!isset($this->prefixes[$prefix])) {
  57. $this->prefixes[$prefix] = [];
  58. }
  59. // Retain the base directory for the namespace prefix.
  60. if ($prepend) {
  61. array_unshift($this->prefixes[$prefix], $baseDir);
  62. } else {
  63. array_push($this->prefixes[$prefix], $baseDir);
  64. }
  65. return $this;
  66. }
  67.  
  68. /**
  69.   * Loads the class file for a given class name.
  70.   *
  71.   * @param string $class The fully-qualified class name.
  72.   * @return bool
  73.   */
  74. public function loadClass($class)
  75. {
  76. if (strpos($class, '\\') !== false) {
  77. foreach ($this->prefixes as $namespace => $baseDirs) {
  78. if (strpos($class, $namespace) === 0) {
  79. $path = substr($class, strlen($namespace));
  80. $path = str_replace('\\', DIRECTORY_SEPARATOR, $path) . self::EXTENSION;
  81. foreach ($baseDirs as $baseDir) {
  82. $file = $baseDir . $path;
  83. // If the mapped file exists, require it
  84. if ($this->requireFile($file)) {
  85. return $file;
  86. }
  87. }
  88. }
  89. }
  90. }
  91. // Never found a mapped file
  92. return false;
  93. }
  94. /**
  95.   * If a file exists, require it from the file system.
  96.   *
  97.   * @param string $file The file to require.
  98.   * @return bool
  99.   */
  100. protected function requireFile($file)
  101. {
  102. if (file_exists($file)) {
  103. require $file;
  104. return true;
  105. }
  106. return false;
  107. }
  108. }
  109.  
  110. class MockPsr4AutoloaderClass extends Psr4Autoloader
  111. {
  112. protected $files = array();
  113.  
  114. public function setFiles(array $files)
  115. {
  116. $this->files = $files;
  117. }
  118.  
  119. protected function requireFile($file)
  120. {
  121. return in_array($file, $this->files);
  122. }
  123. }
  124.  
  125. $loader = new MockPsr4AutoloaderClass;
  126.  
  127. $loader->setFiles(array(
  128. '/vendor/foo.bar/src/ClassName.php',
  129. '/vendor/foo.bar/src/DoomClassName.php',
  130. '/vendor/foo.bar/tests/ClassNameTest.php',
  131. '/vendor/foo.bardoom/src/ClassName.php',
  132. '/vendor/foo.bar.baz.dib/src/ClassName.php',
  133. '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php',
  134. ));
  135.  
  136. $loader->addPrefix(
  137. 'Foo\Bar',
  138. '/vendor/foo.bar/src'
  139. );
  140.  
  141. $loader->addPrefix(
  142. 'Foo\Bar',
  143. '/vendor/foo.bar/tests'
  144. );
  145.  
  146. $loader->addPrefix(
  147. 'Foo\BarDoom',
  148. '/vendor/foo.bardoom/src'
  149. );
  150.  
  151. $loader->addPrefix(
  152. 'Foo\Bar\Baz\Dib',
  153. '/vendor/foo.bar.baz.dib/src'
  154. );
  155.  
  156. $loader->addPrefix(
  157. 'Foo\Bar\Baz\Dib\Zim\Gir',
  158. '/vendor/foo.bar.baz.dib.zim.gir/src'
  159. );
  160.  
  161. assert_options(ASSERT_ACTIVE, 1);
  162.  
  163. var_dump($loader->loadClass('Foo\Bar\ClassName')); echo PHP_EOL;
  164. assert($loader->loadClass('Foo\Bar\ClassName') === '/vendor/foo.bar/src/ClassName.php');
  165.  
  166. var_dump($loader->loadClass('Foo\Bar\ClassNameTest')); echo PHP_EOL;
  167. assert($loader->loadClass('Foo\Bar\ClassNameTest') === '/vendor/foo.bar/tests/ClassNameTest.php');
  168.  
  169. var_dump($loader->loadClass('No_Vendor\No_Package\NoClass')); echo PHP_EOL;
  170. assert($loader->loadClass('No_Vendor\No_Package\NoClass') === false);
  171.  
  172. var_dump($loader->loadClass('Foo\Bar\Baz\Dib\Zim\Gir\ClassName')); echo PHP_EOL;
  173. assert($loader->loadClass('Foo\Bar\Baz\Dib\Zim\Gir\ClassName') === '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php');
  174.  
  175. var_dump($loader->loadClass('Foo\Bar\DoomClassName')); echo PHP_EOL;
  176. assert($loader->loadClass('Foo\Bar\DoomClassName') === '/vendor/foo.bar/src/DoomClassName.php');
  177.  
  178. var_dump($loader->loadClass('Foo\BarDoom\ClassName')); echo PHP_EOL;
  179. assert($loader->loadClass('Foo\BarDoom\ClassName') === '/vendor/foo.bardoom/src/ClassName.php');
  180.  
Success #stdin #stdout #stderr 0.03s 52480KB
stdin
Standard input is empty
stdout
bool(false)

bool(false)

bool(false)

bool(false)

bool(false)

bool(false)

stderr
PHP Warning:  assert(): Assertion failed in /home/eZneGQ/prog.php on line 164
PHP Warning:  assert(): Assertion failed in /home/eZneGQ/prog.php on line 167
PHP Warning:  assert(): Assertion failed in /home/eZneGQ/prog.php on line 173
PHP Warning:  assert(): Assertion failed in /home/eZneGQ/prog.php on line 176
PHP Warning:  assert(): Assertion failed in /home/eZneGQ/prog.php on line 179