/** * This function is a singleton for the Haanga_Compiler_Runtime class. * The instance is already set up properly and resetted. * * * @param bool $checkdir TRUE * * @return Haanga_Compiler_Runtime */ protected static function getCompiler($checkdir = TRUE) { static $compiler; static $has_checkdir = FALSE; if (!$compiler) { /* Load needed files (to avoid autoload as much as possible) */ $dir = dirname(__FILE__); require_once "{$dir}/Haanga/AST.php"; require_once "{$dir}/Haanga/Compiler.php"; require_once "{$dir}/Haanga/Compiler/Runtime.php"; require_once "{$dir}/Haanga/Compiler/Parser.php"; require_once "{$dir}/Haanga/Compiler/Tokenizer.php"; require_once "{$dir}/Haanga/Generator/PHP.php"; require_once "{$dir}/Haanga/Extension.php"; require_once "{$dir}/Haanga/Extension/Filter.php"; require_once "{$dir}/Haanga/Extension/Tag.php"; /* load compiler (done just once) */ if (self::$use_autoload) { spl_autoload_register(array(__CLASS__, 'AutoLoad')); } $compiler = new Haanga_Compiler_Runtime(); if (self::$bootstrap) { /* call bootstrap hook, just the first time */ call_user_func(self::$bootstrap); } if (count(self::$compiler) != 0) { foreach (self::$compiler as $opt => $value) { Haanga_Compiler::setOption($opt, $value); } } } if ($checkdir && !$has_checkdir) { self::checkCacheDir(); $has_checkdir = TRUE; } $compiler->reset(); return $compiler; }
/** * Load * * Load template. If the template is already compiled, just the compiled * PHP file will be included an used. If the template is new, or it * had changed, the Haanga compiler is loaded in memory, and the template * is compiled. * * * @param string $file * @param array $vars * @param bool $return * @param array $blocks * * @return string|NULL */ public static function Load($file, $vars = array(), $return = FALSE, $blocks = array()) { static $compiler; if (empty(self::$cache_dir)) { throw new Haanga_Exception("Cache dir or template dir is missing"); } self::$has_compiled = FALSE; $tpl = self::$templates_dir . '/' . $file; $fnc = sha1($tpl); $callback = "haanga_" . $fnc; if (is_callable($callback)) { return $callback($vars, $return, $blocks); } $php = self::$hash_filename ? $fnc : $file; $php = self::$cache_dir . '/' . $php . '.php'; $check = TRUE; if (self::$check_ttl && self::$check_get && self::$check_set) { /* */ if (call_user_func(self::$check_get, $callback)) { /* disable checking for the next $check_ttl seconds */ $check = FALSE; } else { $result = call_user_func(self::$check_set, $callback, TRUE, self::$check_ttl); } } if (!is_file($php) || $check && filemtime($tpl) > filemtime($php)) { if (!is_file($tpl)) { /* There is no template nor compiled file */ throw new Exception("View {$file} doesn't exists"); } if (!is_dir(dirname($php))) { $old = umask(0); mkdir(dirname($php), 0777, TRUE); umask($old); } $fp = fopen($php, "a+"); /* try to block PHP file */ if (!flock($fp, LOCK_EX | LOCK_NB)) { /* couldn't block, another process is already compiling */ fclose($fp); if (is_file($php)) { /* ** if there is an old version of the cache ** load it */ require $php; return $callback($vars, $return, $blocks); } /* ** no luck, probably the template is new ** the compilation will be done, but we won't ** save */ unset($fp); } /* recompile */ if (!$compiler) { self::checkCacheDir(); /* Load needed files (to avoid autoload as much as possible) */ $dir = dirname(__FILE__); require_once "{$dir}/Haanga/AST.php"; require_once "{$dir}/Haanga/Compiler.php"; require_once "{$dir}/Haanga/Compiler/Runtime.php"; require_once "{$dir}/Haanga/Compiler/Parser.php"; require_once "{$dir}/Haanga/Compiler/Lexer.php"; require_once "{$dir}/Haanga/Generator/PHP.php"; require_once "{$dir}/Haanga/Extension.php"; require_once "{$dir}/Haanga/Extension/Filter.php"; require_once "{$dir}/Haanga/Extension/Tag.php"; /* load compiler (done just once) */ if (self::$use_autoload) { spl_autoload_register(array(__CLASS__, 'AutoLoad')); } $compiler = new Haanga_Compiler_Runtime(); if (self::$bootstrap) { /* call bootstrap hook, just the first time */ call_user_func(self::$bootstrap); } if (count(self::$compiler) != 0) { foreach (self::$compiler as $opt => $value) { Haanga_Compiler::setOption($opt, $value); } } } $compiler->reset(); if (self::$debug) { $compiler->setDebug($php . ".dump"); } $code = $compiler->compile_file($tpl, FALSE, $vars); if (isset($fp)) { ftruncate($fp, 0); // truncate file fwrite($fp, "<?php" . $code); flock($fp, LOCK_UN); // release the lock fclose($fp); } else { /* local eval */ eval($code); } self::$has_compiled = TRUE; } if (!is_callable($callback)) { require $php; } if (!isset($HAANGA_VERSION) || $HAANGA_VERSION != HAANGA_VERSION) { touch($php, 300, 300); chmod($php, 0777); } return $callback($vars, $return, $blocks); }