]>
src.bluestatic.org Git - isso.git/blob - Template.php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework
5 || # Copyright (c)2005-2008 Blue Static
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version 2 of the License.
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
23 * Database-Driven Template System (template.php)
28 require_once(ISSO
. '/Functions.php');
31 * File-Based Template System
33 * This framework merely replaces the template loading functions with
34 * file-system based ones. It has an optional caching system in which
35 * template data will remain stored in the database as long as the filesystem
36 * file is modified. To do this, pass a table name to setDatabaseCache() and make sure
37 * there's a DB module that has access to a table with this schema:
39 * CREATE TABLE template (filename VARCHAR (250) NOT NULL, template TEXT NOT NULL, timestamp INT NOT NULL);
42 * @copyright Copyright (c)2005 - 2008, Blue Static
49 * The name of a function that is called before template parsing of phrases and conditionals occurs
52 public static $preParseHook = ':undefined:';
55 * The database table name for the template cache
58 public static $dbCacheTable = null;
61 * The name of the function phrases are fetched with
64 public static $langcall = 'gettext';
67 * The template path pattern; for instance, this could be: ./templates/%s.tpl
70 public static $templatePath = '%s';
73 * Array of pre-compiled templates that are stored for optimization
76 protected static $cache = array();
79 * The name of the function phrases are sprintf() parsed with
82 public static $langconst = 'sprintf';
85 * Template variables to populate
88 public $vars = array();
94 public static $globalVars = array();
97 * The file name of the template
109 * Takes an array of template names, loads them, and then stores a
110 * parsed version for optimum speed.
112 * @param array List of template names to be cached
114 public static function cache($namearray)
116 if (!self
::$dbCacheTable)
118 return; // there's no point in pre-caching file templates
121 $cache = BSApp
::$db->query("SELECT * FROM " . self
::$dbCacheTable . " WHERE filename IN ('" . implode("', '", $namearray) . "')");
122 while ($tpl = $cache->fetchArray())
124 self
::$cache[$tpl['filename']] = $tpl;
129 * Fluent interface-compatible constructor
131 public static function fetch()
133 $obj = new ReflectionClass(__CLASS__
);
134 $args = func_get_args();
135 return $obj->newInstanceArgs($args);
141 * @param string File name
143 public function __construct($path)
147 // checks to see if the template has been cached
148 if (isset(self
::$cache[$this->file
]))
150 if (!self
::$dbCacheTable || filemtime(sprintf(self
::$templatePath, $this->file
)) <= self
::$cache[$this->file
]['timestamp'])
152 $this->template
= self
::$cache[$this->file
]['template'];
157 // it hasn't been cached
158 $path = sprintf(self
::$templatePath, $this->file
);
159 if (!is_file($path) || !is_readable($path))
161 throw new Exception("Could not load the template $path");
163 $this->template = $this->_parseTemplate(file_get_contents($path));
164 self::$cache[$this->file]['template'] = $this->template;
166 // store the template in the database
167 if (self::$dbCacheTable)
169 BSApp::$db->query("REPLACE INTO
" . self::$dbCacheTable . " SET template
= '" . BSApp::$db->escapeString($this->template) . "', timestamp
= " . TIMENOW . ", filename
= '" . $this->file . "'");
170 self::$cache[$this->file]['time'] = TIMENOW;
175 * Returns the template data
177 * @return string Final template data
179 public function getTemplate()
181 return $this->template;
185 * This function globalizes/extracts the assigned variables and then
186 * returns the output buffer
188 * @param string Unevaluated template
190 * @return fluent interface
192 public function evaluate()
194 extract($this->vars);
195 extract(self::$globalVars);
198 $this->template = str_replace(array('$this->', 'self::'), 'null', $this->template); // don't want internal access coming from a template
199 $this->template = '?>' . $this->template;
200 $test = eval($this->template);
201 $output = ob_get_clean();
202 if ($output === false)
204 throw new Exception('A parse error was encountered while evaluating the template');
207 $this->template = $output;
213 * Output a template fully compiled to the browser
215 public function flush()
219 if (empty($this->template))
221 throw new Exception('There is no output to print');
224 $template = $this->template;
227 if (BSApp::get_debug() && strpos($template, '</body>') !== false)
229 $debugBlock .= "\n
<div align
=\"center\"
>Executed in
" . round(BSFunctions::fetch_microtime_diff('0 ' . $_SERVER['REQUEST_TIME']), 10) . ' seconds</div>';
230 $debugBlock .= "\n
<br
/><div align
=\"center\"
>" . BSApp::get_debug_list() . "</div
>";
234 $queries = BSApp::$db->getHistory();
236 $debugBlock .= "<br
/>\n" . '<table cellpadding="4" cellspacing="1" border="0" align="center
" width="30%
" style="background
-color
: rgb(60, 60, 60); color
: white
">' . "\n\t
" . '<tr><td><strong>Query Debug</strong></td></tr>';
238 foreach ($queries as $query)
240 $debugBlock .= "\n\t
<tr style
=\"background
-color
: rgb(230, 230, 230); color
: black\"
>";
241 $debugBlock .= "\n\t\t
<td
>";
242 $debugBlock .= "\n\t\t\t
$query[query
]\n\n\t\t\t<div style
=\"font
-size
: 9px
;\">($query[time
])</div
>\n<!--\n$query[trace
]\n-->\n\t\t</td
>\n\t</tr
>";
245 $debugBlock .= "\n
</table
>\n\n\n";
248 $template = str_replace('</body>', $debugBlock . '</body>', $template);
255 * A wrapper for all the parsing functions and compiling functins
257 * @param string Unparsed template data
259 * @return string Parsed template data
261 protected function _parseTemplate($template)
263 if (function_exists(self::$preParseHook))
265 $template = call_user_func(self::$preParseHook, $template, $this);
268 $template = $this->_parseTokens($template);
273 * Parses tokens <% %>
275 * @param string Template data
277 * @return string Parsed template data
279 protected function _parseTokens($template)
284 for ($i = 0; $i < strlen($template); $i++)
287 if ($template[$i] == '<' && $template[$i + 1] == '%')
289 array_push($stack, $i);
292 else if ($template[$i] == '%' && $template[$i + 1] == '>')
294 // there's no stack, so it's a bad template
295 if (sizeof($stack) == 0)
297 throw new Exception('Malformed template data: unexpected closing substitution tag');
299 // we're good and nested
300 else if (sizeof($stack) == 1)
302 $open = array_pop($stack);
303 $echo = ($template[$open + 2] == '-' ? 'echo ' : '');
304 $replace = '<?php ' . $echo . BSFunctions::substring($template, $open + ($echo ? 3 : 2), $i) . ' ?>';
305 $template = substr_replace($template, $replace, $open, ($i + 2) - $open);