query("SELECT * FROM " . self::$dbCacheTable . " WHERE filename IN ('" . implode("', '", $namearray) . "')"); while ($tpl = $cache->fetchArray()) { self::$cache[$tpl['filename']] = $tpl; } } /** * Fluent interface-compatible constructor */ public static function fetch() { $obj = new ReflectionClass(__CLASS__); $args = func_get_args(); return $obj->newInstanceArgs($args); } /** * Constructor * * @param string File name */ public function __construct($name) { $this->name = $name; $this->path = self::_path($name); // checks to see if the template has been cached if (isset(self::$cache[$this->path])) { if (!self::$dbCacheTable || filemtime($this->path) <= self::$cache[$this->path]['timestamp']) { $this->template = self::$cache[$this->path]['template']; return; } } // it hasn't been cached if (!is_file($this->path) || !is_readable($this->path)) { throw new Exception("Could not load the template {$this->path}"); } $this->template = $this->_parseTemplate(file_get_contents($this->path)); self::$cache[$this->path]['template'] = $this->template; // store the template in the database if (self::$dbCacheTable) { BSApp::$db->query("REPLACE INTO " . self::$dbCacheTable . " SET template = '" . BSApp::$db->escapeString($this->template) . "', timestamp = " . TIMENOW . ", filename = '" . $this->path . "'"); self::$cache[$this->path]['time'] = TIMENOW; } } /** * Evaluates and returns the template. This is equivalent to calling: * $tpl->evaluate()->getTemplate() * * @return string */ public function __toString() { return $this->evaluate()->getTemplate(); } /** * Returns the template data * * @return string Final template data */ public function getTemplate() { return $this->template; } /** * This function globalizes/extracts the assigned variables and then * returns the output buffer * * @param string Unevaluated template * * @return fluent interface */ public function evaluate() { extract($this->vars); extract(self::$globalVars); ob_start(); $this->template = str_replace(array('$this->', 'self::'), 'null', $this->template); // don't want internal access coming from a template $this->template = '?>' . $this->template; $test = eval($this->template); $output = ob_get_clean(); if ($output === false) { throw new Exception('A parse error was encountered while evaluating the template'); } $this->template = $output; return $this; } /** * Output a template fully compiled to the browser */ public function flush() { ob_start(); if (empty($this->template)) { throw new Exception('There is no output to print'); } echo $this->template; } /** * Returns the debug block * * @return string */ public static function get_debug_block() { if (!BSApp::get_debug()) { return; } $debugBlock = "\n
Executed in " . round(BSFunctions::fetch_microtime_diff('0 ' . $_SERVER['REQUEST_TIME']), 10) . ' seconds
'; $debugBlock .= "\n
" . BSApp::get_debug_list() . "
"; if (BSApp::$db) { $queries = BSApp::$db->getHistory(); $debugBlock .= "
\n" . '' . "\n\t" . ''; foreach ($queries as $query) { $debugBlock .= "\n\t"; $debugBlock .= "\n\t\t\n\t"; } $debugBlock .= "\n
Query Debug
"; $debugBlock .= "\n\t\t\t$query[query]\n\n\t\t\t
($query[time])
\n\n\t\t
\n\n\n"; } return $debugBlock; } /** * A wrapper for all the parsing functions and compiling functins * * @param string Unparsed template data * * @return string Parsed template data */ protected function _parseTemplate($template) { if (function_exists(self::$preParseHook)) { $template = call_user_func(self::$preParseHook, $template, $this); } $template = $this->_parseTokens($template); return $template; } /** * Parses tokens <% %> * * @param string Template data * * @return string Parsed template data */ protected function _parseTokens($template) { $stack = array(); $tokens = array(); for ($i = 0; $i < strlen($template); $i++) { // opening tag if ($template[$i] == '<' && $template[$i + 1] == '%') { array_push($stack, $i); } // closing tag else if ($template[$i] == '%' && $template[$i + 1] == '>') { // there's no stack, so it's a bad template if (sizeof($stack) == 0) { throw new Exception('Malformed template data: unexpected closing substitution tag'); } // we're good and nested else if (sizeof($stack) == 1) { $open = array_pop($stack); $echo = ($template[$open + 2] == '-' ? 'echo ' : ''); $replace = ''; $template = substr_replace($template, $replace, $open, ($i + 2) - $open); } // just pop it off else { array_pop($stack); } // end else } // end if } // end for return $template; } /** * Returns the full path of a template given a name * * @param string Template name * * @return string Template path */ protected static function _path($name) { return sprintf(self::$templatePath, $name); } } ?>