| 
<?php
/**
 *
 * @author Andrei Alexandru Romila
 * @version 1.0
 *
 */
 class Autoloader {
 
 /**
 * PHP default file extension
 *
 * @var string
 */
 const PHP_EXTENSION = '.php';
 
 /**
 * Stores all namespaces and directories
 *
 * @var array
 */
 protected $prefixes = array();
 
 /**
 * Stores all the files
 *
 * @var array
 */
 protected $files = array();
 
 /**
 *
 * @param boolean $register
 */
 public function __construct($register = false) {
 if ($register === true) {
 $this->registerAutoloader();
 }
 }
 
 /**
 * Registers a new autoloader funtion
 *
 * @return boolean Returns true on success or false on failure.
 */
 public function registerAutoloader() {
 return spl_autoload_register(array($this, 'loadClass'), false, true);
 }
 
 /**
 * Register a new file for a classname.
 *
 * @param string $class The name of the class
 * @param string $filename The filename
 * @param boolean $replace If the class is already register, replace the filename
 */
 public function registerFile($class, $filename, $overwrite = false) {
 
 if (is_file($filename) === false || is_readable($filename) === false) {
 echo 'The file: ' . $filename . ' doen\'t exist or is not readable!<br />';
 return;
 }
 
 // Remove the '\' if the class is \ClassName
 $class = rtrim($class, '\\');
 
 // Get real path of the file and normalize directory separator
 $filename = realpath($filename);
 $filename = str_replace('\\', '/', $filename);
 
 // If is not set yet, create it
 if (isset($this->files[$class]) === false) {
 
 $this->files[$class] = $filename;
 
 } else if ($overwrite === true) {
 
 // Overwrite the last filename
 $this->files[$class] = $filename;
 
 }
 }
 
 /**
 * Registers a new namespace in the loader
 *
 * @param string $namespace The namespace
 * @param string $directory Path to the namespace
 */
 public function registerNamespace($namespace, $directory, $prepend = false) {
 
 if (is_dir($directory) === false || is_readable($directory) === false) {
 echo 'The directory: ' . $directory . ' doen\'t exist or is not readable!<br />';
 return;
 }
 
 $namespace = trim($namespace, '\\') . '\\';
 $directory = realpath($directory);
 $directory = str_replace('\\', '/', $directory) . '/';
 
 // If doesnt exist create a new array for the namespace.
 if (false === isset($this->prefixes[$namespace])) {
 
 $this->prefixes[$namespace] = array();
 
 } else if (in_array($directory, $this->prefixes[$namespace], true)) {
 
 // Already added ...
 return;
 
 }
 
 if ($prepend === true) {
 // Prepend this namespace
 $this->prefixes[$namespace] = array_unshift($this->prefixes[$namespace], $directory);
 } else {
 // A bit faster than array_push($array, $value1)
 $this->prefixes[$namespace][] = $directory;
 }
 
 }
 
 /**
 * PSR4 loadClass function with some enhancements.
 *
 * @param string $class
 */
 public function loadClass($class) {
 
 // Check for direct file registration - a bit faster than searching in a sub folder
 if (isset($this->files[$class]) && $this->requireFile($this->files[$class])) {
 return $this->files[$class];
 }
 
 // the current namespace prefix
 $prefix = $class;
 
 // work backwards through the namespace names of the fully-qualified
 // class name to find a mapped file name
 while (false !== ($position = strrpos($prefix, '\\'))) {
 
 // retain the trailing namespace separator in the prefix
 $prefix = substr($class, 0, $position + 1);
 
 // the rest is the relative class name
 $relative = substr($class, $position + 1);
 
 // try to load a mapped file for the prefix and relative class
 $filename = $this->loadFile($prefix, $relative);
 if ($filename) {
 return $filename;
 }
 
 // remove the trailing namespace separator for the next iteration
 // of strrpos()
 $prefix = rtrim($prefix, '\\');
 }
 
 // never found a mapped file
 return false;
 
 }
 
 /**
 * Load the mapped file for a namespace prefix and relative class.
 *
 * @param string $prefix The namespace prefix.
 * @param string $relativePath The relative class name.
 * @return mixed Boolean false if no mapped file can be loaded, or the
 * name of the mapped file that was loaded.
 */
 protected function loadFile($prefix, $relativePath) {
 
 // are there any base directories for this namespace prefix?
 if (isset($this->prefixes[$prefix]) === false) {
 return false;
 }
 
 // look through base directories for this namespace prefix
 foreach ($this->prefixes[$prefix] as $directory) {
 
 $filename = $directory . str_replace('\\', '/', $relativePath) . self::PHP_EXTENSION;
 
 // if the mapped file exists, require it
 if ($this->requireFile($filename)) {
 return $filename;
 }
 }
 
 // never found it
 return false;
 }
 
 /**
 * If a file exists, require it from the file system.
 *
 * @param string $file The file to require.
 * @return bool True if the file exists, false if not.
 */
 protected function requireFile($filename) {
 
 if (is_readable($filename)) {
 require $filename;
 return true;
 }
 
 return false;
 }
 
 }
 
 |