<?php
/**
* autoload.class.php
*
* A class wrapper for the __autoload function
*
* @version 1.0
* @author Thomas Shone <hide@address.com>
* @copyright 2008
* @since 2008-10-24
*
*/
class Autoload {
/**
* Singleton instance of the autoloader
*
* @var Autoload
* @access private
*/
private static $_instance;
/**
* Required collection of files that MUST be included when
* this object is initialized.
*
* @var string array
* @access private
*/
private $_required = array("defaultclass");
/**
* The base path to search for source files
*
* @var string
* @access private
*/
private $_base_dir = "include";
/**
* A list of libraries or files to ignore.
*
* @var string array
* @access private
*/
private $_ignore = array(".", "..");
/**
* A list of available libraries
*
* @var string array
* @access private
*/
private $_available;
/**
* Temporary cross-recursive-function storage.
*
* @var string array
* @access private
*/
private $_found_tmp;
/**
* Extensions to look for on files.
*
* @var string array
* @access private
*/
private $_extensions = array(".class.php", ".inc", ".class.inc", ".php");
/**
* Log of actions of this class
*
* @var string array
* @access private
*/
private $_log;
/**
* PHP 5 constructor
*
* Loads the required libraries on initialization
*
* @access public
*/
private function __construct() {
$this->_buildList($this->_base_dir);
foreach ($this->_required as $file) {
$this->loadFile($file);
}
}
/**
* PHP 3,4 constructor
*
* Points to __constructor()
*
* @access public
*/
private function Factory() {
$this->__construct();
}
/**
* Locates and loads a file on request
*
* @param string $class
* @access public
*/
public function loadFile($class) {
if ($this->_available[$class]) {
// Include the requested class and log it
require_once $this->_available[$class];
$this->_log[] = "Loaded ". $class ." (". $this->_available[$class] .")";
return true;
} else {
throw new Exception("Could not find file for class ". $class);
}
}
/**
* Recursively pass through a directory and find all files that match a paricular pattern
*
* @param string $base
* @access private
*/
private function _buildList($dir = "") {
// Add a / if required
$dir = rtrim($dir, "/") ."/";
if ($directory_handle = opendir($dir)) {
while (($file_handle = readdir($directory_handle)) !== false) {
// Is the file in the ignore list
if (in_array($file_handle, $this->_ignore)) {
// Recusrively check any directories we come across
} else if (is_dir($dir . $file_handle)) {
$this->buildList($dir . $file_handle);
} else {
// If the found file matches one of the acceptable extensions
$class = str_replace($this->_extensions, array_fill(0, count($this->_extensions), ""), $file_handle);
// Is there already a file found for this class?
if (isset($this->_available[$class])) {
throw new Exception("Duplicate file for ". $class ." found.");
} else {
$this->_available[$class] = $dir . $file_handle;
}
}
}
}
}
/**
* Return the log
*
* @access public
* @return string array
*/
public function getLog() {
return $this->_log;
}
/**
* Clone magic function prevents external instantiation of copies of the Singleton class
*
* @access public
*/
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
/**
* Wakeup magic function prevents external instantiation of copies of the Singleton class
*
* @access public
*/
public function __wakeup() {
trigger_error('Deserializing is not allowed.', E_USER_ERROR);
}
/**
* Get the singleton instance of this class
*
* @access public
* @return self
*/
public function getInstance() {
if (!self::$_instance instanceof self) {
self::$_instance = new self;
}
return self::$_instance;
}
}
/**
* Overloading the default __autoload function
*
* @param string $class
*/
function __autoload($class) {
if (!Autoload::getInstance()->loadFile(strtolower($class))) {
// Note: Exceptions thrown in __autoload function cannot be caught in the catch block and results in a fatal error.
// Note: Autoloading is not available if using PHP in CLI interactive mode.
throw new Exception("Failed to load essential library: ". $class, __FILE__, __LINE__);
}
}
?>