3 * Project: Smarty: the PHP compiling template engine
4 * File: Smarty.class.php
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.
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.
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
23 * @link http://www.smarty.net/
24 * @copyright 2016 New Digital Group, Inc.
25 * @copyright 2016 Uwe Tews
26 * @author Monte Ohrt <monte at ohrt dot com>
34 * set SMARTY_DIR to absolute path to Smarty library files.
35 * Sets SMARTY_DIR only if user application has not already defined it.
37 if (!defined('SMARTY_DIR')) {
38 define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
42 * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
43 * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
45 if (!defined('SMARTY_SYSPLUGINS_DIR')) {
46 define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR);
48 if (!defined('SMARTY_PLUGINS_DIR')) {
49 define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DIRECTORY_SEPARATOR);
51 if (!defined('SMARTY_MBSTRING')) {
52 define('SMARTY_MBSTRING', function_exists('mb_get_info'));
54 if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
55 // UTF-8 can only be done properly when mbstring is available!
57 * @deprecated in favor of Smarty::$_CHARSET
59 define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
61 if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
63 * @deprecated in favor of Smarty::$_DATE_FORMAT
65 define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
69 * Load Smarty_Autoloader
71 if (!class_exists('Smarty_Autoloader')) {
72 include __DIR__ . '/bootstrap.php';
76 * Load always needed external class files
78 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
79 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
80 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
81 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
82 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
83 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
84 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
85 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
86 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
89 * This is the main Smarty class
93 * The following methods will be dynamically loaded by the extension handler when they are called.
94 * They are located in a corresponding Smarty_Internal_Method_xxxx class
96 * @method int clearAllCache(int $exp_time = null, string $type = null)
97 * @method int clearCache(string $template_name, string $cache_id = null, string $compile_id = null, int $exp_time = null, string $type = null)
98 * @method int compileAllTemplates(string $extension = '.tpl', bool $force_compile = false, int $time_limit = 0, int $max_errors = null)
99 * @method int compileAllConfig(string $extension = '.conf', bool $force_compile = false, int $time_limit = 0, int $max_errors = null)
100 * @method int clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
102 class Smarty extends Smarty_Internal_TemplateBase
105 * constant definitions
111 const SMARTY_VERSION = '3.1.31';
114 * define variable scopes
116 const SCOPE_LOCAL = 1;
118 const SCOPE_PARENT = 2;
120 const SCOPE_TPL_ROOT = 4;
122 const SCOPE_ROOT = 8;
124 const SCOPE_SMARTY = 16;
126 const SCOPE_GLOBAL = 32;
129 * define caching modes
131 const CACHING_OFF = 0;
133 const CACHING_LIFETIME_CURRENT = 1;
135 const CACHING_LIFETIME_SAVED = 2;
138 * define constant for clearing cache files be saved expiration dates
140 const CLEAR_EXPIRED = - 1;
143 * define compile check modes
145 const COMPILECHECK_OFF = 0;
147 const COMPILECHECK_ON = 1;
149 const COMPILECHECK_CACHEMISS = 2;
158 const DEBUG_INDIVIDUAL = 2;
161 * modes for handling of "<?php ... ?>" tags in templates.
163 const PHP_PASSTHRU = 0; //-> print tags as plain text
165 const PHP_QUOTE = 1; //-> escape tags as entities
167 const PHP_REMOVE = 2; //-> escape tags as entities
169 const PHP_ALLOW = 3; //-> escape tags as entities
174 const FILTER_POST = 'post';
176 const FILTER_PRE = 'pre';
178 const FILTER_OUTPUT = 'output';
180 const FILTER_VARIABLE = 'variable';
185 const PLUGIN_FUNCTION = 'function';
187 const PLUGIN_BLOCK = 'block';
189 const PLUGIN_COMPILER = 'compiler';
191 const PLUGIN_MODIFIER = 'modifier';
193 const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
196 * Resource caching modes
197 * (not used since 3.1.30)
199 const RESOURCE_CACHE_OFF = 0;
201 const RESOURCE_CACHE_AUTOMATIC = 1; // cache template objects by rules
203 const RESOURCE_CACHE_TEMPLATE = 2; // cache all template objects
205 const RESOURCE_CACHE_ON = 4; // cache source and compiled resources
210 * assigned global tpl vars
212 public static $global_tpl_vars = array();
215 * error handler returned by set_error_handler() in Smarty::muteExpectedErrors()
217 public static $_previous_error_handler = null;
220 * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors()
222 public static $_muted_directories = array();
225 * Flag denoting if Multibyte String functions are available
227 public static $_MBSTRING = SMARTY_MBSTRING;
230 * The character set to adhere to (e.g. "UTF-8")
232 public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
235 * The date format to be used internally
236 * (accepts date() and strftime())
238 public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
241 * Flag denoting if PCRE should run in UTF-8 mode
243 public static $_UTF8_MODIFIER = 'u';
246 * Flag denoting if operating system is windows
248 public static $_IS_WINDOWS = false;
255 * auto literal on delimiters with whitespace
259 public $auto_literal = true;
262 * display error on not assigned variables
266 public $error_unassigned = false;
269 * look up relative file path in include_path
273 public $use_include_path = false;
280 protected $template_dir = array('./templates/');
283 * flags for normalized template directory entries
287 protected $_processedTemplateDir = array();
290 * flag if template_dir is normalized
294 public $_templateDirNormalized = false;
297 * joined template directory string used in cache keys
301 public $_joined_template_dir = null;
308 protected $config_dir = array('./configs/');
311 * flags for normalized template directory entries
315 protected $_processedConfigDir = array();
318 * flag if config_dir is normalized
322 public $_configDirNormalized = false;
325 * joined config directory string used in cache keys
329 public $_joined_config_dir = null;
332 * default template handler
336 public $default_template_handler_func = null;
339 * default config handler
343 public $default_config_handler_func = null;
346 * default plugin handler
350 public $default_plugin_handler_func = null;
357 protected $compile_dir = './templates_c/';
360 * flag if template_dir is normalized
364 public $_compileDirNormalized = false;
371 protected $plugins_dir = array();
374 * flag if plugins_dir is normalized
378 public $_pluginsDirNormalized = false;
385 protected $cache_dir = './cache/';
388 * flag if template_dir is normalized
392 public $_cacheDirNormalized = false;
395 * force template compiling?
399 public $force_compile = false;
402 * check template for modifications?
406 public $compile_check = true;
409 * use sub dirs for compiled/cached files?
413 public $use_sub_dirs = false;
416 * allow ambiguous resources (that are made unique by the resource handler)
420 public $allow_ambiguous_resources = false;
423 * merge compiled includes
427 public $merge_compiled_includes = false;
430 * flag for behaviour when extends: resource and {extends} tag are used simultaneous
431 * if false disable execution of {extends} in templates called by extends resource.
432 * (behaviour as versions < 3.1.28)
436 public $extends_recursion = true;
439 * force cache file creation
443 public $force_cache = false;
446 * template left-delimiter
450 public $left_delimiter = "{";
453 * template right-delimiter
457 public $right_delimiter = "}";
464 * This should be instance of Smarty_Security.
467 * @see Smarty_Security
469 public $security_class = 'Smarty_Security';
472 * implementation of security class
474 * @var Smarty_Security
476 public $security_policy = null;
479 * controls handling of PHP-blocks
483 public $php_handling = self::PHP_PASSTHRU;
486 * controls if the php template file resource is allowed
490 public $allow_php_templates = false;
495 * Setting this to true enables the debug-console.
499 public $debugging = false;
502 * This determines if debugging is enable-able from the browser.
504 * <li>NONE => no debugging control allowed</li>
505 * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
510 public $debugging_ctrl = 'NONE';
513 * Name of debugging URL-param.
514 * Only used when $debugging_ctrl is set to 'URL'.
515 * The name of the URL-parameter that activates debugging.
519 public $smarty_debug_id = 'SMARTY_DEBUG';
522 * Path of debug template.
526 public $debug_tpl = null;
529 * When set, smarty uses this value as error_reporting-level.
533 public $error_reporting = null;
536 * config var settings
540 * Controls whether variables with the same name overwrite each other.
544 public $config_overwrite = true;
547 * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
551 public $config_booleanize = true;
554 * Controls whether hidden config sections/vars are read from the file.
558 public $config_read_hidden = false;
567 * locking concurrent compiles
571 public $compile_locking = true;
574 * Controls whether cache resources should use locking mechanism
578 public $cache_locking = false;
581 * seconds to wait for acquiring a lock before ignoring the write lock
585 public $locking_timeout = 10;
590 * resource type used if none given
591 * Must be an valid key of $registered_resources.
595 public $default_resource_type = 'file';
599 * Must be an element of $cache_resource_types.
603 public $caching_type = 'file';
610 public $default_config_type = 'file';
613 * check If-Modified-Since headers
617 public $cache_modified_check = false;
624 public $registered_plugins = array();
631 public $registered_objects = array();
638 public $registered_classes = array();
645 public $registered_filters = array();
648 * registered resources
652 public $registered_resources = array();
655 * registered cache resources
659 public $registered_cache_resources = array();
666 public $autoload_filters = array();
673 public $default_modifiers = array();
676 * autoescape variable output
680 public $escape_html = false;
683 * start time for execution time calculation
687 public $start_time = 0;
690 * required by the compiler for BC
694 public $_current_file = null;
697 * internal flag to enable parser debugging
701 public $_parserdebug = false;
704 * This object type (Smarty = 1, template = 2, data = 4)
708 public $_objType = 1;
713 * @var Smarty_Internal_Debug
715 public $_debug = null;
718 * Directory separator
722 public $ds = DIRECTORY_SEPARATOR;
729 private $obsoleteProperties = array('resource_caching', 'template_resource_caching', 'direct_access_security',
730 '_dir_perms', '_file_perms', 'plugin_search_order',
731 'inheritance_merge_compiled_includes', 'resource_cache_mode',);
734 * List of private properties which will call getter/setter on a direct access
738 private $accessMap = array('template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir',
739 'plugins_dir' => 'PluginsDir', 'compile_dir' => 'CompileDir',
740 'cache_dir' => 'CacheDir',);
745 * Initialize new Smarty object
747 public function __construct()
749 $this->_clearTemplateCache();
750 parent::__construct();
751 if (is_callable('mb_internal_encoding')) {
752 mb_internal_encoding(Smarty::$_CHARSET);
754 $this->start_time = microtime(true);
756 if (isset($_SERVER[ 'SCRIPT_NAME' ])) {
757 Smarty::$global_tpl_vars[ 'SCRIPT_NAME' ] = new Smarty_Variable($_SERVER[ 'SCRIPT_NAME' ]);
760 // Check if we're running on windows
761 Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
762 // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
763 if (Smarty::$_CHARSET !== 'UTF-8') {
764 Smarty::$_UTF8_MODIFIER = '';
769 * Check if a template resource exists
771 * @param string $resource_name template name
773 * @return boolean status
775 public function templateExists($resource_name)
777 // create source object
778 $source = Smarty_Template_Source::load(null, $this, $resource_name);
779 return $source->exists;
783 * Loads security class and enables security
785 * @param string|Smarty_Security $security_class if a string is used, it must be class-name
787 * @return Smarty current Smarty instance for chaining
788 * @throws SmartyException when an invalid class name is provided
790 public function enableSecurity($security_class = null)
792 Smarty_Security::enableSecurity($this, $security_class);
799 * @return Smarty current Smarty instance for chaining
801 public function disableSecurity()
803 $this->security_policy = null;
809 * Set template directory
811 * @param string|array $template_dir directory(s) of template sources
812 * @param bool $isConfig true for config_dir
814 * @return \Smarty current Smarty instance for chaining
816 public function setTemplateDir($template_dir, $isConfig = false)
819 $this->config_dir = array();
820 $this->_processedConfigDir = array();
822 $this->template_dir = array();
823 $this->_processedTemplateDir = array();
825 $this->addTemplateDir($template_dir, null, $isConfig);
830 * Add template directory(s)
832 * @param string|array $template_dir directory(s) of template sources
833 * @param string $key of the array element to assign the template dir to
834 * @param bool $isConfig true for config_dir
836 * @return Smarty current Smarty instance for chaining
838 public function addTemplateDir($template_dir, $key = null, $isConfig = false)
841 $processed = &$this->_processedConfigDir;
842 $dir = &$this->config_dir;
843 $this->_configDirNormalized = false;
845 $processed = &$this->_processedTemplateDir;
846 $dir = &$this->template_dir;
847 $this->_templateDirNormalized = false;
849 if (is_array($template_dir)) {
850 foreach ($template_dir as $k => $v) {
852 // indexes are not merged but appended
855 // string indexes are overridden
857 unset($processed[ $key ]);
862 // override directory at specified index
863 $dir[ $key ] = $template_dir;
864 unset($processed[ $key ]);
866 // append new directory
867 $dir[] = $template_dir;
874 * Get template directories
876 * @param mixed $index index of directory to get, null to get all
877 * @param bool $isConfig true for config_dir
879 * @return array list of template directories, or directory of $index
881 public function getTemplateDir($index = null, $isConfig = false)
884 $dir = &$this->config_dir;
886 $dir = &$this->template_dir;
888 if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) {
889 $this->_nomalizeTemplateConfig($isConfig);
891 if ($index !== null) {
892 return isset($dir[ $index ]) ? $dir[ $index ] : null;
898 * Set config directory
902 * @return Smarty current Smarty instance for chaining
904 public function setConfigDir($config_dir)
906 return $this->setTemplateDir($config_dir, true);
910 * Add config directory(s)
912 * @param string|array $config_dir directory(s) of config sources
913 * @param mixed $key key of the array element to assign the config dir to
915 * @return Smarty current Smarty instance for chaining
917 public function addConfigDir($config_dir, $key = null)
919 return $this->addTemplateDir($config_dir, $key, true);
923 * Get config directory
925 * @param mixed $index index of directory to get, null to get all
927 * @return array configuration directory
929 public function getConfigDir($index = null)
931 return $this->getTemplateDir($index, true);
935 * Set plugins directory
937 * @param string|array $plugins_dir directory(s) of plugins
939 * @return Smarty current Smarty instance for chaining
941 public function setPluginsDir($plugins_dir)
943 $this->plugins_dir = (array) $plugins_dir;
944 $this->_pluginsDirNormalized = false;
949 * Adds directory of plugin files
951 * @param null|array $plugins_dir
953 * @return Smarty current Smarty instance for chaining
955 public function addPluginsDir($plugins_dir)
957 if (empty($this->plugins_dir)) {
958 $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
960 $this->plugins_dir = array_merge($this->plugins_dir, (array) $plugins_dir);
961 $this->_pluginsDirNormalized = false;
966 * Get plugin directories
968 * @return array list of plugin directories
970 public function getPluginsDir()
972 if (empty($this->plugins_dir)) {
973 $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
974 $this->_pluginsDirNormalized = false;
976 if (!$this->_pluginsDirNormalized) {
977 if (!is_array($this->plugins_dir)) {
978 $this->plugins_dir = (array) $this->plugins_dir;
980 foreach ($this->plugins_dir as $k => $v) {
981 $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, "/\\") . $this->ds, true);
983 $this->_cache[ 'plugin_files' ] = array();
984 $this->_pluginsDirNormalized = true;
986 return $this->plugins_dir;
991 * @param string $compile_dir directory to store compiled templates in
993 * @return Smarty current Smarty instance for chaining
995 public function setCompileDir($compile_dir)
997 $this->_normalizeDir('compile_dir', $compile_dir);
998 $this->_compileDirNormalized = true;
1003 * Get compiled directory
1005 * @return string path to compiled templates
1007 public function getCompileDir()
1009 if (!$this->_compileDirNormalized) {
1010 $this->_normalizeDir('compile_dir', $this->compile_dir);
1011 $this->_compileDirNormalized = true;
1013 return $this->compile_dir;
1017 * Set cache directory
1019 * @param string $cache_dir directory to store cached templates in
1021 * @return Smarty current Smarty instance for chaining
1023 public function setCacheDir($cache_dir)
1025 $this->_normalizeDir('cache_dir', $cache_dir);
1026 $this->_cacheDirNormalized = true;
1031 * Get cache directory
1033 * @return string path of cache directory
1035 public function getCacheDir()
1037 if (!$this->_cacheDirNormalized) {
1038 $this->_normalizeDir('cache_dir', $this->cache_dir);
1039 $this->_cacheDirNormalized = true;
1041 return $this->cache_dir;
1045 * Normalize and set directory string
1047 * @param string $dirName cache_dir or compile_dir
1048 * @param string $dir filepath of folder
1050 private function _normalizeDir($dirName, $dir)
1052 $this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . $this->ds, true);
1053 if (!isset(Smarty::$_muted_directories[ $this->{$dirName} ])) {
1054 Smarty::$_muted_directories[ $this->{$dirName} ] = null;
1059 * Normalize template_dir or config_dir
1061 * @param bool $isConfig true for config_dir
1064 private function _nomalizeTemplateConfig($isConfig)
1067 $processed = &$this->_processedConfigDir;
1068 $dir = &$this->config_dir;
1070 $processed = &$this->_processedTemplateDir;
1071 $dir = &$this->template_dir;
1073 if (!is_array($dir)) {
1074 $dir = (array) $dir;
1076 foreach ($dir as $k => $v) {
1077 if (!isset($processed[ $k ])) {
1078 $dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . $this->ds, true);
1079 $processed[ $k ] = true;
1082 $isConfig ? $this->_configDirNormalized = true : $this->_templateDirNormalized = true;
1083 $isConfig ? $this->_joined_config_dir = join('#', $this->config_dir) :
1084 $this->_joined_template_dir = join('#', $this->template_dir);
1088 * creates a template object
1090 * @param string $template the resource handle of the template file
1091 * @param mixed $cache_id cache id to be used with this template
1092 * @param mixed $compile_id compile id to be used with this template
1093 * @param object $parent next higher level of Smarty variables
1094 * @param boolean $do_clone flag is Smarty object shall be cloned
1096 * @return object template object
1098 public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
1100 if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
1101 $parent = $cache_id;
1104 if ($parent !== null && is_array($parent)) {
1110 if (!$this->_templateDirNormalized) {
1111 $this->_nomalizeTemplateConfig(false);
1113 $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id);
1115 if ($this->caching && isset(Smarty_Internal_Template::$isCacheTplObj[ $_templateId ])) {
1116 $tpl = $do_clone ? clone Smarty_Internal_Template::$isCacheTplObj[ $_templateId ] :
1117 Smarty_Internal_Template::$isCacheTplObj[ $_templateId ];
1118 $tpl->inheritance = null;
1119 $tpl->tpl_vars = $tpl->config_vars = array();
1120 } else if (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) {
1121 $tpl = clone Smarty_Internal_Template::$tplObjCache[ $_templateId ];
1122 $tpl->inheritance = null;
1123 $tpl->tpl_vars = $tpl->config_vars = array();
1125 /* @var Smarty_Internal_Template $tpl */
1126 $tpl = new $this->template_class($template, $this, null, $cache_id, $compile_id, null, null);
1127 $tpl->templateId = $_templateId;
1130 $tpl->smarty = clone $tpl->smarty;
1132 $tpl->parent = $parent ? $parent : $this;
1133 // fill data if present
1134 if (!empty($data) && is_array($data)) {
1135 // set up variable values
1136 foreach ($data as $_key => $_val) {
1137 $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val);
1140 if ($this->debugging || $this->debugging_ctrl == 'URL') {
1141 $tpl->smarty->_debug = new Smarty_Internal_Debug();
1142 // check URL debugging control
1143 if (!$this->debugging && $this->debugging_ctrl == 'URL') {
1144 $tpl->smarty->_debug->debugUrl($tpl->smarty);
1151 * Takes unknown classes and loads plugin files for them
1152 * class name format: Smarty_PluginType_PluginName
1153 * plugin filename format: plugintype.pluginname.php
1155 * @param string $plugin_name class plugin name to load
1156 * @param bool $check check if already loaded
1158 * @throws SmartyException
1159 * @return string |boolean filepath of loaded file or false
1161 public function loadPlugin($plugin_name, $check = true)
1163 return $this->ext->loadPlugin->loadPlugin($this, $plugin_name, $check);
1167 * Get unique template id
1169 * @param string $template_name
1170 * @param null|mixed $cache_id
1171 * @param null|mixed $compile_id
1172 * @param null $caching
1173 * @param \Smarty_Internal_Template $template
1177 public function _getTemplateId($template_name, $cache_id = null, $compile_id = null, $caching = null,
1178 Smarty_Internal_Template $template = null)
1180 $template_name = (strpos($template_name, ':') === false) ? "{$this->default_resource_type}:{$template_name}" :
1182 $cache_id = $cache_id === null ? $this->cache_id : $cache_id;
1183 $compile_id = $compile_id === null ? $this->compile_id : $compile_id;
1184 $caching = (int) ($caching === null ? $this->caching : $caching);
1186 if ((isset($template) && strpos($template_name, ':.') !== false) || $this->allow_ambiguous_resources) {
1188 Smarty_Resource::getUniqueTemplateName((isset($template) ? $template : $this), $template_name) .
1189 "#{$cache_id}#{$compile_id}#{$caching}";
1191 $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}";
1193 if (isset($_templateId[ 150 ])) {
1194 $_templateId = sha1($_templateId);
1196 return $_templateId;
1201 * - remove /./ and /../
1202 * - make it absolute if required
1204 * @param string $path file path
1205 * @param bool $realpath if true - convert to absolute
1206 * false - convert to relative
1207 * null - keep as it is but remove /./ /../
1211 public function _realpath($path, $realpath = null)
1213 $nds = $this->ds == '/' ? '\\' : '/';
1214 // normalize $this->ds
1215 $path = str_replace($nds, $this->ds, $path);
1216 preg_match('%^(?<root>(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(?:[[:print:]]*))$%',
1218 $path = $parts[ 'path' ];
1219 if ($parts[ 'root' ] == '\\') {
1220 $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ];
1222 if ($realpath !== null && !$parts[ 'root' ]) {
1223 $path = getcwd() . $this->ds . $path;
1226 // remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns
1227 $path = preg_replace('#([\\\\/]([.]?[\\\\/])+)#', $this->ds, $path);
1228 // resolve '..DIRECTORY_SEPARATOR' pattern, smallest first
1229 if (strpos($path, '..' . $this->ds) != false &&
1230 preg_match_all('#(([.]?[\\\\/])*([.][.])[\\\\/]([.]?[\\\\/])*)+#', $path, $match)
1233 foreach ($match[ 0 ] as $m) {
1234 $counts[] = (int) ((strlen($m) - 1) / 3);
1237 foreach ($counts as $count) {
1238 $path = preg_replace('#(([\\\\/]([.]?[\\\\/])*[^\\\\/.]+){' . $count .
1239 '}[\\\\/]([.]?[\\\\/])*([.][.][\\\\/]([.]?[\\\\/])*){' . $count . '})(?=[^.])#',
1244 return $parts[ 'root' ] . $path;
1248 * Empty template objects cache
1250 public function _clearTemplateCache()
1252 Smarty_Internal_Template::$isCacheTplObj = array();
1253 Smarty_Internal_Template::$tplObjCache = array();
1261 public function _getSmartyObj()
1267 * @param boolean $compile_check
1269 public function setCompileCheck($compile_check)
1271 $this->compile_check = $compile_check;
1275 * @param boolean $use_sub_dirs
1277 public function setUseSubDirs($use_sub_dirs)
1279 $this->use_sub_dirs = $use_sub_dirs;
1283 * @param int $error_reporting
1285 public function setErrorReporting($error_reporting)
1287 $this->error_reporting = $error_reporting;
1291 * @param boolean $escape_html
1293 public function setEscapeHtml($escape_html)
1295 $this->escape_html = $escape_html;
1299 * @param boolean $auto_literal
1301 public function setAutoLiteral($auto_literal)
1303 $this->auto_literal = $auto_literal;
1307 * @param boolean $force_compile
1309 public function setForceCompile($force_compile)
1311 $this->force_compile = $force_compile;
1315 * @param boolean $merge_compiled_includes
1317 public function setMergeCompiledIncludes($merge_compiled_includes)
1319 $this->merge_compiled_includes = $merge_compiled_includes;
1323 * @param string $left_delimiter
1325 public function setLeftDelimiter($left_delimiter)
1327 $this->left_delimiter = $left_delimiter;
1331 * @param string $right_delimiter
1333 public function setRightDelimiter($right_delimiter)
1335 $this->right_delimiter = $right_delimiter;
1339 * @param boolean $debugging
1341 public function setDebugging($debugging)
1343 $this->debugging = $debugging;
1347 * @param boolean $config_overwrite
1349 public function setConfigOverwrite($config_overwrite)
1351 $this->config_overwrite = $config_overwrite;
1355 * @param boolean $config_booleanize
1357 public function setConfigBooleanize($config_booleanize)
1359 $this->config_booleanize = $config_booleanize;
1363 * @param boolean $config_read_hidden
1365 public function setConfigReadHidden($config_read_hidden)
1367 $this->config_read_hidden = $config_read_hidden;
1371 * @param boolean $compile_locking
1373 public function setCompileLocking($compile_locking)
1375 $this->compile_locking = $compile_locking;
1379 * @param string $default_resource_type
1381 public function setDefaultResourceType($default_resource_type)
1383 $this->default_resource_type = $default_resource_type;
1387 * @param string $caching_type
1389 public function setCachingType($caching_type)
1391 $this->caching_type = $caching_type;
1397 * @param null $errors
1399 public function testInstall(&$errors = null)
1401 Smarty_Internal_TestInstall::testInstall($this, $errors);
1405 * <<magic>> Generic getter.
1406 * Calls the appropriate getter function.
1407 * Issues an E_USER_NOTICE if no valid getter is found.
1409 * @param string $name property name
1413 public function __get($name)
1415 if (isset($this->accessMap[ $name ])) {
1416 $method = 'get' . $this->accessMap[ $name ];
1417 return $this->{$method}();
1418 } elseif (isset($this->_cache[ $name ])) {
1419 return $this->_cache[ $name ];
1420 } elseif (in_array($name, $this->obsoleteProperties)) {
1423 trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1429 * <<magic>> Generic setter.
1430 * Calls the appropriate setter function.
1431 * Issues an E_USER_NOTICE if no valid setter is found.
1433 * @param string $name property name
1434 * @param mixed $value parameter passed to setter
1436 public function __set($name, $value)
1438 if (isset($this->accessMap[ $name ])) {
1439 $method = 'set' . $this->accessMap[ $name ];
1440 $this->{$method}($value);
1441 } elseif (in_array($name, $this->obsoleteProperties)) {
1444 if (is_object($value) && method_exists($value, $name)) {
1445 $this->$name = $value;
1447 trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1453 * Error Handler to mute expected messages
1455 * @link http://php.net/set_error_handler
1457 * @param integer $errno Error level
1461 * @param $errcontext
1465 public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext)
1467 $_is_muted_directory = false;
1469 // add the SMARTY_DIR to the list of muted directories
1470 if (!isset(Smarty::$_muted_directories[ SMARTY_DIR ])) {
1471 $smarty_dir = realpath(SMARTY_DIR);
1472 if ($smarty_dir !== false) {
1473 Smarty::$_muted_directories[ SMARTY_DIR ] =
1474 array('file' => $smarty_dir, 'length' => strlen($smarty_dir),);
1478 // walk the muted directories and test against $errfile
1479 foreach (Smarty::$_muted_directories as $key => &$dir) {
1481 // resolve directory and length for speedy comparisons
1482 $file = realpath($key);
1483 if ($file === false) {
1484 // this directory does not exist, remove and skip it
1485 unset(Smarty::$_muted_directories[ $key ]);
1488 $dir = array('file' => $file, 'length' => strlen($file),);
1490 if (!strncmp($errfile, $dir[ 'file' ], $dir[ 'length' ])) {
1491 $_is_muted_directory = true;
1495 // pass to next error handler if this error did not occur inside SMARTY_DIR
1496 // or the error was within smarty but masked to be ignored
1497 if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
1498 if (Smarty::$_previous_error_handler) {
1499 return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline,
1509 * Enable error handler to mute expected messages
1513 public static function muteExpectedErrors()
1516 error muting is done because some people implemented custom error_handlers using
1517 http://php.net/set_error_handler and for some reason did not understand the following paragraph:
1519 It is important to remember that the standard PHP error handler is completely bypassed for the
1520 error types specified by error_types unless the callback function returns FALSE.
1521 error_reporting() settings will have no effect and your error handler will be called regardless -
1522 however you are still able to read the current value of error_reporting and act appropriately.
1523 Of particular note is that this value will be 0 if the statement that caused the error was
1524 prepended by the @ error-control operator.
1526 Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include
1527 - @filemtime() is almost twice as fast as using an additional file_exists()
1528 - between file_exists() and filemtime() a possible race condition is opened,
1529 which does not exist using the simple @filemtime() approach.
1531 $error_handler = array('Smarty', 'mutingErrorHandler');
1532 $previous = set_error_handler($error_handler);
1535 if ($previous !== $error_handler) {
1536 Smarty::$_previous_error_handler = $previous;
1541 * Disable error handler muting expected messages
1545 public static function unmuteExpectedErrors()
1547 restore_error_handler();