<?php
/**
 * core.framework
 *
 * @category  Core
 * @package   Core_Loader
 * @copyright Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license   proprietary
 */

/**
 * @category  Core
 * @package   Core_Loader
 * @copyright Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license   proprietary
 */
class Core_Loader
{
    /**
     * @var array Classmap of form "Class_Name" => "path/to/Class/Name.php"
     */
    static protected $_classMap   = array();

    /**
     * @var array Found class paths
     */
    static protected $_classPaths = array();

    /**
     * Register the Core_Loader::loadClass method as the autoloader
     *
     * @return void
     */
    static public function registerBasicAutoloader()
    {
        spl_autoload_register(array(new self, 'loadClass'));
    }

    /**
     * @param array $classMap
     *
     * @return void
     */
    static public function setClassMap(array $classMap)
    {
        self::$_classMap = array_merge(self::$_classMap, $classMap);
    }

    /**
     * Can this loader instance load a class by name?
     *
     * @param string $className
     *
     * @return boolean
     */
    static public function hasClass($className)
    {
        if (class_exists($className, false)) {
            return true;
        }
        return (bool) self::_findClassPath($className);
    }

    /**
     * Load the class by name.
     *
     * @param string $className
     *
     * @return void
     * @throws InvalidArgumentException If the class cannot be loaded
     */
    static public function loadClass($className)
    {
        if (class_exists($className, false)) {
            return true;
        }

        if (false === ($classPath = self::_findClassPath($className))) {
            return false;
        }
        return self::loadFile($classPath);
    }

    /**
     * Load the file by path.
     *
     * @param string $filePath
     *
     * @return void
     * @throws InvalidArgumentException If the file cannot be loaded
     */
    static public function loadFile($filePath)
    {
        include_once $filePath;
        return true;
    }


    /**
     * Find the class by name.
     *
     * @param string $className
     *
     * @return string Class full path if found or false if not.
     */
    static protected function _findClassPath($className)
    {
        if (isset(self::$_classMap[$className])) {
            return self::$_classMap[$className];
        } else if (!isset(self::$_classPaths[$className])) {
            // security check
            // why are there four backslashes?
            // - need to include the backslash: \
            // - escape it in the string: \\
            // - escape it in the regex, which means escaping the char and the escape char: \\\\
            if (preg_match('/[^\\\\a-zA-Z0-9_]/S', $className)) {
                throw new InvalidArgumentException('Trying to load a class with illegal chars in name');
            }

            $classPath = str_replace(array('_', '\\'), DIRECTORY_SEPARATOR, ltrim($className, '\\')) .'.php';
            self::$_classPaths[$className] = stream_resolve_include_path($classPath);
        }
        return self::$_classPaths[$className];
    }
}
