r66: Moving all DB stuff to be handled by ISSO. Working with our one big $bugsys...
[bugdar.git] / includes / functions_template.php
1 <?php
2 /*=====================================================================*\
3 || ################################################################### ||
4 || # BugStrike [#]version[#]
5 || # --------------------------------------------------------------- # ||
6 || # Copyright ©2002-[#]year[#] by Iris Studios, Inc. All Rights Reserved. # ||
7 || # This file may not be reproduced in any way without permission. # ||
8 || # --------------------------------------------------------------- # ||
9 || # User License Agreement at http://www.iris-studios.com/license/ # ||
10 || ################################################################### ||
11 \*=====================================================================*/
12
13 class Template
14 {
15 var $cache = array();
16 var $usage = array();
17 var $uncached = array();
18
19 var $doneflush = false;
20
21 // ###################### Start Template::cache ######################
22 function cache($namearray)
23 {
24 if (sizeof($this->cache) > 0)
25 {
26 user_error('You cannot Template::cache() more than once per initialization', E_USER_WARNING);
27 }
28 else
29 {
30 foreach ($namearray AS $name)
31 {
32 $template = $this->_load($name);
33 $template = $this->_parse($template);
34 $this->cache["$name"] = $template;
35 }
36 }
37 }
38
39 // ###################### Start Template::fetch ######################
40 function fetch($name)
41 {
42 if (isset($this->cache["$name"]))
43 {
44 $template = $this->cache["$name"];
45 }
46 else
47 {
48 $this->uncached[] = $name;
49 $template = $this->_load($name);
50 $template = $this->_parse($template);
51 }
52
53 $this->usage["$name"]++;
54
55 return $template;
56 }
57
58 // ###################### Start Template::flush ######################
59 function flush($template)
60 {
61 global $db;
62
63 ob_start();
64
65 if (empty($template))
66 {
67 user_error('Template::flush() produced no output', E_USER_WARNING);
68 exit;
69 }
70
71 if (DEVDEBUG AND $_GET['query'])
72 {
73 if (is_array($db->query_history))
74 {
75 echo '<pre>';
76 foreach ($db->query_history AS $query)
77 {
78 echo $query . "\n\n<hr />\n\n";
79 }
80 echo '</pre>';
81 }
82 exit;
83 }
84
85 if ($this->doneflush)
86 {
87 user_error('You cannot Template::flush() more than once per initialization', E_USER_WARNING);
88 exit;
89 }
90
91 if (DEVDEBUG)
92 {
93 foreach ($this->usage AS $name => $count)
94 {
95 $optlist[] = '<option>' . iff($this->uncached["$name"], ' -- [UNCACHED] ') . "$name ($count)</option>";
96 }
97
98 $debug .= "\r<hr /><br />\r<table cellpadding=\"4\" cellspacing=\"1\" border=\"0\" align=\"center\" width=\"99%\" class=\"tborder\">\r<tr>";
99 $debug .= "\r\t<td width=\"33%\" align=\"center\" class=\"panelback\" style=\"text-align:center\">" . 'construct_debug_info_list()' . "</td>\r\t<td width=\"33%\" align=\"center\" class=\"panelback\" style=\"text-align:center\">$revision</td>";
100 $debug .= "\r\t<td width=\"33%\" align=\"center\" class=\"panelback\" style=\"text-align:center\"><a href=\"" . SCRIPT_URI . iff(strpos(SCRIPT_URI, '?') !== false, '&amp;query=1', '?query=1') . "\">Total queries used: " . sizeof($db->query_history) . "</a>";
101 $debug .= "</td>\r</tr>\r<tr>\r\t<td align=\"center\" class=\"panelback\" style=\"text-align:center\" colspan=\"3\">";
102 $debug .= "\r" . iff(is_array($this->uncached), sizeof($uncached) . " Uncached Template(s)\r<br />\r") . "<select>\r\t<option>TEMPLATE USAGE</option>\r\t" . implode("\r\t", $optlist) . "\r</select>\r</td></tr></table><br />";
103
104 $template = str_replace('</body>', "\r\r<!-- dev debug -->$debug\r<!-- / dev debug -->\r\r</body>", $template);
105 }
106
107 print(stripslashes($template));
108 }
109
110 // ###################### Start Template::_load ######################
111 function _load($name)
112 {
113 global $bugsys;
114
115 if (($template = @file_get_contents("{$bugsys->options['ts_includepath']}$name.tpl")) !== false)
116 {
117 return $template;
118 }
119 else
120 {
121 echo "could not load template file {$bugsys->options['ts_includepath']}$name.tpl";
122 exit;
123 }
124 }
125
126 // ###################### Start Template::_parse #####################
127 function _parse($template)
128 {
129 $template = stripslashes($template);
130 $template = str_replace('"', '\"', $template);
131 $template = $this->_parse_phrases($template);
132 $template = $this->_parse_conditionals($template);
133 return $template;
134 }
135
136 // ################## Start Template::_parse_phrases #################
137 function _parse_phrases($template)
138 {
139 $tag_start = '<lang ';
140 $tag_start_end = '">';
141 $tag_end = '</lang>';
142
143 $location_start = -1;
144 $location_end = -1;
145
146 // Process the empty phrase objects -- do this now so we don't have to worry about it when we're parsing later
147 $template = preg_replace('#\{lang\.(.*?)\}#i', '" . fetch_phrase(\'$1\') . "', $template);
148
149 while (1)
150 {
151 // Find the start language object tag
152 $location_start = strpos($template, $tag_start, $location_end + 1);
153 if ($location_start === false)
154 {
155 break;
156 }
157
158 // Find the end tag
159 $location_end = strpos($template, $tag_end, $location_end + strlen($tag_end));
160 if ($location_end === false)
161 {
162 break;
163 }
164
165 // Extract the language object
166 $phrase_bunch = substr($template, $location_start, ($location_end + strlen($tag_end)) - $location_start);
167
168 // Find the close to the opening <lang>
169 $close_of_open = strpos($phrase_bunch, $tag_start_end);
170 if ($close_of_open === false)
171 {
172 break;
173 }
174
175 // Extract the opening tag so it can be parsed
176 $init_tag = substr($phrase_bunch, 0, ($close_of_open + strlen($tag_start_end)));
177 $init_tag = str_replace($tag_start, '', $init_tag);
178 $init_tag = substr($init_tag, 0, strlen($init_tag) - 1);
179
180 // Get the args out of the tag
181 $args = preg_split('#([0-9].*?)=#', $init_tag);
182 foreach ($args AS $arg)
183 {
184 if ($arg AND $arg != ' ')
185 {
186 $arg = trim($arg);
187 $arg = substr($arg, 2);
188 $arg = substr($arg, 0, strlen($arg) - 2);
189 $arglist[] = $arg;
190 }
191 }
192
193 // Just get the phrase name
194 $phrase_name = preg_replace('#<lang(.*?)>(.*?)</lang>#i', '$2', $phrase_bunch);
195
196 // Wrap the parsed data into the build function
197 $function_wrap = '" . construct_phrase(\'' . $phrase_name . '\', "' . implode('", "', $arglist) . '") . "';
198
199 // Replace the fully-parsed string back into the template
200 $template = substr_replace($template, $function_wrap, $location_start, $location_end + strlen($tag_end) - $location_start);
201
202 unset($arglist);
203 }
204
205 return $template;
206 }
207
208 // ############### Start Template::_parse_conditionals ###############
209 function _parse_conditionals($template)
210 {
211 // Tag locations
212 $location_start = -1;
213 $location_end = -1;
214
215 // Tag data
216 $tag_start = '<if condition=\\"';
217 $tag_start_end = '\\">';
218 $tag_else = '<else />';
219 $tag_end = '</if>';
220
221 while (1)
222 {
223 // Finds the start tag: starts looking through the haystack one position
224 // after the old startpoint
225 $location_start = strpos($template, $tag_start, $location_start + 1);
226 if ($location_start === false)
227 {
228 break;
229 }
230
231 // Finds the end tag: starts looking through the haystack after the old end
232 // tag
233 $location_end = strpos($template, $tag_end, $location_end + strlen($tag_end));
234 if ($location_end === false)
235 {
236 break;
237 }
238
239 // Split the template expression out of the template data
240 $expression = substr($template, $location_start, ($location_end + strlen($tag_end)) - $location_start);
241
242 // If we have a nested expression, work it out by setting
243 // the search counters to be one and two after the current
244 // start point
245 if (substr_count($expression, $tag_end) > 1)
246 {
247 $location_start = $location_start + 1;
248 $location_end = $location_start + 2;
249 }
250
251 // Strip out the opening '<if expression="' part of the tag
252 $shell_removed = substr($expression, strlen($tag_start));
253
254 // Get the position of the end of the '<if epxression="' tag
255 $shell_end = strpos($shell_removed, $tag_start_end);
256
257 // Take the condition out of the mix
258 $expression_condition = stripslashes(substr($shell_removed, 0, $shell_end));
259
260 // Now that we've safely stored the condition, parse out the rest of the data
261 $shell_removed = substr($shell_removed, $shell_end + strlen($tag_start_end));
262
263 // Find the end tag and then take out the iftrue data
264 $parsed = str_replace($tag_end, '', $shell_removed);
265
266 // Do we have an $tag_else
267 $location_else = strpos($parsed, $tag_else);
268 if ($location_else !== false)
269 {
270 $data = explode($tag_else, $parsed);
271
272 // um... wtf?
273 if (count($data) > 2)
274 {
275 user_error('Multiple else statements encountered while parsing conditionals in template', E_USER_WARNING);
276 }
277
278 // Set the data
279 $iftrue = $data[0];
280 $iffalse = $data[1];
281 }
282 // Nope, reassign variables
283 else
284 {
285 $iftrue = $parsed;
286 $iffalse = null;
287 }
288
289 // Put the condition and iftrue in the iff() function
290 $parsed_expression = '" . iff(' . stripslashes($expression_condition) . ',"' . $iftrue . '","' . $iffalse . '") . "';
291
292 // Parse the iff()'d expression back into the template data
293 $template = substr_replace($template, $parsed_expression, $location_start, $location_end + strlen($tag_end) - $location_start);
294 }
295
296 // Repeat this process until it can't find any more
297 // expressions, then send back the parsed template data
298 // for final output
299 return $template;
300 }
301 }
302
303 /*=====================================================================*\
304 || ###################################################################
305 || # $HeadURL$
306 || # $Id$
307 || ###################################################################
308 \*=====================================================================*/
309 ?>