<?php 
namespace Jackbooted\Util; 
 
use \Jackbooted\Config\Cfg; 
/** 
 * @copyright Confidential and copyright (c) 2016 Jackbooted Software. All rights reserved. 
 * 
 * Written by Brett Dutton of Jackbooted Software 
 * brett at brettdutton dot com 
 * 
 * This software is written and distributed under the GNU General Public 
 * License which means that its source code is freely-distributed and 
 * available to the general public. 
 */ 
 
 
/** 
 * The day of require_once is now over for classes. This class will automatically set itself up to load any class from 
 * the classes folder and any of it's sub folders. The folowing code initializes and sets up the automatic class loader 
 * <pre> 
 * require_once ( Cfg::get ( 'classes_dir' ) . "/util/Log4PHP.inc" ); 
 * if ( Cfg::get ( 'development') ) { 
 *     Log4PHP::setLogLevel ( Log4PHP::ALL ); 
 * } 
 * 
 * // need to require once the autoloader 
 * require_once ( Cfg::get ( 'classes_dir' ) . "/util/AutoLoader.inc" ); 
 * AutoLoader::init ( Cfg::get ( 'classes_dir' ) ); 
 * </pre> 
 * 
 * The ClassLocator scans all the files in all the sub folders looking for the class that you are trying to load. 
 * 
 * <b>Third Party Libraries</b><br> 
 * You can load third party libraries with the autoloader by creating a class with a dummy class name in comments and 
 * require_once the file containing the third party library. Example: 
 * 
 * <pre> 
 * <?php 
 * /* 
 * The tag below will fool the ClassLocator to associating this class with this file 
 * class Smarty 
 * * / 
 * // This is a dummy include so tha the autoloader finds this class and loads it up 
 * require_once( dirname ( dirname( __FILE__) ) . "/3rdparty/smarty/Smarty.class.php" ); 
 * ?> 
 * </pre> 
 * 
 * @see ClassLocator 
 */ 
class AutoLoader extends \Jackbooted\Util\JB { 
    /** 
     * Suffix for classes that are auto loaded 
     */ 
    const CLASS_SUFFIX = '.php'; 
    const THIRD_PARTY_REGEX = '/^.*\/3rdparty\/.*$/'; 
    /** 
     * initialization method 
     */ 
    const STATIC_INIT = 'init'; 
 
    private static $log; 
    private static $ignoreList =  []; 
 
    /** 
     * load set up the static variables of the class 
     * (still waiting on static initialisation from PHP) 
     * @param string $classesDir 
     */ 
    public static function init () { 
        spl_autoload_register ( __CLASS__ . '::autoload' ); 
        self::$log = Log4PHP::logFactory ( __CLASS__ ); 
    } 
 
    /** 
     * Adds a class to the ignore list. 
     * @param String $className 
     * @param String $fullName This is the full Java class Name. If it exists then assumes quercus and 
     * imports the class 
     * @return void 
     */ 
    public static function ignore ( $className, $fullName=null ) { 
        self::$ignoreList[$className] = true; 
        if ( $fullName != null && Cfg::get ( 'quercus', false ) ) { 
            eval ( 'import ' . $fullName . ';' ); 
        } 
    } 
    /** 
     * This method is called by the autoloader - Registered somewhere (config) 
     * with spl_autoload_register ( 'AutoLoader::autoload' ); 
     * This class must be manually loaded with require_one and then call init 
     * @param string $className Class name that needs to be loaded 
     */ 
    public static function autoload ( $className ) { 
        if ( isset ( self::$ignoreList[$className] ) ) return; 
 
        $tries = self::locateClassFromFileAndLoad ( $className ); 
        if ( $tries === true )  return; 
 
        // If made it to here then we have not loaded anything 
        self::$log->error ( 'The system has attempted to autoload non existing class: ' . $className . ' tried: (' . implode ( ', ', $tries ) . ')'  ); 
    } 
 
    /** 
     * Loads a class based on the class name for legacy classes 
     * @param string $className This is the class that you are attemption to load 
     * @return mixed Return true on successful load, otherwise it returns a list of all the file locations 
     * that it tried to load from 
     */ 
    private static function locateClassFromFileAndLoad ( $className ) { 
        $fileToLoad = ClassLocator::getLocation( $className ); 
        if ( $fileToLoad === false ) return  [ 'none found' ]; 
        if ( self::loadClassFromFile( $className, $fileToLoad ) ) return true; 
        return  [ $fileToLoad ]; 
    } 
 
    /** 
     * Loads a class from the passed file. Attempts to initialize the class 
     * @param string $className This is the class that youb are attemption to load 
     * @param string $fileToLoad The file that you are loading the class from 
     * @return boolean true on sucess 
     */ 
    public static function loadClassFromFile ( $className, $fileToLoad ) { 
        // If the file does not exist then get out 
        if ( ! file_exists ( $fileToLoad ) ) return false; 
 
        // Everything good! 
        require_once $fileToLoad; 
 
        // RUn class level initialization only on classes that follow JackBoot Web standard 
        if ( preg_match ( self::THIRD_PARTY_REGEX, $fileToLoad ) ) { 
            self::$log->trace ( "Skipping class initialization for {$className} from " . $fileToLoad ); 
        } 
        else { 
            self::runClassInitialization ( $className ); 
        } 
 
        self::$log->trace ( "Loaded {$className} from " . $fileToLoad ); 
        return true; 
    } 
 
    /** 
     * Check to see if there is class level initialisation and then runs it 
     * Need this because PHP does not have static initialisation yet 
     * @param string $className to initialise 
     */ 
    private static function runClassInitialization ( $className ) { 
        if ( Cfg::get ( 'quercus', false ) ) { 
            @eval ( $className . '::' . self::STATIC_INIT . '();' ); 
        } 
        else if ( method_exists ( $className, self::STATIC_INIT ) ) { 
            $classLevelInit =  [ $className, self::STATIC_INIT ]; 
            call_user_func ( $classLevelInit ); 
        } 
    } 
}
 
 |