Commit | Line | Data |
---|---|---|
2aa91ff2 S |
1 | <?php |
2 | /** | |
3 | * Project: Smarty: the PHP compiling template engine | |
4 | * File: Smarty.class.php | |
ccd27f54 | 5 | * |
2aa91ff2 S |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2.1 of the License, or (at your option) any later version. | |
ccd27f54 | 10 | * |
2aa91ff2 S |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
ccd27f54 | 15 | * |
2aa91ff2 S |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | * For questions, help, comments, discussion, etc., please join the | |
20 | * Smarty mailing list. Send a blank e-mail to | |
21 | * smarty-discussion-subscribe@googlegroups.com | |
22 | * | |
23 | * @link http://www.smarty.net/ | |
ccd27f54 S |
24 | * @copyright 2015 New Digital Group, Inc. |
25 | * @copyright 2015 Uwe Tews | |
2aa91ff2 S |
26 | * @author Monte Ohrt <monte at ohrt dot com> |
27 | * @author Uwe Tews | |
28 | * @author Rodney Rehm | |
29 | * @package Smarty | |
ccd27f54 | 30 | * @version 3.1-DEV |
2aa91ff2 S |
31 | */ |
32 | ||
33 | /** | |
34 | * define shorthand directory separator constant | |
35 | */ | |
36 | if (!defined('DS')) { | |
37 | define('DS', DIRECTORY_SEPARATOR); | |
38 | } | |
39 | ||
40 | /** | |
41 | * set SMARTY_DIR to absolute path to Smarty library files. | |
42 | * Sets SMARTY_DIR only if user application has not already defined it. | |
43 | */ | |
44 | if (!defined('SMARTY_DIR')) { | |
45 | define('SMARTY_DIR', dirname(__FILE__) . DS); | |
46 | } | |
47 | ||
48 | /** | |
49 | * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. | |
50 | * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it. | |
51 | */ | |
52 | if (!defined('SMARTY_SYSPLUGINS_DIR')) { | |
53 | define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS); | |
54 | } | |
55 | if (!defined('SMARTY_PLUGINS_DIR')) { | |
56 | define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS); | |
57 | } | |
58 | if (!defined('SMARTY_MBSTRING')) { | |
ccd27f54 | 59 | define('SMARTY_MBSTRING', function_exists('mb_get_info')); |
2aa91ff2 S |
60 | } |
61 | if (!defined('SMARTY_RESOURCE_CHAR_SET')) { | |
62 | // UTF-8 can only be done properly when mbstring is available! | |
63 | /** | |
64 | * @deprecated in favor of Smarty::$_CHARSET | |
65 | */ | |
66 | define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1'); | |
67 | } | |
68 | if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) { | |
69 | /** | |
70 | * @deprecated in favor of Smarty::$_DATE_FORMAT | |
71 | */ | |
72 | define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y'); | |
73 | } | |
74 | ||
75 | /** | |
ccd27f54 S |
76 | * Try loading the Smmarty_Internal_Data class |
77 | * If we fail we must load Smarty's autoloader. | |
78 | * Otherwise we may have a global autoloader like Composer | |
2aa91ff2 | 79 | */ |
ccd27f54 S |
80 | if (!class_exists('Smarty_Autoloader', false)) { |
81 | if (!class_exists('Smarty_Internal_Data', true)) { | |
82 | require_once 'Autoloader.php'; | |
83 | Smarty_Autoloader::registerBC(); | |
2aa91ff2 | 84 | } |
2aa91ff2 S |
85 | } |
86 | ||
87 | /** | |
88 | * Load always needed external class files | |
89 | */ | |
ccd27f54 S |
90 | |
91 | if (!class_exists('Smarty_Internal_Data', false)) { | |
92 | require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php'; | |
93 | } | |
94 | require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php'; | |
95 | require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php'; | |
96 | require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php'; | |
97 | require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php'; | |
98 | require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php'; | |
2aa91ff2 S |
99 | |
100 | /** | |
101 | * This is the main Smarty class | |
102 | * | |
103 | * @package Smarty | |
104 | */ | |
105 | class Smarty extends Smarty_Internal_TemplateBase | |
106 | { | |
107 | /**#@+ | |
108 | * constant definitions | |
109 | */ | |
110 | ||
111 | /** | |
112 | * smarty version | |
113 | */ | |
ccd27f54 | 114 | const SMARTY_VERSION = '3.1.22-dev/32'; |
2aa91ff2 S |
115 | |
116 | /** | |
117 | * define variable scopes | |
118 | */ | |
119 | const SCOPE_LOCAL = 0; | |
120 | const SCOPE_PARENT = 1; | |
121 | const SCOPE_ROOT = 2; | |
122 | const SCOPE_GLOBAL = 3; | |
123 | /** | |
124 | * define caching modes | |
125 | */ | |
126 | const CACHING_OFF = 0; | |
127 | const CACHING_LIFETIME_CURRENT = 1; | |
128 | const CACHING_LIFETIME_SAVED = 2; | |
129 | /** | |
130 | * define constant for clearing cache files be saved expiration datees | |
131 | */ | |
132 | const CLEAR_EXPIRED = - 1; | |
133 | ||
134 | /** | |
135 | * define compile check modes | |
136 | */ | |
137 | const COMPILECHECK_OFF = 0; | |
138 | const COMPILECHECK_ON = 1; | |
139 | const COMPILECHECK_CACHEMISS = 2; | |
ccd27f54 S |
140 | |
141 | /** | |
142 | * define debug modes | |
143 | */ | |
144 | const DEBUG_OFF = 0; | |
145 | const DEBUG_ON = 1; | |
146 | const DEBUG_INDIVIDUAL = 2; | |
2aa91ff2 S |
147 | /** |
148 | * modes for handling of "<?php ... ?>" tags in templates. | |
149 | */ | |
150 | const PHP_PASSTHRU = 0; //-> print tags as plain text | |
151 | const PHP_QUOTE = 1; //-> escape tags as entities | |
152 | const PHP_REMOVE = 2; //-> escape tags as entities | |
153 | const PHP_ALLOW = 3; //-> escape tags as entities | |
154 | /** | |
155 | * filter types | |
156 | */ | |
157 | const FILTER_POST = 'post'; | |
158 | const FILTER_PRE = 'pre'; | |
159 | const FILTER_OUTPUT = 'output'; | |
160 | const FILTER_VARIABLE = 'variable'; | |
161 | /** | |
162 | * plugin types | |
163 | */ | |
164 | const PLUGIN_FUNCTION = 'function'; | |
165 | const PLUGIN_BLOCK = 'block'; | |
166 | const PLUGIN_COMPILER = 'compiler'; | |
167 | const PLUGIN_MODIFIER = 'modifier'; | |
168 | const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler'; | |
169 | ||
170 | /**#@-*/ | |
171 | ||
172 | /** | |
173 | * assigned global tpl vars | |
174 | */ | |
175 | public static $global_tpl_vars = array(); | |
176 | ||
177 | /** | |
178 | * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors() | |
179 | */ | |
180 | public static $_previous_error_handler = null; | |
181 | /** | |
182 | * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors() | |
183 | */ | |
ccd27f54 | 184 | public static $_muted_directories = array('./templates_c/' => null, './cache/' => null); |
2aa91ff2 S |
185 | /** |
186 | * Flag denoting if Multibyte String functions are available | |
187 | */ | |
188 | public static $_MBSTRING = SMARTY_MBSTRING; | |
189 | /** | |
190 | * The character set to adhere to (e.g. "UTF-8") | |
191 | */ | |
192 | public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET; | |
193 | /** | |
194 | * The date format to be used internally | |
195 | * (accepts date() and strftime()) | |
196 | */ | |
197 | public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT; | |
198 | /** | |
199 | * Flag denoting if PCRE should run in UTF-8 mode | |
200 | */ | |
201 | public static $_UTF8_MODIFIER = 'u'; | |
202 | ||
203 | /** | |
204 | * Flag denoting if operating system is windows | |
205 | */ | |
206 | public static $_IS_WINDOWS = false; | |
207 | ||
208 | /**#@+ | |
209 | * variables | |
210 | */ | |
211 | ||
212 | /** | |
213 | * auto literal on delimiters with whitspace | |
214 | * | |
215 | * @var boolean | |
216 | */ | |
217 | public $auto_literal = true; | |
218 | /** | |
219 | * display error on not assigned variables | |
220 | * | |
221 | * @var boolean | |
222 | */ | |
223 | public $error_unassigned = false; | |
224 | /** | |
225 | * look up relative filepaths in include_path | |
226 | * | |
227 | * @var boolean | |
228 | */ | |
229 | public $use_include_path = false; | |
230 | /** | |
231 | * template directory | |
232 | * | |
233 | * @var array | |
234 | */ | |
ccd27f54 | 235 | private $template_dir = array('./templates/'); |
2aa91ff2 S |
236 | /** |
237 | * joined template directory string used in cache keys | |
238 | * | |
239 | * @var string | |
240 | */ | |
ccd27f54 | 241 | public $joined_template_dir = './templates/'; |
2aa91ff2 S |
242 | /** |
243 | * joined config directory string used in cache keys | |
244 | * | |
245 | * @var string | |
246 | */ | |
ccd27f54 | 247 | public $joined_config_dir = './configs/'; |
2aa91ff2 S |
248 | /** |
249 | * default template handler | |
250 | * | |
251 | * @var callable | |
252 | */ | |
253 | public $default_template_handler_func = null; | |
254 | /** | |
255 | * default config handler | |
256 | * | |
257 | * @var callable | |
258 | */ | |
259 | public $default_config_handler_func = null; | |
260 | /** | |
261 | * default plugin handler | |
262 | * | |
263 | * @var callable | |
264 | */ | |
265 | public $default_plugin_handler_func = null; | |
266 | /** | |
267 | * compile directory | |
268 | * | |
269 | * @var string | |
270 | */ | |
ccd27f54 | 271 | private $compile_dir = './templates_c/'; |
2aa91ff2 S |
272 | /** |
273 | * plugins directory | |
274 | * | |
275 | * @var array | |
276 | */ | |
ccd27f54 | 277 | private $plugins_dir = null; |
2aa91ff2 S |
278 | /** |
279 | * cache directory | |
280 | * | |
281 | * @var string | |
282 | */ | |
ccd27f54 | 283 | private $cache_dir = './cache/'; |
2aa91ff2 S |
284 | /** |
285 | * config directory | |
286 | * | |
287 | * @var array | |
288 | */ | |
ccd27f54 | 289 | private $config_dir = array('./configs/'); |
2aa91ff2 S |
290 | /** |
291 | * force template compiling? | |
292 | * | |
293 | * @var boolean | |
294 | */ | |
295 | public $force_compile = false; | |
296 | /** | |
297 | * check template for modifications? | |
298 | * | |
299 | * @var boolean | |
300 | */ | |
301 | public $compile_check = true; | |
302 | /** | |
303 | * use sub dirs for compiled/cached files? | |
304 | * | |
305 | * @var boolean | |
306 | */ | |
307 | public $use_sub_dirs = false; | |
308 | /** | |
309 | * allow ambiguous resources (that are made unique by the resource handler) | |
310 | * | |
311 | * @var boolean | |
312 | */ | |
313 | public $allow_ambiguous_resources = false; | |
2aa91ff2 S |
314 | /** |
315 | * merge compiled includes | |
316 | * | |
317 | * @var boolean | |
318 | */ | |
319 | public $merge_compiled_includes = false; | |
320 | /** | |
321 | * template inheritance merge compiled includes | |
322 | * | |
323 | * @var boolean | |
324 | */ | |
325 | public $inheritance_merge_compiled_includes = true; | |
2aa91ff2 S |
326 | /** |
327 | * force cache file creation | |
328 | * | |
329 | * @var boolean | |
330 | */ | |
331 | public $force_cache = false; | |
2aa91ff2 S |
332 | /** |
333 | * template left-delimiter | |
334 | * | |
335 | * @var string | |
336 | */ | |
337 | public $left_delimiter = "{"; | |
338 | /** | |
339 | * template right-delimiter | |
340 | * | |
341 | * @var string | |
342 | */ | |
343 | public $right_delimiter = "}"; | |
344 | /**#@+ | |
345 | * security | |
346 | */ | |
347 | /** | |
348 | * class name | |
349 | * This should be instance of Smarty_Security. | |
350 | * | |
351 | * @var string | |
352 | * @see Smarty_Security | |
353 | */ | |
354 | public $security_class = 'Smarty_Security'; | |
355 | /** | |
356 | * implementation of security class | |
357 | * | |
358 | * @var Smarty_Security | |
359 | */ | |
360 | public $security_policy = null; | |
361 | /** | |
362 | * controls handling of PHP-blocks | |
363 | * | |
364 | * @var integer | |
365 | */ | |
366 | public $php_handling = self::PHP_PASSTHRU; | |
367 | /** | |
368 | * controls if the php template file resource is allowed | |
369 | * | |
370 | * @var bool | |
371 | */ | |
372 | public $allow_php_templates = false; | |
373 | /** | |
374 | * Should compiled-templates be prevented from being called directly? | |
375 | * {@internal | |
376 | * Currently used by Smarty_Internal_Template only. | |
377 | * }} | |
378 | * | |
379 | * @var boolean | |
380 | */ | |
381 | public $direct_access_security = true; | |
382 | /**#@-*/ | |
383 | /** | |
384 | * debug mode | |
385 | * Setting this to true enables the debug-console. | |
386 | * | |
387 | * @var boolean | |
388 | */ | |
389 | public $debugging = false; | |
390 | /** | |
391 | * This determines if debugging is enable-able from the browser. | |
392 | * <ul> | |
393 | * <li>NONE => no debugging control allowed</li> | |
394 | * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li> | |
395 | * </ul> | |
396 | * | |
397 | * @var string | |
398 | */ | |
399 | public $debugging_ctrl = 'NONE'; | |
400 | /** | |
401 | * Name of debugging URL-param. | |
402 | * Only used when $debugging_ctrl is set to 'URL'. | |
403 | * The name of the URL-parameter that activates debugging. | |
404 | * | |
ccd27f54 | 405 | * @var string |
2aa91ff2 S |
406 | */ |
407 | public $smarty_debug_id = 'SMARTY_DEBUG'; | |
408 | /** | |
409 | * Path of debug template. | |
410 | * | |
411 | * @var string | |
412 | */ | |
413 | public $debug_tpl = null; | |
414 | /** | |
415 | * When set, smarty uses this value as error_reporting-level. | |
416 | * | |
417 | * @var int | |
418 | */ | |
419 | public $error_reporting = null; | |
ccd27f54 | 420 | |
2aa91ff2 S |
421 | /** |
422 | * Internal flag for getTags() | |
423 | * | |
424 | * @var boolean | |
425 | */ | |
426 | public $get_used_tags = false; | |
427 | ||
428 | /**#@+ | |
429 | * config var settings | |
430 | */ | |
431 | ||
432 | /** | |
433 | * Controls whether variables with the same name overwrite each other. | |
434 | * | |
435 | * @var boolean | |
436 | */ | |
437 | public $config_overwrite = true; | |
438 | /** | |
439 | * Controls whether config values of on/true/yes and off/false/no get converted to boolean. | |
440 | * | |
441 | * @var boolean | |
442 | */ | |
443 | public $config_booleanize = true; | |
444 | /** | |
445 | * Controls whether hidden config sections/vars are read from the file. | |
446 | * | |
447 | * @var boolean | |
448 | */ | |
449 | public $config_read_hidden = false; | |
450 | ||
451 | /**#@-*/ | |
452 | ||
453 | /**#@+ | |
454 | * resource locking | |
455 | */ | |
456 | ||
457 | /** | |
458 | * locking concurrent compiles | |
459 | * | |
460 | * @var boolean | |
461 | */ | |
462 | public $compile_locking = true; | |
463 | /** | |
464 | * Controls whether cache resources should emply locking mechanism | |
465 | * | |
466 | * @var boolean | |
467 | */ | |
468 | public $cache_locking = false; | |
469 | /** | |
470 | * seconds to wait for acquiring a lock before ignoring the write lock | |
471 | * | |
472 | * @var float | |
473 | */ | |
474 | public $locking_timeout = 10; | |
475 | ||
476 | /**#@-*/ | |
477 | ||
2aa91ff2 S |
478 | /** |
479 | * resource type used if none given | |
480 | * Must be an valid key of $registered_resources. | |
481 | * | |
482 | * @var string | |
483 | */ | |
484 | public $default_resource_type = 'file'; | |
485 | /** | |
486 | * caching type | |
487 | * Must be an element of $cache_resource_types. | |
488 | * | |
489 | * @var string | |
490 | */ | |
491 | public $caching_type = 'file'; | |
492 | /** | |
493 | * internal config properties | |
494 | * | |
495 | * @var array | |
496 | */ | |
497 | public $properties = array(); | |
498 | /** | |
499 | * config type | |
500 | * | |
501 | * @var string | |
502 | */ | |
503 | public $default_config_type = 'file'; | |
ccd27f54 S |
504 | /** |
505 | * cached template objects | |
506 | * | |
507 | * @var array | |
508 | */ | |
509 | public $source_objects = array(); | |
2aa91ff2 S |
510 | /** |
511 | * cached template objects | |
512 | * | |
513 | * @var array | |
514 | */ | |
515 | public $template_objects = array(); | |
ccd27f54 S |
516 | |
517 | /** | |
518 | * enable resource caching | |
519 | * | |
520 | * @var bool | |
521 | */ | |
522 | public $resource_caching = false; | |
523 | /** | |
524 | * enable template resource caching | |
525 | * | |
526 | * @var bool | |
527 | */ | |
528 | public $template_resource_caching = true; | |
2aa91ff2 S |
529 | /** |
530 | * check If-Modified-Since headers | |
531 | * | |
532 | * @var boolean | |
533 | */ | |
534 | public $cache_modified_check = false; | |
535 | /** | |
536 | * registered plugins | |
537 | * | |
538 | * @var array | |
539 | */ | |
540 | public $registered_plugins = array(); | |
541 | /** | |
542 | * plugin search order | |
543 | * | |
544 | * @var array | |
545 | */ | |
546 | public $plugin_search_order = array('function', 'block', 'compiler', 'class'); | |
547 | /** | |
548 | * registered objects | |
549 | * | |
550 | * @var array | |
551 | */ | |
552 | public $registered_objects = array(); | |
553 | /** | |
554 | * registered classes | |
555 | * | |
556 | * @var array | |
557 | */ | |
558 | public $registered_classes = array(); | |
559 | /** | |
560 | * registered filters | |
561 | * | |
562 | * @var array | |
563 | */ | |
564 | public $registered_filters = array(); | |
565 | /** | |
566 | * registered resources | |
567 | * | |
568 | * @var array | |
569 | */ | |
570 | public $registered_resources = array(); | |
571 | /** | |
572 | * resource handler cache | |
573 | * | |
574 | * @var array | |
575 | */ | |
576 | public $_resource_handlers = array(); | |
577 | /** | |
578 | * registered cache resources | |
579 | * | |
580 | * @var array | |
581 | */ | |
582 | public $registered_cache_resources = array(); | |
583 | /** | |
584 | * cache resource handler cache | |
585 | * | |
586 | * @var array | |
587 | */ | |
588 | public $_cacheresource_handlers = array(); | |
589 | /** | |
590 | * autoload filter | |
591 | * | |
592 | * @var array | |
593 | */ | |
594 | public $autoload_filters = array(); | |
595 | /** | |
596 | * default modifier | |
597 | * | |
598 | * @var array | |
599 | */ | |
600 | public $default_modifiers = array(); | |
601 | /** | |
602 | * autoescape variable output | |
603 | * | |
604 | * @var boolean | |
605 | */ | |
606 | public $escape_html = false; | |
607 | /** | |
608 | * global internal smarty vars | |
609 | * | |
610 | * @var array | |
611 | */ | |
612 | public static $_smarty_vars = array(); | |
613 | /** | |
614 | * start time for execution time calculation | |
615 | * | |
616 | * @var int | |
617 | */ | |
618 | public $start_time = 0; | |
619 | /** | |
620 | * default file permissions | |
621 | * | |
622 | * @var int | |
623 | */ | |
624 | public $_file_perms = 0644; | |
625 | /** | |
626 | * default dir permissions | |
627 | * | |
628 | * @var int | |
629 | */ | |
630 | public $_dir_perms = 0771; | |
631 | /** | |
632 | * block tag hierarchy | |
633 | * | |
634 | * @var array | |
635 | */ | |
636 | public $_tag_stack = array(); | |
2aa91ff2 S |
637 | /** |
638 | * required by the compiler for BC | |
639 | * | |
640 | * @var string | |
641 | */ | |
642 | public $_current_file = null; | |
643 | /** | |
644 | * internal flag to enable parser debugging | |
645 | * | |
646 | * @var bool | |
647 | */ | |
648 | public $_parserdebug = false; | |
2aa91ff2 S |
649 | |
650 | /** | |
651 | * Cache of is_file results of loadPlugin() | |
ccd27f54 | 652 | * |
2aa91ff2 S |
653 | * @var array |
654 | */ | |
ccd27f54 | 655 | public $_is_file_cache = array(); |
2aa91ff2 S |
656 | |
657 | /**#@-*/ | |
658 | ||
659 | /** | |
660 | * Initialize new Smarty object | |
661 | ||
662 | */ | |
663 | public function __construct() | |
664 | { | |
2aa91ff2 S |
665 | if (is_callable('mb_internal_encoding')) { |
666 | mb_internal_encoding(Smarty::$_CHARSET); | |
667 | } | |
668 | $this->start_time = microtime(true); | |
ccd27f54 S |
669 | // check default dirs for overloading |
670 | if ($this->template_dir[0] !== './templates/' || isset($this->template_dir[1])) { | |
671 | $this->setTemplateDir($this->template_dir); | |
672 | } | |
673 | if ($this->config_dir[0] !== './configs/' || isset($this->config_dir[1])) { | |
674 | $this->setConfigDir($this->config_dir); | |
675 | } | |
676 | if ($this->compile_dir !== './templates_c/') { | |
677 | unset(self::$_muted_directories['./templates_c/']); | |
678 | $this->setCompileDir($this->compile_dir); | |
679 | } | |
680 | if ($this->cache_dir !== './cache/') { | |
681 | unset(self::$_muted_directories['./cache/']); | |
682 | $this->setCacheDir($this->cache_dir); | |
683 | } | |
684 | if (isset($this->plugins_dir)) { | |
685 | $this->setPluginsDir($this->plugins_dir); | |
686 | } else { | |
687 | $this->setPluginsDir(SMARTY_PLUGINS_DIR); | |
688 | } | |
2aa91ff2 S |
689 | |
690 | $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl'; | |
691 | if (isset($_SERVER['SCRIPT_NAME'])) { | |
ccd27f54 | 692 | Smarty::$global_tpl_vars['SCRIPT_NAME'] = new Smarty_Variable($_SERVER['SCRIPT_NAME']); |
2aa91ff2 | 693 | } |
2aa91ff2 | 694 | |
ccd27f54 S |
695 | // Check if we're running on windows |
696 | Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; | |
2aa91ff2 | 697 | |
ccd27f54 S |
698 | // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 |
699 | if (Smarty::$_CHARSET !== 'UTF-8') { | |
700 | Smarty::$_UTF8_MODIFIER = ''; | |
701 | } | |
2aa91ff2 S |
702 | } |
703 | ||
704 | /** | |
ccd27f54 | 705 | * fetches a rendered Smarty template |
2aa91ff2 | 706 | * |
ccd27f54 S |
707 | * @param string $template the resource handle of the template file or template object |
708 | * @param mixed $cache_id cache id to be used with this template | |
709 | * @param mixed $compile_id compile id to be used with this template | |
710 | * @param object $parent next higher level of Smarty variables | |
711 | * @param bool $display true: display, false: fetch | |
712 | * @param bool $merge_tpl_vars not used - left for BC | |
713 | * @param bool $no_output_filter not used - left for BC | |
2aa91ff2 | 714 | * |
ccd27f54 S |
715 | * @throws Exception |
716 | * @throws SmartyException | |
717 | * @return string rendered template output | |
2aa91ff2 | 718 | */ |
ccd27f54 | 719 | public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) |
2aa91ff2 | 720 | { |
ccd27f54 S |
721 | if ($cache_id !== null && is_object($cache_id)) { |
722 | $parent = $cache_id; | |
723 | $cache_id = null; | |
724 | } | |
725 | if ($parent === null) { | |
726 | $parent = $this; | |
2aa91ff2 | 727 | } |
ccd27f54 S |
728 | // get template object |
729 | $_template = is_object($template) ? $template : $this->createTemplate($template, $cache_id, $compile_id, $parent, false); | |
730 | // set caching in template object | |
731 | $_template->caching = $this->caching; | |
732 | // fetch template content | |
733 | return $_template->render(true, false, $display); | |
2aa91ff2 S |
734 | } |
735 | ||
736 | /** | |
ccd27f54 | 737 | * displays a Smarty template |
2aa91ff2 | 738 | * |
ccd27f54 S |
739 | * @param string $template the resource handle of the template file or template object |
740 | * @param mixed $cache_id cache id to be used with this template | |
741 | * @param mixed $compile_id compile id to be used with this template | |
742 | * @param object $parent next higher level of Smarty variables | |
2aa91ff2 | 743 | */ |
ccd27f54 | 744 | public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) |
2aa91ff2 | 745 | { |
ccd27f54 S |
746 | // display template |
747 | $this->fetch($template, $cache_id, $compile_id, $parent, true); | |
2aa91ff2 S |
748 | } |
749 | ||
750 | /** | |
751 | * Check if a template resource exists | |
752 | * | |
753 | * @param string $resource_name template name | |
754 | * | |
755 | * @return boolean status | |
756 | */ | |
757 | public function templateExists($resource_name) | |
758 | { | |
759 | // create template object | |
760 | $save = $this->template_objects; | |
761 | $tpl = new $this->template_class($resource_name, $this); | |
762 | // check if it does exists | |
763 | $result = $tpl->source->exists; | |
764 | $this->template_objects = $save; | |
765 | ||
766 | return $result; | |
767 | } | |
768 | ||
769 | /** | |
770 | * Returns a single or all global variables | |
771 | * | |
772 | * @param string $varname variable name or null | |
773 | * | |
774 | * @return string variable value or or array of variables | |
775 | */ | |
776 | public function getGlobal($varname = null) | |
777 | { | |
778 | if (isset($varname)) { | |
779 | if (isset(self::$global_tpl_vars[$varname])) { | |
780 | return self::$global_tpl_vars[$varname]->value; | |
781 | } else { | |
782 | return ''; | |
783 | } | |
784 | } else { | |
785 | $_result = array(); | |
786 | foreach (self::$global_tpl_vars AS $key => $var) { | |
787 | $_result[$key] = $var->value; | |
788 | } | |
789 | ||
790 | return $_result; | |
791 | } | |
792 | } | |
793 | ||
794 | /** | |
795 | * Empty cache folder | |
796 | * | |
797 | * @param integer $exp_time expiration time | |
798 | * @param string $type resource type | |
799 | * | |
800 | * @return integer number of cache files deleted | |
801 | */ | |
802 | public function clearAllCache($exp_time = null, $type = null) | |
803 | { | |
804 | // load cache resource and call clearAll | |
805 | $_cache_resource = Smarty_CacheResource::load($this, $type); | |
806 | Smarty_CacheResource::invalidLoadedCache($this); | |
807 | ||
808 | return $_cache_resource->clearAll($this, $exp_time); | |
809 | } | |
810 | ||
811 | /** | |
812 | * Empty cache for a specific template | |
813 | * | |
814 | * @param string $template_name template name | |
815 | * @param string $cache_id cache id | |
816 | * @param string $compile_id compile id | |
817 | * @param integer $exp_time expiration time | |
818 | * @param string $type resource type | |
819 | * | |
820 | * @return integer number of cache files deleted | |
821 | */ | |
822 | public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) | |
823 | { | |
824 | // load cache resource and call clear | |
825 | $_cache_resource = Smarty_CacheResource::load($this, $type); | |
826 | Smarty_CacheResource::invalidLoadedCache($this); | |
827 | ||
828 | return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time); | |
829 | } | |
830 | ||
831 | /** | |
832 | * Loads security class and enables security | |
833 | * | |
834 | * @param string|Smarty_Security $security_class if a string is used, it must be class-name | |
835 | * | |
836 | * @return Smarty current Smarty instance for chaining | |
837 | * @throws SmartyException when an invalid class name is provided | |
838 | */ | |
839 | public function enableSecurity($security_class = null) | |
840 | { | |
841 | if ($security_class instanceof Smarty_Security) { | |
842 | $this->security_policy = $security_class; | |
843 | ||
844 | return $this; | |
845 | } elseif (is_object($security_class)) { | |
846 | throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security."); | |
847 | } | |
848 | if ($security_class == null) { | |
849 | $security_class = $this->security_class; | |
850 | } | |
851 | if (!class_exists($security_class)) { | |
852 | throw new SmartyException("Security class '$security_class' is not defined"); | |
853 | } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) { | |
854 | throw new SmartyException("Class '$security_class' must extend Smarty_Security."); | |
855 | } else { | |
856 | $this->security_policy = new $security_class($this); | |
857 | } | |
858 | ||
859 | return $this; | |
860 | } | |
861 | ||
862 | /** | |
863 | * Disable security | |
864 | * | |
865 | * @return Smarty current Smarty instance for chaining | |
866 | */ | |
867 | public function disableSecurity() | |
868 | { | |
869 | $this->security_policy = null; | |
870 | ||
871 | return $this; | |
872 | } | |
873 | ||
874 | /** | |
875 | * Set template directory | |
876 | * | |
877 | * @param string|array $template_dir directory(s) of template sources | |
878 | * | |
879 | * @return Smarty current Smarty instance for chaining | |
880 | */ | |
881 | public function setTemplateDir($template_dir) | |
882 | { | |
883 | $this->template_dir = array(); | |
884 | foreach ((array) $template_dir as $k => $v) { | |
ccd27f54 | 885 | $this->template_dir[$k] = rtrim(strtr($v, '\\', '/'), '/') . '/'; |
2aa91ff2 | 886 | } |
ccd27f54 | 887 | $this->joined_template_dir = join(' # ', $this->template_dir); |
2aa91ff2 S |
888 | return $this; |
889 | } | |
890 | ||
891 | /** | |
892 | * Add template directory(s) | |
893 | * | |
894 | * @param string|array $template_dir directory(s) of template sources | |
895 | * @param string $key of the array element to assign the template dir to | |
896 | * | |
897 | * @return Smarty current Smarty instance for chaining | |
898 | * @throws SmartyException when the given template directory is not valid | |
899 | */ | |
900 | public function addTemplateDir($template_dir, $key = null) | |
901 | { | |
ccd27f54 S |
902 | $this->_addDir('template_dir', $template_dir, $key); |
903 | $this->joined_template_dir = join(' # ', $this->template_dir); | |
2aa91ff2 S |
904 | return $this; |
905 | } | |
906 | ||
907 | /** | |
908 | * Get template directories | |
909 | * | |
910 | * @param mixed $index index of directory to get, null to get all | |
911 | * | |
912 | * @return array|string list of template directories, or directory of $index | |
913 | */ | |
914 | public function getTemplateDir($index = null) | |
915 | { | |
916 | if ($index !== null) { | |
917 | return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null; | |
918 | } | |
2aa91ff2 S |
919 | return (array) $this->template_dir; |
920 | } | |
921 | ||
922 | /** | |
923 | * Set config directory | |
924 | * | |
925 | * @param $config_dir | |
926 | * | |
927 | * @return Smarty current Smarty instance for chaining | |
928 | */ | |
929 | public function setConfigDir($config_dir) | |
930 | { | |
931 | $this->config_dir = array(); | |
932 | foreach ((array) $config_dir as $k => $v) { | |
ccd27f54 | 933 | $this->config_dir[$k] = rtrim(strtr($v, '\\', '/'), '/') . '/'; |
2aa91ff2 | 934 | } |
ccd27f54 | 935 | $this->joined_config_dir = join(' # ', $this->config_dir); |
2aa91ff2 S |
936 | return $this; |
937 | } | |
938 | ||
939 | /** | |
940 | * Add config directory(s) | |
941 | * | |
ccd27f54 S |
942 | * @param string|array $config_dir directory(s) of config sources |
943 | * @param mixed $key key of the array element to assign the config dir to | |
2aa91ff2 S |
944 | * |
945 | * @return Smarty current Smarty instance for chaining | |
946 | */ | |
947 | public function addConfigDir($config_dir, $key = null) | |
948 | { | |
ccd27f54 S |
949 | $this->_addDir('config_dir', $config_dir, $key); |
950 | $this->joined_config_dir = join(' # ', $this->config_dir); | |
2aa91ff2 S |
951 | return $this; |
952 | } | |
953 | ||
954 | /** | |
955 | * Get config directory | |
956 | * | |
957 | * @param mixed $index index of directory to get, null to get all | |
958 | * | |
959 | * @return array|string configuration directory | |
960 | */ | |
961 | public function getConfigDir($index = null) | |
962 | { | |
963 | if ($index !== null) { | |
964 | return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null; | |
965 | } | |
2aa91ff2 S |
966 | return (array) $this->config_dir; |
967 | } | |
968 | ||
969 | /** | |
970 | * Set plugins directory | |
971 | * | |
972 | * @param string|array $plugins_dir directory(s) of plugins | |
973 | * | |
974 | * @return Smarty current Smarty instance for chaining | |
975 | */ | |
976 | public function setPluginsDir($plugins_dir) | |
977 | { | |
978 | $this->plugins_dir = array(); | |
979 | foreach ((array) $plugins_dir as $k => $v) { | |
ccd27f54 | 980 | $this->plugins_dir[$k] = rtrim(strtr($v, '\\', '/'), '/') . '/'; |
2aa91ff2 | 981 | } |
ccd27f54 | 982 | $this->_is_file_cache = array(); |
2aa91ff2 S |
983 | return $this; |
984 | } | |
985 | ||
986 | /** | |
987 | * Adds directory of plugin files | |
988 | * | |
989 | * @param $plugins_dir | |
990 | * | |
991 | * @return Smarty current Smarty instance for chaining | |
992 | */ | |
993 | public function addPluginsDir($plugins_dir) | |
994 | { | |
ccd27f54 | 995 | $this->_addDir('plugins_dir', $plugins_dir); |
2aa91ff2 | 996 | $this->plugins_dir = array_unique($this->plugins_dir); |
ccd27f54 | 997 | $this->_is_file_cache = array(); |
2aa91ff2 S |
998 | return $this; |
999 | } | |
1000 | ||
1001 | /** | |
1002 | * Get plugin directories | |
1003 | * | |
1004 | * @return array list of plugin directories | |
1005 | */ | |
1006 | public function getPluginsDir() | |
1007 | { | |
1008 | return (array) $this->plugins_dir; | |
1009 | } | |
1010 | ||
1011 | /** | |
1012 | * Set compile directory | |
1013 | * | |
1014 | * @param string $compile_dir directory to store compiled templates in | |
1015 | * | |
1016 | * @return Smarty current Smarty instance for chaining | |
1017 | */ | |
1018 | public function setCompileDir($compile_dir) | |
1019 | { | |
ccd27f54 | 1020 | $this->compile_dir = rtrim(strtr($compile_dir, '\\', '/'), '/') . '/'; |
2aa91ff2 S |
1021 | if (!isset(Smarty::$_muted_directories[$this->compile_dir])) { |
1022 | Smarty::$_muted_directories[$this->compile_dir] = null; | |
1023 | } | |
1024 | ||
1025 | return $this; | |
1026 | } | |
1027 | ||
1028 | /** | |
1029 | * Get compiled directory | |
1030 | * | |
1031 | * @return string path to compiled templates | |
1032 | */ | |
1033 | public function getCompileDir() | |
1034 | { | |
1035 | return $this->compile_dir; | |
1036 | } | |
1037 | ||
1038 | /** | |
1039 | * Set cache directory | |
1040 | * | |
1041 | * @param string $cache_dir directory to store cached templates in | |
1042 | * | |
1043 | * @return Smarty current Smarty instance for chaining | |
1044 | */ | |
1045 | public function setCacheDir($cache_dir) | |
1046 | { | |
ccd27f54 | 1047 | $this->cache_dir = rtrim(strtr($cache_dir, '\\', '/'), '/') . '/'; |
2aa91ff2 S |
1048 | if (!isset(Smarty::$_muted_directories[$this->cache_dir])) { |
1049 | Smarty::$_muted_directories[$this->cache_dir] = null; | |
1050 | } | |
1051 | ||
1052 | return $this; | |
1053 | } | |
1054 | ||
1055 | /** | |
1056 | * Get cache directory | |
1057 | * | |
1058 | * @return string path of cache directory | |
1059 | */ | |
1060 | public function getCacheDir() | |
1061 | { | |
1062 | return $this->cache_dir; | |
1063 | } | |
1064 | ||
ccd27f54 S |
1065 | /** |
1066 | * add directories to given property name | |
1067 | * | |
1068 | * @param string $dirName directory property name | |
1069 | * @param string|array $dir directory string or array of strings | |
1070 | * @param mixed $key optional key | |
1071 | */ | |
1072 | private function _addDir($dirName, $dir, $key = null) | |
1073 | { | |
1074 | // make sure we're dealing with an array | |
1075 | $this->$dirName = (array) $this->$dirName; | |
1076 | ||
1077 | if (is_array($dir)) { | |
1078 | foreach ($dir as $k => $v) { | |
1079 | $v = rtrim(strtr($v, '\\', '/'), '/') . '/'; | |
1080 | if (is_int($k)) { | |
1081 | // indexes are not merged but appended | |
1082 | $this->{$dirName}[] = $v; | |
1083 | } else { | |
1084 | // string indexes are overridden | |
1085 | $this->{$dirName}[$k] = $v; | |
1086 | } | |
1087 | } | |
1088 | } else { | |
1089 | $v = rtrim(strtr($dir, '\\', '/'), '/') . '/'; | |
1090 | if ($key !== null) { | |
1091 | // override directory at specified index | |
1092 | $this->{$dirName}[$key] = $v; | |
1093 | } else { | |
1094 | // append new directory | |
1095 | $this->{$dirName}[] = $v; | |
1096 | } | |
1097 | } | |
1098 | } | |
1099 | ||
2aa91ff2 S |
1100 | /** |
1101 | * Set default modifiers | |
1102 | * | |
1103 | * @param array|string $modifiers modifier or list of modifiers to set | |
1104 | * | |
1105 | * @return Smarty current Smarty instance for chaining | |
1106 | */ | |
1107 | public function setDefaultModifiers($modifiers) | |
1108 | { | |
1109 | $this->default_modifiers = (array) $modifiers; | |
1110 | ||
1111 | return $this; | |
1112 | } | |
1113 | ||
1114 | /** | |
1115 | * Add default modifiers | |
1116 | * | |
1117 | * @param array|string $modifiers modifier or list of modifiers to add | |
1118 | * | |
1119 | * @return Smarty current Smarty instance for chaining | |
1120 | */ | |
1121 | public function addDefaultModifiers($modifiers) | |
1122 | { | |
1123 | if (is_array($modifiers)) { | |
1124 | $this->default_modifiers = array_merge($this->default_modifiers, $modifiers); | |
1125 | } else { | |
1126 | $this->default_modifiers[] = $modifiers; | |
1127 | } | |
1128 | ||
1129 | return $this; | |
1130 | } | |
1131 | ||
1132 | /** | |
1133 | * Get default modifiers | |
1134 | * | |
1135 | * @return array list of default modifiers | |
1136 | */ | |
1137 | public function getDefaultModifiers() | |
1138 | { | |
1139 | return $this->default_modifiers; | |
1140 | } | |
1141 | ||
1142 | /** | |
1143 | * Set autoload filters | |
1144 | * | |
1145 | * @param array $filters filters to load automatically | |
ccd27f54 S |
1146 | * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' |
1147 | * keys as the appropriate types | |
2aa91ff2 S |
1148 | * |
1149 | * @return Smarty current Smarty instance for chaining | |
1150 | */ | |
1151 | public function setAutoloadFilters($filters, $type = null) | |
1152 | { | |
1153 | if ($type !== null) { | |
1154 | $this->autoload_filters[$type] = (array) $filters; | |
1155 | } else { | |
1156 | $this->autoload_filters = (array) $filters; | |
1157 | } | |
1158 | ||
1159 | return $this; | |
1160 | } | |
1161 | ||
1162 | /** | |
1163 | * Add autoload filters | |
1164 | * | |
1165 | * @param array $filters filters to load automatically | |
ccd27f54 S |
1166 | * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' |
1167 | * keys as the appropriate types | |
2aa91ff2 S |
1168 | * |
1169 | * @return Smarty current Smarty instance for chaining | |
1170 | */ | |
1171 | public function addAutoloadFilters($filters, $type = null) | |
1172 | { | |
1173 | if ($type !== null) { | |
1174 | if (!empty($this->autoload_filters[$type])) { | |
1175 | $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters); | |
1176 | } else { | |
1177 | $this->autoload_filters[$type] = (array) $filters; | |
1178 | } | |
1179 | } else { | |
1180 | foreach ((array) $filters as $key => $value) { | |
1181 | if (!empty($this->autoload_filters[$key])) { | |
1182 | $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value); | |
1183 | } else { | |
1184 | $this->autoload_filters[$key] = (array) $value; | |
1185 | } | |
1186 | } | |
1187 | } | |
1188 | ||
1189 | return $this; | |
1190 | } | |
1191 | ||
1192 | /** | |
1193 | * Get autoload filters | |
1194 | * | |
1195 | * @param string $type type of filter to get autoloads for. Defaults to all autoload filters | |
1196 | * | |
ccd27f54 S |
1197 | * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type |
1198 | * was specified | |
2aa91ff2 S |
1199 | */ |
1200 | public function getAutoloadFilters($type = null) | |
1201 | { | |
1202 | if ($type !== null) { | |
1203 | return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array(); | |
1204 | } | |
1205 | ||
1206 | return $this->autoload_filters; | |
1207 | } | |
1208 | ||
1209 | /** | |
1210 | * return name of debugging template | |
1211 | * | |
1212 | * @return string | |
1213 | */ | |
1214 | public function getDebugTemplate() | |
1215 | { | |
1216 | return $this->debug_tpl; | |
1217 | } | |
1218 | ||
1219 | /** | |
1220 | * set the debug template | |
1221 | * | |
1222 | * @param string $tpl_name | |
1223 | * | |
1224 | * @return Smarty current Smarty instance for chaining | |
1225 | * @throws SmartyException if file is not readable | |
1226 | */ | |
1227 | public function setDebugTemplate($tpl_name) | |
1228 | { | |
1229 | if (!is_readable($tpl_name)) { | |
1230 | throw new SmartyException("Unknown file '{$tpl_name}'"); | |
1231 | } | |
1232 | $this->debug_tpl = $tpl_name; | |
1233 | ||
1234 | return $this; | |
1235 | } | |
1236 | ||
1237 | /** | |
1238 | * creates a template object | |
1239 | * | |
1240 | * @param string $template the resource handle of the template file | |
1241 | * @param mixed $cache_id cache id to be used with this template | |
1242 | * @param mixed $compile_id compile id to be used with this template | |
1243 | * @param object $parent next higher level of Smarty variables | |
1244 | * @param boolean $do_clone flag is Smarty object shall be cloned | |
1245 | * | |
1246 | * @return object template object | |
1247 | */ | |
1248 | public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) | |
1249 | { | |
1250 | if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) { | |
1251 | $parent = $cache_id; | |
1252 | $cache_id = null; | |
1253 | } | |
1254 | if ($parent !== null && is_array($parent)) { | |
1255 | $data = $parent; | |
1256 | $parent = null; | |
1257 | } else { | |
1258 | $data = null; | |
1259 | } | |
ccd27f54 S |
1260 | $_templateId = $this->getTemplateId($template, $cache_id, $compile_id); |
1261 | if (isset($this->template_objects[$_templateId])) { | |
1262 | if ($do_clone) { | |
2aa91ff2 S |
1263 | $tpl = clone $this->template_objects[$_templateId]; |
1264 | $tpl->smarty = clone $tpl->smarty; | |
2aa91ff2 | 1265 | } else { |
ccd27f54 | 1266 | $tpl = $this->template_objects[$_templateId]; |
2aa91ff2 | 1267 | } |
ccd27f54 S |
1268 | $tpl->parent = $parent; |
1269 | $tpl->tpl_vars = array(); | |
1270 | $tpl->config_vars = array(); | |
2aa91ff2 | 1271 | } else { |
ccd27f54 S |
1272 | $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); |
1273 | if ($do_clone) { | |
1274 | $tpl->smarty = clone $tpl->smarty; | |
2aa91ff2 | 1275 | } |
ccd27f54 | 1276 | $tpl->templateId = $_templateId; |
2aa91ff2 S |
1277 | } |
1278 | // fill data if present | |
1279 | if (!empty($data) && is_array($data)) { | |
1280 | // set up variable values | |
1281 | foreach ($data as $_key => $_val) { | |
ccd27f54 S |
1282 | $tpl->tpl_vars[$_key] = new Smarty_Variable($_val); |
1283 | } | |
1284 | } | |
1285 | if ($this->debugging) { | |
1286 | if ($this->debugging) { | |
1287 | Smarty_Internal_Debug::register_template($tpl); | |
2aa91ff2 S |
1288 | } |
1289 | } | |
2aa91ff2 S |
1290 | return $tpl; |
1291 | } | |
1292 | ||
1293 | /** | |
1294 | * Takes unknown classes and loads plugin files for them | |
1295 | * class name format: Smarty_PluginType_PluginName | |
1296 | * plugin filename format: plugintype.pluginname.php | |
1297 | * | |
1298 | * @param string $plugin_name class plugin name to load | |
1299 | * @param bool $check check if already loaded | |
1300 | * | |
1301 | * @throws SmartyException | |
1302 | * @return string |boolean filepath of loaded file or false | |
1303 | */ | |
1304 | public function loadPlugin($plugin_name, $check = true) | |
1305 | { | |
1306 | // if function or class exists, exit silently (already loaded) | |
1307 | if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) { | |
1308 | return true; | |
1309 | } | |
1310 | // Plugin name is expected to be: Smarty_[Type]_[Name] | |
1311 | $_name_parts = explode('_', $plugin_name, 3); | |
1312 | // class name must have three parts to be valid plugin | |
1313 | // count($_name_parts) < 3 === !isset($_name_parts[2]) | |
1314 | if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') { | |
1315 | throw new SmartyException("plugin {$plugin_name} is not a valid name format"); | |
1316 | } | |
1317 | // if type is "internal", get plugin from sysplugins | |
1318 | if (strtolower($_name_parts[1]) == 'internal') { | |
1319 | $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; | |
ccd27f54 | 1320 | if (isset($this->_is_file_cache[$file]) ? $this->_is_file_cache[$file] : $this->_is_file_cache[$file] = is_file($file)) { |
2aa91ff2 S |
1321 | require_once($file); |
1322 | return $file; | |
1323 | } else { | |
1324 | return false; | |
1325 | } | |
1326 | } | |
1327 | // plugin filename is expected to be: [type].[name].php | |
1328 | $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php"; | |
1329 | ||
1330 | $_stream_resolve_include_path = function_exists('stream_resolve_include_path'); | |
1331 | ||
1332 | // loop through plugin dirs and find the plugin | |
1333 | foreach ($this->getPluginsDir() as $_plugin_dir) { | |
1334 | $names = array( | |
1335 | $_plugin_dir . $_plugin_filename, | |
1336 | $_plugin_dir . strtolower($_plugin_filename), | |
1337 | ); | |
1338 | foreach ($names as $file) { | |
ccd27f54 | 1339 | if (isset($this->_is_file_cache[$file]) ? $this->_is_file_cache[$file] : $this->_is_file_cache[$file] = is_file($file)) { |
2aa91ff2 S |
1340 | require_once($file); |
1341 | return $file; | |
1342 | } | |
1343 | if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) { | |
1344 | // try PHP include_path | |
1345 | if ($_stream_resolve_include_path) { | |
1346 | $file = stream_resolve_include_path($file); | |
1347 | } else { | |
1348 | $file = Smarty_Internal_Get_Include_Path::getIncludePath($file); | |
1349 | } | |
1350 | ||
1351 | if ($file !== false) { | |
1352 | require_once($file); | |
1353 | ||
1354 | return $file; | |
1355 | } | |
1356 | } | |
1357 | } | |
1358 | } | |
1359 | // no plugin loaded | |
1360 | return false; | |
1361 | } | |
1362 | ||
1363 | /** | |
1364 | * Compile all template files | |
1365 | * | |
1366 | * @param string $extension file extension | |
1367 | * @param bool $force_compile force all to recompile | |
1368 | * @param int $time_limit | |
1369 | * @param int $max_errors | |
1370 | * | |
1371 | * @return integer number of template files recompiled | |
1372 | */ | |
1373 | public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) | |
1374 | { | |
1375 | return Smarty_Internal_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this); | |
1376 | } | |
1377 | ||
1378 | /** | |
1379 | * Compile all config files | |
1380 | * | |
1381 | * @param string $extension file extension | |
1382 | * @param bool $force_compile force all to recompile | |
1383 | * @param int $time_limit | |
1384 | * @param int $max_errors | |
1385 | * | |
1386 | * @return integer number of template files recompiled | |
1387 | */ | |
1388 | public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null) | |
1389 | { | |
1390 | return Smarty_Internal_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this); | |
1391 | } | |
1392 | ||
1393 | /** | |
1394 | * Delete compiled template file | |
1395 | * | |
1396 | * @param string $resource_name template name | |
1397 | * @param string $compile_id compile id | |
1398 | * @param integer $exp_time expiration time | |
1399 | * | |
1400 | * @return integer number of template files deleted | |
1401 | */ | |
1402 | public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) | |
1403 | { | |
1404 | return Smarty_Internal_Utility::clearCompiledTemplate($resource_name, $compile_id, $exp_time, $this); | |
1405 | } | |
1406 | ||
1407 | /** | |
1408 | * Return array of tag/attributes of all tags used by an template | |
1409 | * | |
1410 | * @param Smarty_Internal_Template $template | |
1411 | * | |
1412 | * @return array of tag/attributes | |
1413 | */ | |
1414 | public function getTags(Smarty_Internal_Template $template) | |
1415 | { | |
1416 | return Smarty_Internal_Utility::getTags($template); | |
1417 | } | |
1418 | ||
1419 | /** | |
1420 | * Run installation test | |
1421 | * | |
1422 | * @param array $errors Array to write errors into, rather than outputting them | |
1423 | * | |
1424 | * @return boolean true if setup is fine, false if something is wrong | |
1425 | */ | |
1426 | public function testInstall(&$errors = null) | |
1427 | { | |
ccd27f54 S |
1428 | return Smarty_Internal_TestInstall::testInstall($this, $errors); |
1429 | } | |
1430 | ||
1431 | /** | |
1432 | * @param boolean $compile_check | |
1433 | */ | |
1434 | public function setCompileCheck($compile_check) | |
1435 | { | |
1436 | $this->compile_check = $compile_check; | |
1437 | } | |
1438 | ||
1439 | /** | |
1440 | * @param boolean $use_sub_dirs | |
1441 | */ | |
1442 | public function setUseSubDirs($use_sub_dirs) | |
1443 | { | |
1444 | $this->use_sub_dirs = $use_sub_dirs; | |
1445 | } | |
1446 | ||
1447 | /** | |
1448 | * @param boolean $caching | |
1449 | */ | |
1450 | public function setCaching($caching) | |
1451 | { | |
1452 | $this->caching = $caching; | |
1453 | } | |
1454 | ||
1455 | /** | |
1456 | * @param int $cache_lifetime | |
1457 | */ | |
1458 | public function setCacheLifetime($cache_lifetime) | |
1459 | { | |
1460 | $this->cache_lifetime = $cache_lifetime; | |
1461 | } | |
1462 | ||
1463 | /** | |
1464 | * @param string $compile_id | |
1465 | */ | |
1466 | public function setCompileId($compile_id) | |
1467 | { | |
1468 | $this->compile_id = $compile_id; | |
1469 | } | |
1470 | ||
1471 | /** | |
1472 | * @param string $cache_id | |
1473 | */ | |
1474 | public function setCacheId($cache_id) | |
1475 | { | |
1476 | $this->cache_id = $cache_id; | |
1477 | } | |
1478 | ||
1479 | /** | |
1480 | * @param int $error_reporting | |
1481 | */ | |
1482 | public function setErrorReporting($error_reporting) | |
1483 | { | |
1484 | $this->error_reporting = $error_reporting; | |
1485 | } | |
1486 | ||
1487 | /** | |
1488 | * @param boolean $escape_html | |
1489 | */ | |
1490 | public function setEscapeHtml($escape_html) | |
1491 | { | |
1492 | $this->escape_html = $escape_html; | |
1493 | } | |
1494 | ||
1495 | /** | |
1496 | * @param boolean $auto_literal | |
1497 | */ | |
1498 | public function setAutoLiteral($auto_literal) | |
1499 | { | |
1500 | $this->auto_literal = $auto_literal; | |
1501 | } | |
1502 | ||
1503 | /** | |
1504 | * @param boolean $force_compile | |
1505 | */ | |
1506 | public function setForceCompile($force_compile) | |
1507 | { | |
1508 | $this->force_compile = $force_compile; | |
1509 | } | |
1510 | ||
1511 | /** | |
1512 | * @param boolean $merge_compiled_includes | |
1513 | */ | |
1514 | public function setMergeCompiledIncludes($merge_compiled_includes) | |
1515 | { | |
1516 | $this->merge_compiled_includes = $merge_compiled_includes; | |
1517 | } | |
1518 | ||
1519 | /** | |
1520 | * @param string $left_delimiter | |
1521 | */ | |
1522 | public function setLeftDelimiter($left_delimiter) | |
1523 | { | |
1524 | $this->left_delimiter = $left_delimiter; | |
1525 | } | |
1526 | ||
1527 | /** | |
1528 | * @param string $right_delimiter | |
1529 | */ | |
1530 | public function setRightDelimiter($right_delimiter) | |
1531 | { | |
1532 | $this->right_delimiter = $right_delimiter; | |
1533 | } | |
1534 | ||
1535 | /** | |
1536 | * @param boolean $debugging | |
1537 | */ | |
1538 | public function setDebugging($debugging) | |
1539 | { | |
1540 | $this->debugging = $debugging; | |
1541 | } | |
1542 | ||
1543 | /** | |
1544 | * @param boolean $config_overwrite | |
1545 | */ | |
1546 | public function setConfigOverwrite($config_overwrite) | |
1547 | { | |
1548 | $this->config_overwrite = $config_overwrite; | |
1549 | } | |
1550 | ||
1551 | /** | |
1552 | * @param boolean $config_booleanize | |
1553 | */ | |
1554 | public function setConfigBooleanize($config_booleanize) | |
1555 | { | |
1556 | $this->config_booleanize = $config_booleanize; | |
1557 | } | |
1558 | ||
1559 | /** | |
1560 | * @param boolean $config_read_hidden | |
1561 | */ | |
1562 | public function setConfigReadHidden($config_read_hidden) | |
1563 | { | |
1564 | $this->config_read_hidden = $config_read_hidden; | |
1565 | } | |
1566 | ||
1567 | /** | |
1568 | * @param boolean $compile_locking | |
1569 | */ | |
1570 | public function setCompileLocking($compile_locking) | |
1571 | { | |
1572 | $this->compile_locking = $compile_locking; | |
1573 | } | |
1574 | ||
1575 | /** | |
1576 | * Class destructor | |
1577 | */ | |
1578 | public function __destruct() | |
1579 | { | |
1580 | // intentionally left blank | |
1581 | } | |
1582 | ||
1583 | /** | |
1584 | * <<magic>> Generic getter. | |
1585 | * Calls the appropriate getter function. | |
1586 | * Issues an E_USER_NOTICE if no valid getter is found. | |
1587 | * | |
1588 | * @param string $name property name | |
1589 | * | |
1590 | * @return mixed | |
1591 | */ | |
1592 | public function __get($name) | |
1593 | { | |
1594 | $allowed = array( | |
1595 | 'template_dir' => 'getTemplateDir', | |
1596 | 'config_dir' => 'getConfigDir', | |
1597 | 'plugins_dir' => 'getPluginsDir', | |
1598 | 'compile_dir' => 'getCompileDir', | |
1599 | 'cache_dir' => 'getCacheDir', | |
1600 | ); | |
1601 | ||
1602 | if (isset($allowed[$name])) { | |
1603 | return $this->{$allowed[$name]}(); | |
1604 | } else { | |
1605 | trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); | |
1606 | } | |
1607 | } | |
1608 | ||
1609 | /** | |
1610 | * <<magic>> Generic setter. | |
1611 | * Calls the appropriate setter function. | |
1612 | * Issues an E_USER_NOTICE if no valid setter is found. | |
1613 | * | |
1614 | * @param string $name property name | |
1615 | * @param mixed $value parameter passed to setter | |
1616 | */ | |
1617 | public function __set($name, $value) | |
1618 | { | |
1619 | $allowed = array( | |
1620 | 'template_dir' => 'setTemplateDir', | |
1621 | 'config_dir' => 'setConfigDir', | |
1622 | 'plugins_dir' => 'setPluginsDir', | |
1623 | 'compile_dir' => 'setCompileDir', | |
1624 | 'cache_dir' => 'setCacheDir', | |
1625 | ); | |
1626 | ||
1627 | if (isset($allowed[$name])) { | |
1628 | $this->{$allowed[$name]}($value); | |
1629 | } else { | |
1630 | trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); | |
1631 | } | |
2aa91ff2 S |
1632 | } |
1633 | ||
1634 | /** | |
1635 | * Error Handler to mute expected messages | |
1636 | * | |
1637 | * @link http://php.net/set_error_handler | |
1638 | * | |
1639 | * @param integer $errno Error level | |
1640 | * @param $errstr | |
1641 | * @param $errfile | |
1642 | * @param $errline | |
1643 | * @param $errcontext | |
1644 | * | |
1645 | * @return boolean | |
1646 | */ | |
1647 | public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) | |
1648 | { | |
1649 | $_is_muted_directory = false; | |
1650 | ||
1651 | // add the SMARTY_DIR to the list of muted directories | |
1652 | if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) { | |
1653 | $smarty_dir = realpath(SMARTY_DIR); | |
1654 | if ($smarty_dir !== false) { | |
1655 | Smarty::$_muted_directories[SMARTY_DIR] = array( | |
1656 | 'file' => $smarty_dir, | |
1657 | 'length' => strlen($smarty_dir), | |
1658 | ); | |
1659 | } | |
1660 | } | |
1661 | ||
1662 | // walk the muted directories and test against $errfile | |
1663 | foreach (Smarty::$_muted_directories as $key => &$dir) { | |
1664 | if (!$dir) { | |
1665 | // resolve directory and length for speedy comparisons | |
1666 | $file = realpath($key); | |
1667 | if ($file === false) { | |
1668 | // this directory does not exist, remove and skip it | |
1669 | unset(Smarty::$_muted_directories[$key]); | |
1670 | continue; | |
1671 | } | |
1672 | $dir = array( | |
1673 | 'file' => $file, | |
1674 | 'length' => strlen($file), | |
1675 | ); | |
1676 | } | |
1677 | if (!strncmp($errfile, $dir['file'], $dir['length'])) { | |
1678 | $_is_muted_directory = true; | |
1679 | break; | |
1680 | } | |
1681 | } | |
1682 | ||
1683 | // pass to next error handler if this error did not occur inside SMARTY_DIR | |
1684 | // or the error was within smarty but masked to be ignored | |
1685 | if (!$_is_muted_directory || ($errno && $errno & error_reporting())) { | |
1686 | if (Smarty::$_previous_error_handler) { | |
1687 | return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext); | |
1688 | } else { | |
1689 | return false; | |
1690 | } | |
1691 | } | |
1692 | } | |
1693 | ||
1694 | /** | |
1695 | * Enable error handler to mute expected messages | |
1696 | * | |
1697 | * @return void | |
1698 | */ | |
1699 | public static function muteExpectedErrors() | |
1700 | { | |
1701 | /* | |
1702 | error muting is done because some people implemented custom error_handlers using | |
1703 | http://php.net/set_error_handler and for some reason did not understand the following paragraph: | |
1704 | ||
1705 | It is important to remember that the standard PHP error handler is completely bypassed for the | |
1706 | error types specified by error_types unless the callback function returns FALSE. | |
1707 | error_reporting() settings will have no effect and your error handler will be called regardless - | |
1708 | however you are still able to read the current value of error_reporting and act appropriately. | |
1709 | Of particular note is that this value will be 0 if the statement that caused the error was | |
1710 | prepended by the @ error-control operator. | |
1711 | ||
1712 | Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include | |
1713 | - @filemtime() is almost twice as fast as using an additional file_exists() | |
1714 | - between file_exists() and filemtime() a possible race condition is opened, | |
1715 | which does not exist using the simple @filemtime() approach. | |
1716 | */ | |
1717 | $error_handler = array('Smarty', 'mutingErrorHandler'); | |
1718 | $previous = set_error_handler($error_handler); | |
1719 | ||
1720 | // avoid dead loops | |
1721 | if ($previous !== $error_handler) { | |
1722 | Smarty::$_previous_error_handler = $previous; | |
1723 | } | |
1724 | } | |
1725 | ||
1726 | /** | |
1727 | * Disable error handler muting expected messages | |
1728 | * | |
1729 | * @return void | |
1730 | */ | |
1731 | public static function unmuteExpectedErrors() | |
1732 | { | |
1733 | restore_error_handler(); | |
1734 | } | |
1735 | } |