<?php
/**
 * Web Application Component Toolkit
 *
 * @link http://www.phpwact.org/
 *
 * @author Wact Development Team
 * @link http://www.phpwact.org/team
 *
 * @copyright Copyright 2006, Jeff Moore
 * @license http://opensource.org/licenses/mit-license.php MIT
 */

/**
 * Automatically load class files based on a class name to file mapping pattern
 */
class Wact_Loader {

    /**
     * The name of the standard Wact Namespace.
     */
    const WACT_NAMESPACE = 'Wact';

    /**
     * Indicates that the autoloader can attempt to load any class.
     */
    const ANY_NAMESPACE = '';
    
    /**
     * The default file extension for Wact class definition files
     */
    const WACT_CLASS_EXTENSION = '.inc.php';
    
    /**
     * @var string
     */
    protected $namespace;

    /**
     * @var string
     */
    protected $extension;
    
    /**
     * @param $namespace Restrict loading to classes with this namespace name.
     * @param $extension Extension for php class files.
'     */
    function __construct($namespace = self::ANY_NAMESPACE, $extension = self::WACT_CLASS_EXTENSION) {
        $this->namespace = $namespace;
        $this->extension = $extension;
    }

    /**
     * @param $class class name to find a defination for
     */
    public function autoload($class) {
        if (class_exists($class, false) || interface_exists($class, false)) {
            return true;
        }

        if (strncasecmp($class, $this->namespace, strlen($this->namespace)) !== 0) {
            return false;
        }

        $filename = str_replace('_', DIRECTORY_SEPARATOR, $class . $this->extension);
            
        if($fp = @fopen($filename, 'r', true)) {
            fclose($fp);
            require $filename;
            if (!class_exists($class, false) && !interface_Exists($class, false)) {
                // Exceptions get eaten while autoloading
                trigger_error("Class $class not found in $filename");
            } else {
                return true;
            }
        }
        return false;
    }

    /**
     */
    public function install() {
        spl_autoload_register(array($this, 'autoload'));
    }
    
    /**
     * Convenience method for installing the autoloader
     */
    static function installNew($namespace = self::ANY_NAMESPACE, $extension = self::WACT_CLASS_EXTENSION) {
       $loader = new self($namespace, $extension);
       $loader->install();
       return $loader;
    }

    /**
     * Test if a given path is in the include_path
     *
     * @param string $target_path path to test
     */
    static function inIncludePath($target_path) {
        foreach( explode(PATH_SEPARATOR, get_include_path()) as $path) {
            if ($path == $target_path) {
                return TRUE;
            }
        }
        return FALSE;
    }

    /**
     * Add a path to the include path if it is not there already.
     *
     * @param string $target_path
     */
    static function appendToIncludePath($target_path) {
        if (!self::inIncludePath($target_path)) {
            set_include_path(get_include_path() . PATH_SEPARATOR . $target_path);
        }
    }

    /**
     * Make sure the include_path includes the wact directory that this
     * file is located in.
     */
    static function setupWactIncludePath() {
        self::appendToIncludePath(dirname(dirname(__FILE__)));
    }
    
    /**
     * Convenience method that registers the autoloader and ensures that
     * Wact is in the include_path. 
     */
    static function setupWact($namespace = self::ANY_NAMESPACE) {
        $loader = new self($namespace);
        $loader->install();
        self::setupWactIncludePath();
        return $loader;
    }

}

?>