<?php
/**
* A general-purpose implementation that includes the optional functionality
* of allowing multiple base directories for a single namespace prefix.
*/
class Psr4Autoloader
{
const EXTENSION = '.php' ;
/**
* An associative array where the key is a namespace prefix and the value
* is an array of base directories for classes in that namespace.
*
* @var array
*/
protected $prefixes = [ ] ;
/**
* Register loader with SPL autoloader stack.
*
* @param bool $prepend If true, will prepend the autoloader on
* the autoload queue instead of appending it.
* @return $this
*/
public function register( $prepend = false )
{
return $this ;
}
/**
* Unregister loader with SPL autoloader stack.
*
* @return void
*/
public function unregister( )
{
}
/**
* Adds a base directory for a namespace prefix.
*
* @param string $prefix The namespace prefix.
* @param string $baseDir A base directory for class files in the namespace.
* @param bool $prepend If true, prepend the base directory to the stack.
* instead of appending it, this causes it to be searched first rather than
* last.
* @return this
*/
public function addPrefix( $prefix , $baseDir , $prepend = false )
{
// Normalize namespace prefix.
$prefix = trim ( $prefix , '\\' ) . '\\' ; // Normalize the base directory with a trailing separator.
$baseDir = realpath ( $baseDir ) . DIRECTORY_SEPARATOR ; // Initialize the namespace prefix array.
if ( ! isset ( $this -> prefixes [ $prefix ] ) ) { $this -> prefixes [ $prefix ] = [ ] ;
}
// Retain the base directory for the namespace prefix.
if ( $prepend ) {
} else {
}
return $this ;
}
/**
* Loads the class file for a given class name.
*
* @param string $class The fully-qualified class name.
* @return bool
*/
public function loadClass( $class )
{
if ( strpos ( $class , '\\' ) !== false ) { foreach ( $this -> prefixes as $namespace => $baseDirs ) {
if ( strpos ( $class , $namespace ) === 0 ) { $path = str_replace ( '\\' , DIRECTORY_SEPARATOR , $path ) . self :: EXTENSION ; foreach ( $baseDirs as $baseDir ) {
$file = $baseDir . $path ;
// If the mapped file exists, require it
if ( $this -> requireFile ( $file ) ) {
return $file ;
}
}
}
}
}
// Never found a mapped file
return false ;
}
/**
* If a file exists, require it from the file system.
*
* @param string $file The file to require.
* @return bool
*/
protected function requireFile( $file )
{
require $file ;
return true ;
}
return false ;
}
}
class MockPsr4AutoloaderClass extends Psr4Autoloader
{
protected $files = array ( ) ;
public function setFiles
( array $files ) {
$this -> files = $files ;
}
protected function requireFile( $file )
{
}
}
$loader = new MockPsr4AutoloaderClass;
'/vendor/foo.bar/src/ClassName.php' ,
'/vendor/foo.bar/src/DoomClassName.php' ,
'/vendor/foo.bar/tests/ClassNameTest.php' ,
'/vendor/foo.bardoom/src/ClassName.php' ,
'/vendor/foo.bar.baz.dib/src/ClassName.php' ,
'/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php' ,
) ) ;
$loader -> addPrefix (
'Foo\Bar' ,
'/vendor/foo.bar/src'
) ;
$loader -> addPrefix (
'Foo\Bar' ,
'/vendor/foo.bar/tests'
) ;
$loader -> addPrefix (
'Foo\BarDoom' ,
'/vendor/foo.bardoom/src'
) ;
$loader -> addPrefix (
'Foo\Bar\Baz\Dib' ,
'/vendor/foo.bar.baz.dib/src'
) ;
$loader -> addPrefix (
'Foo\Bar\Baz\Dib\Zim\Gir' ,
'/vendor/foo.bar.baz.dib.zim.gir/src'
) ;
var_dump ( $loader -> loadClass ( 'Foo\Bar\ClassName' ) ) ; echo PHP_EOL
; assert ( $loader -> loadClass ( 'Foo\Bar\ClassName' ) === '/vendor/foo.bar/src/ClassName.php' ) ;
var_dump ( $loader -> loadClass ( 'Foo\Bar\ClassNameTest' ) ) ; echo PHP_EOL
; assert ( $loader -> loadClass ( 'Foo\Bar\ClassNameTest' ) === '/vendor/foo.bar/tests/ClassNameTest.php' ) ;
var_dump ( $loader -> loadClass ( 'No_Vendor\No_Package\NoClass' ) ) ; echo PHP_EOL
; assert ( $loader -> loadClass ( 'No_Vendor\No_Package\NoClass' ) === false ) ;
var_dump ( $loader -> loadClass ( 'Foo\Bar\Baz\Dib\Zim\Gir\ClassName' ) ) ; echo PHP_EOL
; assert ( $loader -> loadClass ( 'Foo\Bar\Baz\Dib\Zim\Gir\ClassName' ) === '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php' ) ;
var_dump ( $loader -> loadClass ( 'Foo\Bar\DoomClassName' ) ) ; echo PHP_EOL
; assert ( $loader -> loadClass ( 'Foo\Bar\DoomClassName' ) === '/vendor/foo.bar/src/DoomClassName.php' ) ;
var_dump ( $loader -> loadClass ( 'Foo\BarDoom\ClassName' ) ) ; echo PHP_EOL
; assert ( $loader -> loadClass ( 'Foo\BarDoom\ClassName' ) === '/vendor/foo.bardoom/src/ClassName.php' ) ;
PD9waHAKCi8qKgogKiBBIGdlbmVyYWwtcHVycG9zZSBpbXBsZW1lbnRhdGlvbiB0aGF0IGluY2x1ZGVzIHRoZSBvcHRpb25hbCBmdW5jdGlvbmFsaXR5CiAqIG9mIGFsbG93aW5nIG11bHRpcGxlIGJhc2UgZGlyZWN0b3JpZXMgZm9yIGEgc2luZ2xlIG5hbWVzcGFjZSBwcmVmaXguCiAqLwpjbGFzcyBQc3I0QXV0b2xvYWRlcgp7CiAgICBjb25zdCBFWFRFTlNJT04gPSAnLnBocCc7CiAgICAvKioKICAgICAqIEFuIGFzc29jaWF0aXZlIGFycmF5IHdoZXJlIHRoZSBrZXkgaXMgYSBuYW1lc3BhY2UgcHJlZml4IGFuZCB0aGUgdmFsdWUKICAgICAqIGlzIGFuIGFycmF5IG9mIGJhc2UgZGlyZWN0b3JpZXMgZm9yIGNsYXNzZXMgaW4gdGhhdCBuYW1lc3BhY2UuCiAgICAgKgogICAgICogQHZhciBhcnJheQogICAgICovCiAgICBwcm90ZWN0ZWQgJHByZWZpeGVzID0gW107CiAgICAvKioKICAgICAqIFJlZ2lzdGVyIGxvYWRlciB3aXRoIFNQTCBhdXRvbG9hZGVyIHN0YWNrLgogICAgICogCiAgICAgKiBAcGFyYW0gYm9vbCAkcHJlcGVuZCBJZiB0cnVlLCB3aWxsIHByZXBlbmQgdGhlIGF1dG9sb2FkZXIgb24KICAgICAqIHRoZSBhdXRvbG9hZCBxdWV1ZSBpbnN0ZWFkIG9mIGFwcGVuZGluZyBpdC4KICAgICAqIEByZXR1cm4gJHRoaXMKICAgICAqLwogICAgcHVibGljIGZ1bmN0aW9uIHJlZ2lzdGVyKCRwcmVwZW5kID0gZmFsc2UpCiAgICB7CiAgICAgICAgc3BsX2F1dG9sb2FkX3JlZ2lzdGVyKFskdGhpcywgJ2xvYWRDbGFzcyddLCB0cnVlLCAkcHJlcGVuZCk7CiAgICAgICAgcmV0dXJuICR0aGlzOwogICAgfQogICAgLyoqCiAgICAgKiBVbnJlZ2lzdGVyIGxvYWRlciB3aXRoIFNQTCBhdXRvbG9hZGVyIHN0YWNrLgogICAgICogCiAgICAgKiBAcmV0dXJuIHZvaWQKICAgICAqLwogICAgcHVibGljIGZ1bmN0aW9uIHVucmVnaXN0ZXIoKQogICAgewogICAgICAgIHNwbF9hdXRvbG9hZF91bnJlZ2lzdGVyKFskdGhpcywgJ2xvYWRDbGFzcyddKTsKICAgIH0KICAgIAogICAgLyoqCiAgICAgKiBBZGRzIGEgYmFzZSBkaXJlY3RvcnkgZm9yIGEgbmFtZXNwYWNlIHByZWZpeC4KICAgICAqCiAgICAgKiBAcGFyYW0gc3RyaW5nICRwcmVmaXggVGhlIG5hbWVzcGFjZSBwcmVmaXguCiAgICAgKiBAcGFyYW0gc3RyaW5nICRiYXNlRGlyIEEgYmFzZSBkaXJlY3RvcnkgZm9yIGNsYXNzIGZpbGVzIGluIHRoZSBuYW1lc3BhY2UuCiAgICAgKiBAcGFyYW0gYm9vbCAkcHJlcGVuZCBJZiB0cnVlLCBwcmVwZW5kIHRoZSBiYXNlIGRpcmVjdG9yeSB0byB0aGUgc3RhY2suCiAgICAgKiBpbnN0ZWFkIG9mIGFwcGVuZGluZyBpdCwgdGhpcyBjYXVzZXMgaXQgdG8gYmUgc2VhcmNoZWQgZmlyc3QgcmF0aGVyIHRoYW4KICAgICAqIGxhc3QuCiAgICAgKiBAcmV0dXJuIHRoaXMKICAgICAqLwogICAgcHVibGljIGZ1bmN0aW9uIGFkZFByZWZpeCgkcHJlZml4LCAkYmFzZURpciwgJHByZXBlbmQgPSBmYWxzZSkKICAgIHsKICAgICAgICAvLyBOb3JtYWxpemUgbmFtZXNwYWNlIHByZWZpeC4KICAgICAgICAkcHJlZml4ID0gdHJpbSgkcHJlZml4LCAnXFwnKSAuICdcXCc7CiAgICAgICAgLy8gTm9ybWFsaXplIHRoZSBiYXNlIGRpcmVjdG9yeSB3aXRoIGEgdHJhaWxpbmcgc2VwYXJhdG9yLgogICAgICAgICRiYXNlRGlyID0gcmVhbHBhdGgoJGJhc2VEaXIpIC4gRElSRUNUT1JZX1NFUEFSQVRPUjsKICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBuYW1lc3BhY2UgcHJlZml4IGFycmF5LgogICAgICAgIGlmICghaXNzZXQoJHRoaXMtPnByZWZpeGVzWyRwcmVmaXhdKSkgewogICAgICAgICAgICAkdGhpcy0+cHJlZml4ZXNbJHByZWZpeF0gPSBbXTsKICAgICAgICB9CiAgICAgICAgLy8gUmV0YWluIHRoZSBiYXNlIGRpcmVjdG9yeSBmb3IgdGhlIG5hbWVzcGFjZSBwcmVmaXguCiAgICAgICAgaWYgKCRwcmVwZW5kKSB7CiAgICAgICAgICAgIGFycmF5X3Vuc2hpZnQoJHRoaXMtPnByZWZpeGVzWyRwcmVmaXhdLCAkYmFzZURpcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYXJyYXlfcHVzaCgkdGhpcy0+cHJlZml4ZXNbJHByZWZpeF0sICRiYXNlRGlyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuICR0aGlzOwogICAgfQogICAgCiAgICAvKioKICAgICAqIExvYWRzIHRoZSBjbGFzcyBmaWxlIGZvciBhIGdpdmVuIGNsYXNzIG5hbWUuCiAgICAgKgogICAgICogQHBhcmFtIHN0cmluZyAkY2xhc3MgVGhlIGZ1bGx5LXF1YWxpZmllZCBjbGFzcyBuYW1lLgogICAgICogQHJldHVybiBib29sCiAgICAgKi8KICAgIHB1YmxpYyBmdW5jdGlvbiBsb2FkQ2xhc3MoJGNsYXNzKQogICAgewogICAgICAgIGlmIChzdHJwb3MoJGNsYXNzLCAnXFwnKSAhPT0gZmFsc2UpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJHRoaXMtPnByZWZpeGVzIGFzICRuYW1lc3BhY2UgPT4gJGJhc2VEaXJzKSB7CiAgICAgICAgICAgICAgICBpZiAoc3RycG9zKCRjbGFzcywgJG5hbWVzcGFjZSkgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAkcGF0aCA9IHN1YnN0cigkY2xhc3MsIHN0cmxlbigkbmFtZXNwYWNlKSk7CiAgICAgICAgICAgICAgICAgICAgJHBhdGggPSBzdHJfcmVwbGFjZSgnXFwnLCBESVJFQ1RPUllfU0VQQVJBVE9SLCAkcGF0aCkgLiBzZWxmOjpFWFRFTlNJT047CiAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJGJhc2VEaXJzIGFzICRiYXNlRGlyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICRmaWxlID0gJGJhc2VEaXIgLiAkcGF0aDsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIG1hcHBlZCBmaWxlIGV4aXN0cywgcmVxdWlyZSBpdAogICAgICAgICAgICAgICAgICAgICAgICBpZiAoJHRoaXMtPnJlcXVpcmVGaWxlKCRmaWxlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRmaWxlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8vIE5ldmVyIGZvdW5kIGEgbWFwcGVkIGZpbGUKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICAvKioKICAgICAqIElmIGEgZmlsZSBleGlzdHMsIHJlcXVpcmUgaXQgZnJvbSB0aGUgZmlsZSBzeXN0ZW0uCiAgICAgKiAKICAgICAqIEBwYXJhbSBzdHJpbmcgJGZpbGUgVGhlIGZpbGUgdG8gcmVxdWlyZS4KICAgICAqIEByZXR1cm4gYm9vbAogICAgICovCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gcmVxdWlyZUZpbGUoJGZpbGUpCiAgICB7CiAgICAgICAgaWYgKGZpbGVfZXhpc3RzKCRmaWxlKSkgewogICAgICAgICAgICByZXF1aXJlICRmaWxlOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQp9CgpjbGFzcyBNb2NrUHNyNEF1dG9sb2FkZXJDbGFzcyBleHRlbmRzIFBzcjRBdXRvbG9hZGVyCnsKICAgIHByb3RlY3RlZCAkZmlsZXMgPSBhcnJheSgpOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBzZXRGaWxlcyhhcnJheSAkZmlsZXMpCiAgICB7CiAgICAgICAgJHRoaXMtPmZpbGVzID0gJGZpbGVzOwogICAgfQoKICAgIHByb3RlY3RlZCBmdW5jdGlvbiByZXF1aXJlRmlsZSgkZmlsZSkKICAgIHsKICAgICAgICByZXR1cm4gaW5fYXJyYXkoJGZpbGUsICR0aGlzLT5maWxlcyk7CiAgICB9Cn0KCiRsb2FkZXIgPSBuZXcgTW9ja1BzcjRBdXRvbG9hZGVyQ2xhc3M7CgokbG9hZGVyLT5zZXRGaWxlcyhhcnJheSgKICAgICcvdmVuZG9yL2Zvby5iYXIvc3JjL0NsYXNzTmFtZS5waHAnLAogICAgJy92ZW5kb3IvZm9vLmJhci9zcmMvRG9vbUNsYXNzTmFtZS5waHAnLAogICAgJy92ZW5kb3IvZm9vLmJhci90ZXN0cy9DbGFzc05hbWVUZXN0LnBocCcsCiAgICAnL3ZlbmRvci9mb28uYmFyZG9vbS9zcmMvQ2xhc3NOYW1lLnBocCcsCiAgICAnL3ZlbmRvci9mb28uYmFyLmJhei5kaWIvc3JjL0NsYXNzTmFtZS5waHAnLAogICAgJy92ZW5kb3IvZm9vLmJhci5iYXouZGliLnppbS5naXIvc3JjL0NsYXNzTmFtZS5waHAnLAopKTsKCiRsb2FkZXItPmFkZFByZWZpeCgKICAgICdGb29cQmFyJywKICAgICcvdmVuZG9yL2Zvby5iYXIvc3JjJwopOwoKJGxvYWRlci0+YWRkUHJlZml4KAogICAgJ0Zvb1xCYXInLAogICAgJy92ZW5kb3IvZm9vLmJhci90ZXN0cycKKTsKCiRsb2FkZXItPmFkZFByZWZpeCgKICAgICdGb29cQmFyRG9vbScsCiAgICAnL3ZlbmRvci9mb28uYmFyZG9vbS9zcmMnCik7CgokbG9hZGVyLT5hZGRQcmVmaXgoCiAgICAnRm9vXEJhclxCYXpcRGliJywKICAgICcvdmVuZG9yL2Zvby5iYXIuYmF6LmRpYi9zcmMnCik7CgokbG9hZGVyLT5hZGRQcmVmaXgoCiAgICAnRm9vXEJhclxCYXpcRGliXFppbVxHaXInLAogICAgJy92ZW5kb3IvZm9vLmJhci5iYXouZGliLnppbS5naXIvc3JjJwopOwoKYXNzZXJ0X29wdGlvbnMoQVNTRVJUX0FDVElWRSwgMSk7Cgp2YXJfZHVtcCgkbG9hZGVyLT5sb2FkQ2xhc3MoJ0Zvb1xCYXJcQ2xhc3NOYW1lJykpOyBlY2hvIFBIUF9FT0w7CmFzc2VydCgkbG9hZGVyLT5sb2FkQ2xhc3MoJ0Zvb1xCYXJcQ2xhc3NOYW1lJykgPT09ICcvdmVuZG9yL2Zvby5iYXIvc3JjL0NsYXNzTmFtZS5waHAnKTsKCnZhcl9kdW1wKCRsb2FkZXItPmxvYWRDbGFzcygnRm9vXEJhclxDbGFzc05hbWVUZXN0JykpOyBlY2hvIFBIUF9FT0w7CmFzc2VydCgkbG9hZGVyLT5sb2FkQ2xhc3MoJ0Zvb1xCYXJcQ2xhc3NOYW1lVGVzdCcpID09PSAnL3ZlbmRvci9mb28uYmFyL3Rlc3RzL0NsYXNzTmFtZVRlc3QucGhwJyk7Cgp2YXJfZHVtcCgkbG9hZGVyLT5sb2FkQ2xhc3MoJ05vX1ZlbmRvclxOb19QYWNrYWdlXE5vQ2xhc3MnKSk7IGVjaG8gUEhQX0VPTDsKYXNzZXJ0KCRsb2FkZXItPmxvYWRDbGFzcygnTm9fVmVuZG9yXE5vX1BhY2thZ2VcTm9DbGFzcycpID09PSBmYWxzZSk7Cgp2YXJfZHVtcCgkbG9hZGVyLT5sb2FkQ2xhc3MoJ0Zvb1xCYXJcQmF6XERpYlxaaW1cR2lyXENsYXNzTmFtZScpKTsgZWNobyBQSFBfRU9MOwphc3NlcnQoJGxvYWRlci0+bG9hZENsYXNzKCdGb29cQmFyXEJhelxEaWJcWmltXEdpclxDbGFzc05hbWUnKSA9PT0gJy92ZW5kb3IvZm9vLmJhci5iYXouZGliLnppbS5naXIvc3JjL0NsYXNzTmFtZS5waHAnKTsKCnZhcl9kdW1wKCRsb2FkZXItPmxvYWRDbGFzcygnRm9vXEJhclxEb29tQ2xhc3NOYW1lJykpOyBlY2hvIFBIUF9FT0w7CmFzc2VydCgkbG9hZGVyLT5sb2FkQ2xhc3MoJ0Zvb1xCYXJcRG9vbUNsYXNzTmFtZScpID09PSAnL3ZlbmRvci9mb28uYmFyL3NyYy9Eb29tQ2xhc3NOYW1lLnBocCcpOwoKdmFyX2R1bXAoJGxvYWRlci0+bG9hZENsYXNzKCdGb29cQmFyRG9vbVxDbGFzc05hbWUnKSk7IGVjaG8gUEhQX0VPTDsKYXNzZXJ0KCRsb2FkZXItPmxvYWRDbGFzcygnRm9vXEJhckRvb21cQ2xhc3NOYW1lJykgPT09ICcvdmVuZG9yL2Zvby5iYXJkb29tL3NyYy9DbGFzc05hbWUucGhwJyk7Cg==