1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file has functions dealing with loading and precessing template files. |
5
|
|
|
* |
6
|
|
|
* @name ElkArte Forum |
7
|
|
|
* @copyright ElkArte Forum contributors |
8
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause |
9
|
|
|
* |
10
|
|
|
* This file contains code covered by: |
11
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
12
|
|
|
* license: BSD, See included LICENSE.TXT for terms and conditions. |
13
|
|
|
* |
14
|
|
|
* @version 1.1 Release Candidate 1 |
15
|
|
|
* |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Class Templates |
20
|
|
|
* |
21
|
|
|
* This class loads and processes template files and sheets. |
22
|
|
|
*/ |
23
|
|
|
class Templates |
24
|
|
|
{ |
25
|
|
|
protected static $instance = null; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Template directory's that we will be searching for the sheets |
29
|
|
|
* @var array |
30
|
|
|
*/ |
31
|
|
|
public $dirs = array(); |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Template sheets that have not loaded |
35
|
|
|
* @var array |
36
|
|
|
*/ |
37
|
|
|
protected $delayed = array(); |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Holds the file that are in the include list |
41
|
|
|
* @var array |
42
|
|
|
*/ |
43
|
|
|
protected $templates = array(); |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Tracks if the default index.css has been loaded |
47
|
|
|
* @var bool |
48
|
|
|
*/ |
49
|
|
|
protected $default_loaded = false; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Templates constructor. |
53
|
|
|
*/ |
54
|
|
|
protected function __construct() |
55
|
|
|
{ |
56
|
|
|
// We want to be able to figure out any errors... |
57
|
|
|
@ini_set('track_errors', '1'); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Load a template - if the theme doesn't include it, use the default. |
62
|
|
|
* |
63
|
|
|
* What it does: |
64
|
|
|
* |
65
|
|
|
* - Loads a template file with the name template_name from the current, default, or base theme. |
66
|
|
|
* - Detects a wrong default theme directory and tries to work around it. |
67
|
|
|
* - Can be used to only load style sheets by using false as the template name |
68
|
|
|
* loading of style sheets with this function is deprecated, use loadCSSFile instead |
69
|
|
|
* - If $this->dirs is empty, it delays the loading of the template |
70
|
|
|
* |
71
|
|
|
* @uses $this->requireTemplate() to actually load the file. |
72
|
|
|
* |
73
|
|
|
* @param string|false $template_name |
74
|
|
|
* @param string[]|string $style_sheets any style sheets to load with the template |
75
|
|
|
* @param bool $fatal = true if fatal is true, dies with an error message if the template cannot be found |
76
|
|
|
* |
77
|
|
|
* @return boolean|null |
78
|
|
|
* @throws Elk_Exception |
79
|
|
|
*/ |
80
|
17 |
|
public function load($template_name, $style_sheets = array(), $fatal = true) |
81
|
|
|
{ |
82
|
|
|
// If we don't know yet the default theme directory, let's wait a bit. |
83
|
17 |
|
if (empty($this->dirs)) |
84
|
17 |
|
{ |
85
|
|
|
$this->delayed[] = array( |
86
|
|
|
$template_name, |
87
|
|
|
$style_sheets, |
88
|
|
|
$fatal |
89
|
|
|
); |
90
|
|
|
|
91
|
|
|
return; |
92
|
|
|
} |
93
|
|
|
// If instead we know the default theme directory and we have delayed something, it's time to process |
94
|
17 |
|
elseif (!empty($this->delayed)) |
95
|
|
|
{ |
96
|
|
|
foreach ($this->delayed as $val) |
97
|
|
|
{ |
98
|
|
|
$this->requireTemplate($val[0], $val[1], $val[2]); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
// Forget about them (load them only once) |
102
|
|
|
$this->delayed = array(); |
103
|
|
|
} |
104
|
|
|
|
105
|
17 |
|
$this->requireTemplate($template_name, $style_sheets, $fatal); |
106
|
17 |
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* <b>Internal function! Do not use it, use loadTemplate instead</b> |
110
|
|
|
* |
111
|
|
|
* What it does: |
112
|
|
|
* |
113
|
|
|
* - Loads a template file with the name template_name from the current, default, or base theme. |
114
|
|
|
* - Detects a wrong default theme directory and tries to work around it. |
115
|
|
|
* - Can be used to only load style sheets by using false as the template name |
116
|
|
|
* loading of style sheets with this function is deprecated, use loadCSSFile instead |
117
|
|
|
* |
118
|
|
|
* @uses $this->templateInclude() to include the file. |
119
|
|
|
* |
120
|
|
|
* @param string|false $template_name |
121
|
|
|
* @param string[]|string $style_sheets any style sheets to load with the template |
122
|
|
|
* @param bool $fatal = true if fatal is true, dies with an error message if the template cannot be found |
123
|
|
|
* |
124
|
|
|
* @return bool|null |
125
|
|
|
* @throws Elk_Exception theme_template_error |
126
|
|
|
*/ |
127
|
17 |
|
protected function requireTemplate($template_name, $style_sheets, $fatal) |
128
|
|
|
{ |
129
|
17 |
|
global $context, $settings, $txt, $scripturl, $db_show_debug; |
130
|
|
|
|
131
|
17 |
|
if (!is_array($style_sheets)) |
132
|
17 |
|
{ |
133
|
|
|
$style_sheets = array($style_sheets); |
134
|
|
|
} |
135
|
|
|
|
136
|
17 |
|
if ($this->default_loaded === false) |
137
|
17 |
|
{ |
138
|
|
|
loadCSSFile('index.css'); |
139
|
|
|
$this->default_loaded = true; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
// Any specific template style sheets to load? |
143
|
17 |
|
if (!empty($style_sheets)) |
144
|
17 |
|
{ |
145
|
|
|
trigger_error('Use of loadTemplate to add style sheets to the head is deprecated.', E_USER_DEPRECATED); |
146
|
|
|
$sheets = array(); |
147
|
|
|
foreach ($style_sheets as $sheet) |
148
|
|
|
{ |
149
|
|
|
$sheets[] = stripos('.css', $sheet) !== false ? $sheet : $sheet . '.css'; |
150
|
|
|
if ($sheet == 'admin' && !empty($context['theme_variant'])) |
151
|
|
|
{ |
152
|
|
|
$sheets[] = $context['theme_variant'] . '/admin' . $context['theme_variant'] . '.css'; |
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
loadCSSFile($sheets); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
// No template to load? |
160
|
17 |
|
if ($template_name === false) |
161
|
17 |
|
{ |
162
|
|
|
return true; |
163
|
|
|
} |
164
|
|
|
|
165
|
17 |
|
$loaded = false; |
166
|
17 |
|
$template_dir = ''; |
167
|
17 |
|
foreach ($this->dirs as $template_dir) |
168
|
|
|
{ |
169
|
17 |
|
if (file_exists($template_dir . '/' . $template_name . '.template.php')) |
170
|
17 |
|
{ |
171
|
17 |
|
$loaded = true; |
172
|
17 |
|
$this->templateInclude($template_dir . '/' . $template_name . '.template.php', true); |
173
|
17 |
|
break; |
174
|
|
|
} |
175
|
17 |
|
} |
176
|
|
|
|
177
|
|
|
if ($loaded) |
178
|
17 |
|
{ |
179
|
17 |
|
if ($db_show_debug === true) |
180
|
17 |
|
{ |
181
|
|
|
Debug::instance()->add('templates', $template_name . ' (' . basename($template_dir) . ')'); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
// If they have specified an initialization function for this template, go ahead and call it now. |
185
|
17 |
|
if (function_exists('template_' . $template_name . '_init')) |
186
|
17 |
|
{ |
187
|
3 |
|
call_user_func('template_' . $template_name . '_init'); |
188
|
3 |
|
} |
189
|
17 |
|
} |
190
|
|
|
// Hmmm... doesn't exist?! I don't suppose the directory is wrong, is it? |
191
|
|
|
elseif (!file_exists($settings['default_theme_dir']) && file_exists(BOARDDIR . '/themes/default')) |
192
|
|
|
{ |
193
|
|
|
$settings['default_theme_dir'] = BOARDDIR . '/themes/default'; |
194
|
|
|
$this->addDirectory($settings['default_theme_dir']); |
195
|
|
|
|
196
|
|
|
if (!empty($context['user']['is_admin']) && !isset($_GET['th'])) |
197
|
|
|
{ |
198
|
|
|
loadLanguage('Errors'); |
199
|
|
|
|
200
|
|
|
if (!isset($context['security_controls_files']['title'])) |
201
|
|
|
{ |
202
|
|
|
$context['security_controls_files']['title'] = $txt['generic_warning']; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
$context['security_controls_files']['errors']['theme_dir'] = '<a href="' . $scripturl . '?action=admin;area=theme;sa=list;th=1;' . $context['session_var'] . '=' . $context['session_id'] . '">' . $txt['theme_dir_wrong'] . '</a>'; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
loadTemplate($template_name); |
209
|
|
|
} |
210
|
|
|
// Cause an error otherwise. |
211
|
|
|
elseif ($template_name !== 'Errors' && $template_name !== 'index' && $fatal) |
212
|
|
|
{ |
213
|
|
|
throw new Elk_Exception('theme_template_error', 'template', array((string) $template_name)); |
214
|
|
|
} |
215
|
|
View Code Duplication |
elseif ($fatal) |
216
|
|
|
{ |
217
|
|
|
die(Errors::instance()->log_error(sprintf(isset($txt['theme_template_error']) ? $txt['theme_template_error'] : 'Unable to load themes/default/%s.template.php!', (string) $template_name), 'template')); |
|
|
|
|
218
|
|
|
} |
219
|
|
|
else |
220
|
|
|
{ |
221
|
|
|
return false; |
222
|
|
|
} |
223
|
|
|
|
224
|
17 |
|
return true; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Load the template/language file using eval or require? (with eval we can show an error message!) |
229
|
|
|
* |
230
|
|
|
* What it does: |
231
|
|
|
* |
232
|
|
|
* - Loads the template or language file specified by filename. |
233
|
|
|
* - Uses eval unless disableTemplateEval is enabled. |
234
|
|
|
* - Outputs a parse error if the file did not exist or contained errors. |
235
|
|
|
* - Attempts to detect the error and line, and show detailed information. |
236
|
|
|
* |
237
|
|
|
* @param string $filename |
238
|
|
|
* @param bool $once = false, if true only includes the file once (like include_once) |
239
|
|
|
*/ |
240
|
27 |
|
public function templateInclude($filename, $once = false) |
241
|
|
|
{ |
242
|
|
|
// I know this looks weird but this is used to include $txt files. If the parent doesn't declare them global |
243
|
|
|
// the scope will be local to this function. IOW, don't remove this line! |
244
|
27 |
|
global $txt; |
245
|
|
|
|
246
|
|
|
// Don't include the file more than once, if $once is true. |
247
|
27 |
|
if ($once && in_array($filename, $this->templates)) |
248
|
27 |
|
{ |
249
|
16 |
|
return; |
250
|
|
|
} |
251
|
|
|
// Add this file to the include list, whether $once is true or not. |
252
|
|
|
else |
253
|
|
|
{ |
254
|
18 |
|
$this->templates[] = $filename; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
// Load it if we find it |
258
|
18 |
|
$file_found = file_exists($filename); |
259
|
|
|
|
260
|
18 |
|
if ($once && $file_found) |
261
|
18 |
|
{ |
262
|
4 |
|
require_once($filename); |
263
|
4 |
|
} |
264
|
17 |
|
elseif ($file_found) |
265
|
|
|
{ |
266
|
17 |
|
require($filename); |
267
|
17 |
|
} |
268
|
|
|
|
269
|
18 |
|
if ($file_found !== true) |
270
|
18 |
|
{ |
271
|
|
|
$this->templateNotFound($filename); |
272
|
|
|
} |
273
|
18 |
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Displays an error when a template is not found or has syntax errors preventing its loading |
277
|
|
|
* |
278
|
|
|
* @param string $filename |
279
|
|
|
*/ |
280
|
|
|
protected function templateNotFound($filename) |
281
|
|
|
{ |
282
|
|
|
global $context, $txt, $scripturl, $modSettings, $boardurl; |
283
|
|
|
global $maintenance, $mtitle, $mmessage; |
284
|
|
|
|
285
|
|
|
obStart(!empty($modSettings['enableCompressedOutput'])); |
286
|
|
|
|
287
|
|
|
// Don't cache error pages!! |
288
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
289
|
|
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); |
290
|
|
|
header('Cache-Control: no-cache'); |
291
|
|
|
|
292
|
|
|
if (!isset($txt['template_parse_error'])) |
293
|
|
|
{ |
294
|
|
|
$txt['template_parse_error'] = 'Template Parse Error!'; |
295
|
|
|
$txt['template_parse_error_message'] = 'It seems something has gone sour on the forum with the template system. This problem should only be temporary, so please come back later and try again. If you continue to see this message, please contact the administrator.<br /><br />You can also try <a href="javascript:location.reload();">refreshing this page</a>.'; |
296
|
|
|
$txt['template_parse_error_details'] = 'There was a problem loading the <span style="font-family: monospace;"><strong>%1$s</strong></span> template or language file. Please check the syntax and try again - remember, single quotes (<span style="font-family: monospace;">\'</span>) often have to be escaped with a slash (<span style="font-family: monospace;">\\</span>). To see more specific error information from PHP, try <a href="%2$s%1$s" class="extern">accessing the file directly</a>.<br /><br />You may want to try to <a href="javascript:location.reload();">refresh this page</a> or <a href="%3$s">use the default theme</a>.'; |
297
|
|
|
$txt['template_parse_undefined'] = 'An undefined error occurred during the parsing of this template'; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
// First, let's get the doctype and language information out of the way. |
301
|
|
|
echo '<!DOCTYPE html> |
302
|
|
|
<html ', !empty($context['right_to_left']) ? 'dir="rtl"' : '', '> |
303
|
|
|
<head> |
304
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'; |
305
|
|
|
|
306
|
|
|
if (!empty($maintenance) && !allowedTo('admin_forum')) |
307
|
|
|
{ |
308
|
|
|
echo ' |
309
|
|
|
<title>', $mtitle, '</title> |
310
|
|
|
</head> |
311
|
|
|
<body> |
312
|
|
|
<h3>', $mtitle, '</h3> |
313
|
|
|
', $mmessage, ' |
314
|
|
|
</body> |
315
|
|
|
</html>'; |
316
|
|
|
} |
317
|
|
|
elseif (!allowedTo('admin_forum')) |
318
|
|
|
{ |
319
|
|
|
echo ' |
320
|
|
|
<title>', $txt['template_parse_error'], '</title> |
321
|
|
|
</head> |
322
|
|
|
<body> |
323
|
|
|
<h3>', $txt['template_parse_error'], '</h3> |
324
|
|
|
', $txt['template_parse_error_message'], ' |
325
|
|
|
</body> |
326
|
|
|
</html>'; |
327
|
|
|
} |
328
|
|
|
else |
329
|
|
|
{ |
330
|
|
|
require_once(SUBSDIR . '/Package.subs.php'); |
331
|
|
|
|
332
|
|
|
$error = fetch_web_data($boardurl . strtr($filename, array(BOARDDIR => '', strtr(BOARDDIR, '\\', '/') => ''))); |
333
|
|
|
if (empty($error) && ini_get('track_errors') && !empty($php_errormsg)) |
334
|
|
|
{ |
335
|
|
|
$error = $php_errormsg; |
336
|
|
|
} |
337
|
|
|
elseif (empty($error)) |
338
|
|
|
{ |
339
|
|
|
$error = $txt['template_parse_undefined']; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
$error = strtr($error, array('<b>' => '<strong>', '</b>' => '</strong>')); |
343
|
|
|
|
344
|
|
|
echo ' |
345
|
|
|
<title>', $txt['template_parse_error'], '</title> |
346
|
|
|
</head> |
347
|
|
|
<body> |
348
|
|
|
<h3>', $txt['template_parse_error'], '</h3> |
349
|
|
|
', sprintf($txt['template_parse_error_details'], strtr($filename, array(BOARDDIR => '', strtr(BOARDDIR, '\\', '/') => '')), $boardurl, $scripturl . '?theme=1'); |
350
|
|
|
|
351
|
|
|
if (!empty($error)) |
352
|
|
|
{ |
353
|
|
|
echo ' |
354
|
|
|
<hr /> |
355
|
|
|
|
356
|
|
|
<div style="margin: 0 20px;"><span style="font-family: monospace;">', strtr(strtr($error, array('<strong>' . BOARDDIR => '<strong>...', '<strong>' . strtr(BOARDDIR, '\\', '/') => '<strong>...')), '\\', '/'), '</span></div>'; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
// I know, I know... this is VERY COMPLICATED. Still, it's good. |
360
|
|
|
if (preg_match('~ <strong>(\d+)</strong><br( /)?' . '>$~i', $error, $match) != 0) |
361
|
|
|
{ |
362
|
|
|
$data = file($filename); |
363
|
|
|
$data2 = highlight_php_code(implode('', $data)); |
364
|
|
|
$data2 = preg_split('~\<br( /)?\>~', $data2); |
365
|
|
|
|
366
|
|
|
// Fix the PHP code stuff... |
367
|
|
|
if (!isBrowser('gecko')) |
368
|
|
|
{ |
369
|
|
|
$data2 = str_replace("\t", '<span style="white-space: pre;">' . "\t" . '</span>', $data2); |
370
|
|
|
} |
371
|
|
|
else |
372
|
|
|
{ |
373
|
|
|
$data2 = str_replace('<pre style="display: inline;">' . "\t" . '</pre>', "\t", $data2); |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
// Now we get to work around a bug in PHP where it doesn't escape <br />s! |
377
|
|
|
$j = -1; |
378
|
|
|
foreach ($data as $line) |
379
|
|
|
{ |
380
|
|
|
$j++; |
381
|
|
|
|
382
|
|
|
if (substr_count($line, '<br />') == 0) |
383
|
|
|
{ |
384
|
|
|
continue; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
$n = substr_count($line, '<br />'); |
388
|
|
|
for ($i = 0; $i < $n; $i++) |
389
|
|
|
{ |
390
|
|
|
$data2[$j] .= '<br />' . $data2[$j + $i + 1]; |
391
|
|
|
unset($data2[$j + $i + 1]); |
392
|
|
|
} |
393
|
|
|
$j += $n; |
394
|
|
|
} |
395
|
|
|
$data2 = array_values($data2); |
396
|
|
|
array_unshift($data2, ''); |
397
|
|
|
|
398
|
|
|
echo ' |
399
|
|
|
<div style="margin: 2ex 20px; width: 96%; overflow: auto;"><pre style="margin: 0;">'; |
400
|
|
|
|
401
|
|
|
// Figure out what the color coding was before... |
402
|
|
|
$line = max($match[1] - 9, 1); |
403
|
|
|
$last_line = ''; |
404
|
|
|
for ($line2 = $line - 1; $line2 > 1; $line2--) |
405
|
|
|
{ |
406
|
|
|
if (strpos($data2[$line2], '<') !== false) |
407
|
|
|
{ |
408
|
|
|
if (preg_match('~(<[^/>]+>)[^<]*$~', $data2[$line2], $color_match) != 0) |
409
|
|
|
{ |
410
|
|
|
$last_line = $color_match[1]; |
411
|
|
|
} |
412
|
|
|
break; |
413
|
|
|
} |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
// Show the relevant lines... |
417
|
|
|
for ($n = min($match[1] + 4, count($data2) + 1); $line <= $n; $line++) |
418
|
|
|
{ |
419
|
|
|
if ($line == $match[1]) |
420
|
|
|
{ |
421
|
|
|
echo '</pre><div style="background: #ffb0b5;"><pre style="margin: 0;">'; |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
echo '<span style="color: black;">', sprintf('%' . strlen($n) . 's', $line), ':</span> '; |
425
|
|
|
if (isset($data2[$line]) && $data2[$line] != '') |
426
|
|
|
{ |
427
|
|
|
echo substr($data2[$line], 0, 2) == '</' ? preg_replace('~^</[^>]+>~', '', $data2[$line]) : $last_line . $data2[$line]; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
if (isset($data2[$line]) && preg_match('~(<[^/>]+>)[^<]*$~', $data2[$line], $color_match) != 0) |
431
|
|
|
{ |
432
|
|
|
$last_line = $color_match[1]; |
433
|
|
|
echo '</', substr($last_line, 1, 4), '>'; |
434
|
|
|
} |
435
|
|
|
elseif ($last_line != '' && strpos($data2[$line], '<') !== false) |
436
|
|
|
{ |
437
|
|
|
$last_line = ''; |
438
|
|
|
} |
439
|
|
|
elseif ($last_line != '' && $data2[$line] != '') |
440
|
|
|
{ |
441
|
|
|
echo '</', substr($last_line, 1, 4), '>'; |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
if ($line == $match[1]) |
445
|
|
|
{ |
446
|
|
|
echo '</pre></div><pre style="margin: 0;">'; |
447
|
|
|
} |
448
|
|
|
else |
449
|
|
|
{ |
450
|
|
|
echo "\n"; |
451
|
|
|
} |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
echo '</pre></div>'; |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
echo ' |
458
|
|
|
</body> |
459
|
|
|
</html>'; |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
die; |
|
|
|
|
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
/** |
466
|
|
|
* Load a sub-template. |
467
|
|
|
* |
468
|
|
|
* What it does: |
469
|
|
|
* |
470
|
|
|
* - loads the sub template specified by sub_template_name, which must be in an already-loaded template. |
471
|
|
|
* - if ?debug is in the query string, shows administrators a marker after every sub template |
472
|
|
|
* for debugging purposes. |
473
|
|
|
* |
474
|
|
|
* @todo get rid of reading $_REQUEST directly |
475
|
|
|
* |
476
|
|
|
* @param string $sub_template_name |
477
|
|
|
* @param bool|string $fatal = false, $fatal = true is for templates that |
478
|
|
|
* shouldn't get a 'pretty' error screen 'ignore' to skip |
479
|
|
|
* |
480
|
|
|
* @throws Elk_Exception theme_template_error |
481
|
|
|
*/ |
482
|
|
|
public function loadSubTemplate($sub_template_name, $fatal = false) |
483
|
|
|
{ |
484
|
|
|
global $txt, $db_show_debug; |
485
|
|
|
|
486
|
|
|
if ($sub_template_name === false) |
487
|
|
|
{ |
488
|
|
|
return; |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
if ($db_show_debug === true) |
492
|
|
|
{ |
493
|
|
|
Debug::instance()->add('sub_templates', $sub_template_name); |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
// Figure out what the template function is named. |
497
|
|
|
$theme_function = 'template_' . $sub_template_name; |
498
|
|
|
|
499
|
|
|
if (function_exists($theme_function)) |
500
|
|
|
{ |
501
|
|
|
$this->_templateDebug($sub_template_name, true); |
502
|
|
|
$theme_function(); |
|
|
|
|
503
|
|
|
} |
504
|
|
|
elseif ($fatal === false) |
505
|
|
|
{ |
506
|
|
|
throw new Elk_Exception('theme_template_error', 'template', array((string) $sub_template_name)); |
507
|
|
|
} |
508
|
|
View Code Duplication |
elseif ($fatal !== 'ignore') |
509
|
|
|
{ |
510
|
|
|
die(Errors::instance()->log_error(sprintf(isset($txt['theme_template_error']) ? $txt['theme_template_error'] : 'Unable to load the %s sub template!', (string) $sub_template_name), 'template')); |
|
|
|
|
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
$this->_templateDebug($sub_template_name); |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
/** |
517
|
|
|
* Are we showing debugging for templates? Just make sure not to do it before the doctype... |
518
|
|
|
* |
519
|
|
|
* @param bool $start |
520
|
|
|
* @param string $sub_template_name |
521
|
|
|
*/ |
522
|
|
|
private function _templateDebug($sub_template_name, $start = false) |
523
|
|
|
{ |
524
|
|
|
if (isset($_REQUEST['debug']) && allowedTo('admin_forum') && !in_array($sub_template_name, array('init')) && ob_get_length() > 0 && !isset($_REQUEST['xml']) && !isset($_REQUEST['api'])) |
525
|
|
|
{ |
526
|
|
|
echo ' |
527
|
|
|
<div class="warningbox">---- ', $sub_template_name, ' ', ($start ? 'starts' : 'ends'), ' ----</div>'; |
|
|
|
|
528
|
|
|
} |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
/** |
532
|
|
|
* Reloads the directory stack/queue to ensure they are searched in the proper order |
533
|
|
|
* |
534
|
|
|
* @param array $settings |
535
|
|
|
*/ |
536
|
7 |
|
public function reloadDirectories(array $settings) |
537
|
|
|
{ |
538
|
7 |
|
$this->dirs = array(); |
539
|
|
|
|
540
|
7 |
|
if (!empty($settings['theme_dir'])) |
541
|
7 |
|
{ |
542
|
7 |
|
$this->addDirectory($settings['theme_dir']); |
543
|
7 |
|
} |
544
|
|
|
|
545
|
|
|
// Based on theme (if there is one). |
546
|
7 |
|
if (!empty($settings['base_theme_dir'])) |
547
|
7 |
|
{ |
548
|
|
|
$this->addDirectory($settings['base_theme_dir']); |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
// Lastly the default theme. |
552
|
7 |
|
if ($settings['theme_dir'] !== $settings['default_theme_dir']) |
553
|
7 |
|
{ |
554
|
|
|
$this->addDirectory($settings['default_theme_dir']); |
555
|
|
|
} |
556
|
7 |
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* Add a template directory to the search stack |
560
|
|
|
* |
561
|
|
|
* @param string $dir |
562
|
|
|
* |
563
|
|
|
* @return $this |
564
|
|
|
*/ |
565
|
7 |
|
public function addDirectory($dir) |
566
|
|
|
{ |
567
|
7 |
|
$this->dirs[] = (string) $dir; |
568
|
|
|
|
569
|
7 |
|
return $this; |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
/** |
573
|
|
|
* Sets the directory array in to the class |
574
|
|
|
* |
575
|
|
|
* @param array $dirs |
576
|
|
|
*/ |
577
|
|
|
public function setDirectories(array $dirs) |
578
|
|
|
{ |
579
|
|
|
$this->dirs = $dirs; |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/** |
583
|
|
|
* Returns if theme directory's have been loaded |
584
|
|
|
* |
585
|
|
|
* @return bool |
586
|
|
|
*/ |
587
|
1 |
|
public function hasDirectories() |
588
|
|
|
{ |
589
|
1 |
|
return !empty($this->dirs); |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Return the directory's that have been loaded |
594
|
|
|
* |
595
|
|
|
* @return array |
596
|
|
|
*/ |
597
|
|
|
public function getTemplateDirectories() |
598
|
|
|
{ |
599
|
|
|
return $this->dirs; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
/** |
603
|
|
|
* Return the template sheet stack |
604
|
|
|
* |
605
|
|
|
* @return array |
606
|
|
|
*/ |
607
|
|
|
public function getIncludedTemplates() |
608
|
|
|
{ |
609
|
|
|
return $this->templates; |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* Find and return Templates instance if it exists, |
614
|
|
|
* or create a new instance |
615
|
|
|
* |
616
|
|
|
* @return Templates |
617
|
|
|
*/ |
618
|
27 |
|
public static function instance() |
619
|
|
|
{ |
620
|
27 |
|
if (self::$instance === null) |
621
|
27 |
|
{ |
622
|
|
|
self::$instance = new Templates; |
623
|
|
|
} |
624
|
|
|
|
625
|
27 |
|
return self::$instance; |
626
|
|
|
} |
627
|
|
|
} |
628
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.