Location: PHPKode > projects > PWF > PWF_0.3.0/Core/ClassLoader.php
<?php
/**
 _Core_ClassLoader registers and defines the autoload method and methods for
 retrieving Controllers public static properties from cache file and update
 them if they change. It is a framework internal class instantiated by the _Core_FrontController
 * @copyright	Copyright (c) 2012, PWF
 * @license		http://phpwebframework.com/License 
 * @version PWF_0.3.0
 */
class _Core_ClassLoader
{

  /**
   * The directory of the cache files for Controllers static properties
   */
  private static $cacheDir;

  /**
   * The unique id of the application
   */
  public static $applicationId;

  /**
   * The reflections classes of the used Controllers in an array with the class name as key
   */
  private static $reflectionClasses = array();

  /**
   * Array of the static properties of each Controller with the class name as key and an array
   * with property name and each value, as value
   */
  private $staticVariables = array();


  /**
   * The application properties object generated by the defined PROPERTIES_FILE of the index.php
   * @var _Properties
   */
  private $properties;

  /**
   * Three dimensions array with first key the class name , second key the static property
   * name and third the flag "ID" for the special caching id and "VALUE" for the original
   * value of the property after binding from caching file.
   * @var array
   */
  private static $cachingBinds;

  /**
   * Registers the autoload method
   */
  public function __construct()
  {
    require_once(PWF_VERSION."/String.php");
    spl_autoload_register(array($this, "load"));
  }

  /**
   * Initiates the class for what is necessary for Controllers static properties caching
   * and defines the External folder of the framework as include path (for classes outside 
   * PWF naming convensions). 
   * @param _Properties $properties
   */
  public function init(_Properties $properties)
  {
    $pwfDir = _String::beforeLast(__FILE__, "Core");
    set_include_path(get_include_path() . PATH_SEPARATOR . $pwfDir."External");
    self::$cacheDir = $pwfDir."Cache";
    self::$applicationId = hash("crc32",getcwd())."_"._String::afterLast(SRC, "/");
    $this->properties = $properties;
  }

  /**
   * The autoload method. It tries to load the classes whose name start from _ from the PWF_VERSION
   * directory and all the others from the current src directory. Underscores are replaced with back
   * slashes , and it adds the .php extension to the file to require. If the class name starts form
   * Controller_ then it will try to load static properties from cache file.
   * @param $className The class name to be loaded
   * @throws _Exception_FileSystem
   */
  public function load($className)
  {
    if(_String::startsWith($className, "_"))
    {
      require_once(PWF_VERSION._String::replace($className, "_", "/").".php");
    }
    else
    {
      $classFile = _String::replace($className, "_", "/").".php";
      if(_File::exists($classFile))
      {
        require_once($classFile);
        // Read static variables of controller’s classes from cache files
        if( _String::startsWith($className, $this->properties->get("CONTROLLERS_FOLDER")."_") )
        {
          $reflClass = new ReflectionClass($className);
          if(!$reflClass->isInterface())
          {
            self::$reflectionClasses[$className] = $reflClass;
            $file =self::$cacheDir."/".self::$applicationId."-".$className;
            if(_File::exists($file))
            {
              $this->staticVariables[$className] = unserialize(_File::read($file));
              foreach($this->staticVariables[$className] as $key=>$value)
              {
                self::$reflectionClasses[$className]->setStaticPropertyValue($key, $value);
              }
            }
          }
        }
      }
      else
      {
        if(isset($this->properties))
        {
          throw new _Exception_FileSystem($classFile." "._Exception_Messages::$fileNotFound, 4568);
        }
      }
    }
  }


  /**
   * It takes the name of a public static property (that is out of PWF caching
   * static utility – it starts with _ ) and binds it with a PWF caching file
   * depending on the given id. The first parameter is the class name where the
   * property is declared.
   * @param $className The name of the class
   * @param $staticPropertyName The name of the static property
   * @param $id The id that it will be used for that bind
   */
  public static function cachingBind($className,$staticPropertyName,$id)
  {
    if(isset(self::$reflectionClasses[$className]) && _String::startsWith($staticPropertyName, "_") && self::$reflectionClasses[$className]->hasProperty($staticPropertyName))
    {
      $property = self::$reflectionClasses[$className]->getProperty($staticPropertyName);
      if($property->isPublic() && $property->isStatic())
      {
        $file =self::$cacheDir."/".self::$applicationId."-".$className."-".$staticPropertyName."-".$id;
        self::$cachingBinds[$className][$staticPropertyName]["ID"] = $id;
        if(_File::exists($file))
        {
          $content = _File::read($file);
          self::$cachingBinds[$className][$staticPropertyName]["VALUE"] = unserialize($content);
          self::$reflectionClasses[$className]->setStaticPropertyValue($staticPropertyName, unserialize($content));
        }
        else
        {
          self::$cachingBinds[$className][$staticPropertyName]["VALUE"] = null;
          self::$reflectionClasses[$className]->setStaticPropertyValue($staticPropertyName, null);
        }
      }
      else
      {
        throw new _Exception_FlowControl(_String::prepare(_Exception_Messages::$staticPropertyBinfFailed,array($staticPropertyName,$className)), 1234);
      }
    }
    else
    {
      throw new _Exception_FlowControl(_String::prepare(_Exception_Messages::$staticPropertyBinfFailed,array($staticPropertyName,$className)), 1234);
    }
  }


  /**
   * Checks if the static properties of used Controllers classes or
   * the special caching static properties that have been binded have changed
   * and if so it writes them in the class caching file
   */
  public function cache()
  {
    foreach(self::$reflectionClasses as $className => $reflectionClass)
    {
      $newStatics = array();
      $properties = $reflectionClass->getStaticProperties();

      if(_Array::size($properties) > 0)
      {
        foreach($reflectionClass->getStaticProperties() as $key => $value)
        {
          $property = $reflectionClass->getProperty($key);
          if($value != null && $property->getDeclaringClass()->getName() ==  $className && $property->isPublic() && !_String::startsWith($key, "_"))
          {
            $newStatics[$key] = $value;
          }
        }
      }

      if(count($newStatics) > 0)
      {
        $oldStatic = isset($this->staticVariables[$className]) ? $this->staticVariables[$className] : array();
        if($oldStatic != $newStatics)
        {
          _File::write(self::$cacheDir."/".self::$applicationId."-".$className, serialize($newStatics));
        }
      }
       
      if(isset(self::$cachingBinds[$className]))
      {
        foreach(self::$cachingBinds[$className] as $propertyName => $st)
        {
          $file =self::$cacheDir."/".self::$applicationId."-".$className."-".$propertyName."-".$st["ID"];
          $newValue = $reflectionClass->getStaticPropertyValue($propertyName);
          if($newValue == null && _File::exists($file))
          {
            _File::delete($file);
          }
          else if($newValue != $st["VALUE"])
          {
            _File::write($file, serialize($newValue));
          }
        }
      }
    }
  }
}
?>
Return current item: PWF