php封装的smarty类完整实例


Posted in PHP onOctober 19, 2016

本文实例讲述了php封装的smarty类。分享给大家供大家参考,具体如下:

<?php
/**
 * Project:   Smarty: the PHP compiling template engine
 * File:    Smarty.class.php
 * SVN:     $Id: Smarty.class.php 4848 2014-06-08 18:12:09Z Uwe.Tews@googlemail.com $
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 * For questions, help, comments, discussion, etc., please join the
 * Smarty mailing list. Send a blank e-mail to
 * smarty-discussion-subscribe@googlegroups.com
 *
 * @link   http://www.smarty.net/
 * @copyright 2008 New Digital Group, Inc.
 * @author  Monte Ohrt <monte at ohrt dot com>
 * @author  Uwe Tews
 * @author  Rodney Rehm
 * @package  Smarty
 * @version  3.1.19
 */
/**
 * define shorthand directory separator constant
 */
if (!defined('DS')) {
  define('DS', DIRECTORY_SEPARATOR);
}
/**
 * set SMARTY_DIR to absolute path to Smarty library files.
 * Sets SMARTY_DIR only if user application has not already defined it.
 */
if (!defined('SMARTY_DIR')) {
  define('SMARTY_DIR', dirname(__FILE__) . DS);
}
/**
 * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
 * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
 */
if (!defined('SMARTY_SYSPLUGINS_DIR')) {
  define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS);
}
if (!defined('SMARTY_PLUGINS_DIR')) {
  define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS);
}
if (!defined('SMARTY_MBSTRING')) {
  define('SMARTY_MBSTRING', function_exists('mb_split'));
}
if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
  // UTF-8 can only be done properly when mbstring is available!
  /**
   * @deprecated in favor of Smarty::$_CHARSET
   */
  define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
}
if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
  /**
   * @deprecated in favor of Smarty::$_DATE_FORMAT
   */
  define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
}
/**
 * register the class autoloader
 */
if (!defined('SMARTY_SPL_AUTOLOAD')) {
  define('SMARTY_SPL_AUTOLOAD', 0);
}
if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false) {
  $registeredAutoLoadFunctions = spl_autoload_functions();
  if (!isset($registeredAutoLoadFunctions['spl_autoload'])) {
    spl_autoload_register();
  }
} else {
  spl_autoload_register('smartyAutoload');
}
/**
 * Load always needed external class files
 */
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_cacheresource_file.php';
/**
 * This is the main Smarty class
 *
 * @package Smarty
 */
class Smarty extends Smarty_Internal_TemplateBase
{
  /**#@+
   * constant definitions
   */
  /**
   * smarty version
   */
  const SMARTY_VERSION = 'Smarty-3.1.19';
  /**
   * define variable scopes
   */
  const SCOPE_LOCAL = 0;
  const SCOPE_PARENT = 1;
  const SCOPE_ROOT = 2;
  const SCOPE_GLOBAL = 3;
  /**
   * define caching modes
   */
  const CACHING_OFF = 0;
  const CACHING_LIFETIME_CURRENT = 1;
  const CACHING_LIFETIME_SAVED = 2;
  /**
   * define constant for clearing cache files be saved expiration datees
   */
  const CLEAR_EXPIRED = - 1;
  /**
   * define compile check modes
   */
  const COMPILECHECK_OFF = 0;
  const COMPILECHECK_ON = 1;
  const COMPILECHECK_CACHEMISS = 2;
  /**
   * modes for handling of "<?php ... ?>" tags in templates.
   */
  const PHP_PASSTHRU = 0; //-> print tags as plain text
  const PHP_QUOTE = 1; //-> escape tags as entities
  const PHP_REMOVE = 2; //-> escape tags as entities
  const PHP_ALLOW = 3; //-> escape tags as entities
  /**
   * filter types
   */
  const FILTER_POST = 'post';
  const FILTER_PRE = 'pre';
  const FILTER_OUTPUT = 'output';
  const FILTER_VARIABLE = 'variable';
  /**
   * plugin types
   */
  const PLUGIN_FUNCTION = 'function';
  const PLUGIN_BLOCK = 'block';
  const PLUGIN_COMPILER = 'compiler';
  const PLUGIN_MODIFIER = 'modifier';
  const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
  /**#@-*/
  /**
   * assigned global tpl vars
   */
  public static $global_tpl_vars = array();
  /**
   * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors()
   */
  public static $_previous_error_handler = null;
  /**
   * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors()
   */
  public static $_muted_directories = array();
  /**
   * Flag denoting if Multibyte String functions are available
   */
  public static $_MBSTRING = SMARTY_MBSTRING;
  /**
   * The character set to adhere to (e.g. "UTF-8")
   */
  public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
  /**
   * The date format to be used internally
   * (accepts date() and strftime())
   */
  public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
  /**
   * Flag denoting if PCRE should run in UTF-8 mode
   */
  public static $_UTF8_MODIFIER = 'u';
  /**
   * Flag denoting if operating system is windows
   */
  public static $_IS_WINDOWS = false;
  /**#@+
   * variables
   */
  /**
   * auto literal on delimiters with whitspace
   *
   * @var boolean
   */
  public $auto_literal = true;
  /**
   * display error on not assigned variables
   *
   * @var boolean
   */
  public $error_unassigned = false;
  /**
   * look up relative filepaths in include_path
   *
   * @var boolean
   */
  public $use_include_path = false;
  /**
   * template directory
   *
   * @var array
   */
  private $template_dir = array();
  /**
   * joined template directory string used in cache keys
   *
   * @var string
   */
  public $joined_template_dir = null;
  /**
   * joined config directory string used in cache keys
   *
   * @var string
   */
  public $joined_config_dir = null;
  /**
   * default template handler
   *
   * @var callable
   */
  public $default_template_handler_func = null;
  /**
   * default config handler
   *
   * @var callable
   */
  public $default_config_handler_func = null;
  /**
   * default plugin handler
   *
   * @var callable
   */
  public $default_plugin_handler_func = null;
  /**
   * compile directory
   *
   * @var string
   */
  private $compile_dir = null;
  /**
   * plugins directory
   *
   * @var array
   */
  private $plugins_dir = array();
  /**
   * cache directory
   *
   * @var string
   */
  private $cache_dir = null;
  /**
   * config directory
   *
   * @var array
   */
  private $config_dir = array();
  /**
   * force template compiling?
   *
   * @var boolean
   */
  public $force_compile = false;
  /**
   * check template for modifications?
   *
   * @var boolean
   */
  public $compile_check = true;
  /**
   * use sub dirs for compiled/cached files?
   *
   * @var boolean
   */
  public $use_sub_dirs = false;
  /**
   * allow ambiguous resources (that are made unique by the resource handler)
   *
   * @var boolean
   */
  public $allow_ambiguous_resources = false;
  /**
   * caching enabled
   *
   * @var boolean
   */
  public $caching = false;
  /**
   * merge compiled includes
   *
   * @var boolean
   */
  public $merge_compiled_includes = false;
  /**
   * template inheritance merge compiled includes
   *
   * @var boolean
   */
  public $inheritance_merge_compiled_includes = true;
  /**
   * cache lifetime in seconds
   *
   * @var integer
   */
  public $cache_lifetime = 3600;
  /**
   * force cache file creation
   *
   * @var boolean
   */
  public $force_cache = false;
  /**
   * Set this if you want different sets of cache files for the same
   * templates.
   *
   * @var string
   */
  public $cache_id = null;
  /**
   * Set this if you want different sets of compiled files for the same
   * templates.
   *
   * @var string
   */
  public $compile_id = null;
  /**
   * template left-delimiter
   *
   * @var string
   */
  public $left_delimiter = "{";
  /**
   * template right-delimiter
   *
   * @var string
   */
  public $right_delimiter = "}";
  /**#@+
   * security
   */
  /**
   * class name
   * This should be instance of Smarty_Security.
   *
   * @var string
   * @see Smarty_Security
   */
  public $security_class = 'Smarty_Security';
  /**
   * implementation of security class
   *
   * @var Smarty_Security
   */
  public $security_policy = null;
  /**
   * controls handling of PHP-blocks
   *
   * @var integer
   */
  public $php_handling = self::PHP_PASSTHRU;
  /**
   * controls if the php template file resource is allowed
   *
   * @var bool
   */
  public $allow_php_templates = false;
  /**
   * Should compiled-templates be prevented from being called directly?
   * {@internal
   * Currently used by Smarty_Internal_Template only.
   * }}
   *
   * @var boolean
   */
  public $direct_access_security = true;
  /**#@-*/
  /**
   * debug mode
   * Setting this to true enables the debug-console.
   *
   * @var boolean
   */
  public $debugging = false;
  /**
   * This determines if debugging is enable-able from the browser.
   * <ul>
   * <li>NONE => no debugging control allowed</li>
   * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
   * </ul>
   *
   * @var string
   */
  public $debugging_ctrl = 'NONE';
  /**
   * Name of debugging URL-param.
   * Only used when $debugging_ctrl is set to 'URL'.
   * The name of the URL-parameter that activates debugging.
   *
   * @var type
   */
  public $smarty_debug_id = 'SMARTY_DEBUG';
  /**
   * Path of debug template.
   *
   * @var string
   */
  public $debug_tpl = null;
  /**
   * When set, smarty uses this value as error_reporting-level.
   *
   * @var int
   */
  public $error_reporting = null;
  /**
   * Internal flag for getTags()
   *
   * @var boolean
   */
  public $get_used_tags = false;
  /**#@+
   * config var settings
   */
  /**
   * Controls whether variables with the same name overwrite each other.
   *
   * @var boolean
   */
  public $config_overwrite = true;
  /**
   * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
   *
   * @var boolean
   */
  public $config_booleanize = true;
  /**
   * Controls whether hidden config sections/vars are read from the file.
   *
   * @var boolean
   */
  public $config_read_hidden = false;
  /**#@-*/
  /**#@+
   * resource locking
   */
  /**
   * locking concurrent compiles
   *
   * @var boolean
   */
  public $compile_locking = true;
  /**
   * Controls whether cache resources should emply locking mechanism
   *
   * @var boolean
   */
  public $cache_locking = false;
  /**
   * seconds to wait for acquiring a lock before ignoring the write lock
   *
   * @var float
   */
  public $locking_timeout = 10;
  /**#@-*/
  /**
   * global template functions
   *
   * @var array
   */
  public $template_functions = array();
  /**
   * resource type used if none given
   * Must be an valid key of $registered_resources.
   *
   * @var string
   */
  public $default_resource_type = 'file';
  /**
   * caching type
   * Must be an element of $cache_resource_types.
   *
   * @var string
   */
  public $caching_type = 'file';
  /**
   * internal config properties
   *
   * @var array
   */
  public $properties = array();
  /**
   * config type
   *
   * @var string
   */
  public $default_config_type = 'file';
  /**
   * cached template objects
   *
   * @var array
   */
  public $template_objects = array();
  /**
   * check If-Modified-Since headers
   *
   * @var boolean
   */
  public $cache_modified_check = false;
  /**
   * registered plugins
   *
   * @var array
   */
  public $registered_plugins = array();
  /**
   * plugin search order
   *
   * @var array
   */
  public $plugin_search_order = array('function', 'block', 'compiler', 'class');
  /**
   * registered objects
   *
   * @var array
   */
  public $registered_objects = array();
  /**
   * registered classes
   *
   * @var array
   */
  public $registered_classes = array();
  /**
   * registered filters
   *
   * @var array
   */
  public $registered_filters = array();
  /**
   * registered resources
   *
   * @var array
   */
  public $registered_resources = array();
  /**
   * resource handler cache
   *
   * @var array
   */
  public $_resource_handlers = array();
  /**
   * registered cache resources
   *
   * @var array
   */
  public $registered_cache_resources = array();
  /**
   * cache resource handler cache
   *
   * @var array
   */
  public $_cacheresource_handlers = array();
  /**
   * autoload filter
   *
   * @var array
   */
  public $autoload_filters = array();
  /**
   * default modifier
   *
   * @var array
   */
  public $default_modifiers = array();
  /**
   * autoescape variable output
   *
   * @var boolean
   */
  public $escape_html = false;
  /**
   * global internal smarty vars
   *
   * @var array
   */
  public static $_smarty_vars = array();
  /**
   * start time for execution time calculation
   *
   * @var int
   */
  public $start_time = 0;
  /**
   * default file permissions
   *
   * @var int
   */
  public $_file_perms = 0644;
  /**
   * default dir permissions
   *
   * @var int
   */
  public $_dir_perms = 0771;
  /**
   * block tag hierarchy
   *
   * @var array
   */
  public $_tag_stack = array();
  /**
   * self pointer to Smarty object
   *
   * @var Smarty
   */
  public $smarty;
  /**
   * required by the compiler for BC
   *
   * @var string
   */
  public $_current_file = null;
  /**
   * internal flag to enable parser debugging
   *
   * @var bool
   */
  public $_parserdebug = false;
  /**
   * Saved parameter of merged templates during compilation
   *
   * @var array
   */
  public $merged_templates_func = array();
  /**#@-*/
  /**
   * Initialize new Smarty object
   */
  public function __construct()
  {
    // selfpointer needed by some other class methods
    $this->smarty = $this;
    if (is_callable('mb_internal_encoding')) {
      mb_internal_encoding(Smarty::$_CHARSET);
    }
    $this->start_time = microtime(true);
    // set default dirs
    $this->setTemplateDir('.' . DS . 'templates' . DS)
      ->setCompileDir('.' . DS . 'templates_c' . DS)
      ->setPluginsDir(SMARTY_PLUGINS_DIR)
      ->setCacheDir('.' . DS . 'cache' . DS)
      ->setConfigDir('.' . DS . 'configs' . DS);
    $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl';
    if (isset($_SERVER['SCRIPT_NAME'])) {
      $this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']);
    }
  }
  /**
   * Class destructor
   */
  public function __destruct()
  {
    // intentionally left blank
  }
  /**
   * <<magic>> set selfpointer on cloned object
   */
  public function __clone()
  {
    $this->smarty = $this;
  }
  /**
   * <<magic>> Generic getter.
   * Calls the appropriate getter function.
   * Issues an E_USER_NOTICE if no valid getter is found.
   *
   * @param string $name property name
   *
   * @return mixed
   */
  public function __get($name)
  {
    $allowed = array(
      'template_dir' => 'getTemplateDir',
      'config_dir'  => 'getConfigDir',
      'plugins_dir' => 'getPluginsDir',
      'compile_dir' => 'getCompileDir',
      'cache_dir'  => 'getCacheDir',
    );
    if (isset($allowed[$name])) {
      return $this->{$allowed[$name]}();
    } else {
      trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
    }
  }
  /**
   * <<magic>> Generic setter.
   * Calls the appropriate setter function.
   * Issues an E_USER_NOTICE if no valid setter is found.
   *
   * @param string $name property name
   * @param mixed $value parameter passed to setter
   */
  public function __set($name, $value)
  {
    $allowed = array(
      'template_dir' => 'setTemplateDir',
      'config_dir'  => 'setConfigDir',
      'plugins_dir' => 'setPluginsDir',
      'compile_dir' => 'setCompileDir',
      'cache_dir'  => 'setCacheDir',
    );
    if (isset($allowed[$name])) {
      $this->{$allowed[$name]}($value);
    } else {
      trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
    }
  }
  /**
   * Check if a template resource exists
   *
   * @param string $resource_name template name
   *
   * @return boolean status
   */
  public function templateExists($resource_name)
  {
    // create template object
    $save = $this->template_objects;
    $tpl = new $this->template_class($resource_name, $this);
    // check if it does exists
    $result = $tpl->source->exists;
    $this->template_objects = $save;
    return $result;
  }
  /**
   * Returns a single or all global variables
   *
   * @param string $varname variable name or null
   *
   * @return string variable value or or array of variables
   */
  public function getGlobal($varname = null)
  {
    if (isset($varname)) {
      if (isset(self::$global_tpl_vars[$varname])) {
        return self::$global_tpl_vars[$varname]->value;
      } else {
        return '';
      }
    } else {
      $_result = array();
      foreach (self::$global_tpl_vars AS $key => $var) {
        $_result[$key] = $var->value;
      }
      return $_result;
    }
  }
  /**
   * Empty cache folder
   *
   * @param integer $exp_time expiration time
   * @param string $type   resource type
   *
   * @return integer number of cache files deleted
   */
  public function clearAllCache($exp_time = null, $type = null)
  {
    // load cache resource and call clearAll
    $_cache_resource = Smarty_CacheResource::load($this, $type);
    Smarty_CacheResource::invalidLoadedCache($this);
    return $_cache_resource->clearAll($this, $exp_time);
  }
  /**
   * Empty cache for a specific template
   *
   * @param string $template_name template name
   * @param string $cache_id   cache id
   * @param string $compile_id  compile id
   * @param integer $exp_time   expiration time
   * @param string $type     resource type
   *
   * @return integer number of cache files deleted
   */
  public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
  {
    // load cache resource and call clear
    $_cache_resource = Smarty_CacheResource::load($this, $type);
    Smarty_CacheResource::invalidLoadedCache($this);
    return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time);
  }
  /**
   * Loads security class and enables security
   *
   * @param string|Smarty_Security $security_class if a string is used, it must be class-name
   *
   * @return Smarty         current Smarty instance for chaining
   * @throws SmartyException    when an invalid class name is provided
   */
  public function enableSecurity($security_class = null)
  {
    if ($security_class instanceof Smarty_Security) {
      $this->security_policy = $security_class;
      return $this;
    } elseif (is_object($security_class)) {
      throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security.");
    }
    if ($security_class == null) {
      $security_class = $this->security_class;
    }
    if (!class_exists($security_class)) {
      throw new SmartyException("Security class '$security_class' is not defined");
    } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) {
      throw new SmartyException("Class '$security_class' must extend Smarty_Security.");
    } else {
      $this->security_policy = new $security_class($this);
    }
    return $this;
  }
  /**
   * Disable security
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function disableSecurity()
  {
    $this->security_policy = null;
    return $this;
  }
  /**
   * Set template directory
   *
   * @param string|array $template_dir directory(s) of template sources
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setTemplateDir($template_dir)
  {
    $this->template_dir = array();
    foreach ((array) $template_dir as $k => $v) {
      $this->template_dir[$k] = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
    }
    $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir);
    return $this;
  }
  /**
   * Add template directory(s)
   *
   * @param string|array $template_dir directory(s) of template sources
   * @param string    $key     of the array element to assign the template dir to
   *
   * @return Smarty     current Smarty instance for chaining
   * @throws SmartyException when the given template directory is not valid
   */
  public function addTemplateDir($template_dir, $key = null)
  {
    // make sure we're dealing with an array
    $this->template_dir = (array) $this->template_dir;
    if (is_array($template_dir)) {
      foreach ($template_dir as $k => $v) {
        $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
        if (is_int($k)) {
          // indexes are not merged but appended
          $this->template_dir[] = $v;
        } else {
          // string indexes are overridden
          $this->template_dir[$k] = $v;
        }
      }
    } else {
      $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($template_dir, '/\\')) . DS;
      if ($key !== null) {
        // override directory at specified index
        $this->template_dir[$key] = $v;
      } else {
        // append new directory
        $this->template_dir[] = $v;
      }
    }
    $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir);
    return $this;
  }
  /**
   * Get template directories
   *
   * @param mixed $index index of directory to get, null to get all
   *
   * @return array|string list of template directories, or directory of $index
   */
  public function getTemplateDir($index = null)
  {
    if ($index !== null) {
      return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null;
    }
    return (array) $this->template_dir;
  }
  /**
   * Set config directory
   *
   * @param $config_dir
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setConfigDir($config_dir)
  {
    $this->config_dir = array();
    foreach ((array) $config_dir as $k => $v) {
      $this->config_dir[$k] = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
    }
    $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir);
    return $this;
  }
  /**
   * Add config directory(s)
   *
   * @param string|array    $config_dir directory(s) of config sources
   * @param mixed $key    key of the array element to assign the config dir to
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function addConfigDir($config_dir, $key = null)
  {
    // make sure we're dealing with an array
    $this->config_dir = (array) $this->config_dir;
    if (is_array($config_dir)) {
      foreach ($config_dir as $k => $v) {
        $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
        if (is_int($k)) {
          // indexes are not merged but appended
          $this->config_dir[] = $v;
        } else {
          // string indexes are overridden
          $this->config_dir[$k] = $v;
        }
      }
    } else {
      $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($config_dir, '/\\')) . DS;
      if ($key !== null) {
        // override directory at specified index
        $this->config_dir[$key] = rtrim($v, '/\\') . DS;
      } else {
        // append new directory
        $this->config_dir[] = rtrim($v, '/\\') . DS;
      }
    }
    $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir);
    return $this;
  }
  /**
   * Get config directory
   *
   * @param mixed $index index of directory to get, null to get all
   *
   * @return array|string configuration directory
   */
  public function getConfigDir($index = null)
  {
    if ($index !== null) {
      return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null;
    }
    return (array) $this->config_dir;
  }
  /**
   * Set plugins directory
   *
   * @param string|array $plugins_dir directory(s) of plugins
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setPluginsDir($plugins_dir)
  {
    $this->plugins_dir = array();
    foreach ((array) $plugins_dir as $k => $v) {
      $this->plugins_dir[$k] = rtrim($v, '/\\') . DS;
    }
    return $this;
  }
  /**
   * Adds directory of plugin files
   *
   * @param $plugins_dir
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function addPluginsDir($plugins_dir)
  {
    // make sure we're dealing with an array
    $this->plugins_dir = (array) $this->plugins_dir;
    if (is_array($plugins_dir)) {
      foreach ($plugins_dir as $k => $v) {
        if (is_int($k)) {
          // indexes are not merged but appended
          $this->plugins_dir[] = rtrim($v, '/\\') . DS;
        } else {
          // string indexes are overridden
          $this->plugins_dir[$k] = rtrim($v, '/\\') . DS;
        }
      }
    } else {
      // append new directory
      $this->plugins_dir[] = rtrim($plugins_dir, '/\\') . DS;
    }
    $this->plugins_dir = array_unique($this->plugins_dir);
    return $this;
  }
  /**
   * Get plugin directories
   *
   * @return array list of plugin directories
   */
  public function getPluginsDir()
  {
    return (array) $this->plugins_dir;
  }
  /**
   * Set compile directory
   *
   * @param string $compile_dir directory to store compiled templates in
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function setCompileDir($compile_dir)
  {
    $this->compile_dir = rtrim($compile_dir, '/\\') . DS;
    if (!isset(Smarty::$_muted_directories[$this->compile_dir])) {
      Smarty::$_muted_directories[$this->compile_dir] = null;
    }
    return $this;
  }
  /**
   * Get compiled directory
   *
   * @return string path to compiled templates
   */
  public function getCompileDir()
  {
    return $this->compile_dir;
  }
  /**
   * Set cache directory
   *
   * @param string $cache_dir directory to store cached templates in
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function setCacheDir($cache_dir)
  {
    $this->cache_dir = rtrim($cache_dir, '/\\') . DS;
    if (!isset(Smarty::$_muted_directories[$this->cache_dir])) {
      Smarty::$_muted_directories[$this->cache_dir] = null;
    }
    return $this;
  }
  /**
   * Get cache directory
   *
   * @return string path of cache directory
   */
  public function getCacheDir()
  {
    return $this->cache_dir;
  }
  /**
   * Set default modifiers
   *
   * @param array|string $modifiers modifier or list of modifiers to set
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setDefaultModifiers($modifiers)
  {
    $this->default_modifiers = (array) $modifiers;
    return $this;
  }
  /**
   * Add default modifiers
   *
   * @param array|string $modifiers modifier or list of modifiers to add
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function addDefaultModifiers($modifiers)
  {
    if (is_array($modifiers)) {
      $this->default_modifiers = array_merge($this->default_modifiers, $modifiers);
    } else {
      $this->default_modifiers[] = $modifiers;
    }
    return $this;
  }
  /**
   * Get default modifiers
   *
   * @return array list of default modifiers
   */
  public function getDefaultModifiers()
  {
    return $this->default_modifiers;
  }
  /**
   * Set autoload filters
   *
   * @param array $filters filters to load automatically
   * @param string $type  "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function setAutoloadFilters($filters, $type = null)
  {
    if ($type !== null) {
      $this->autoload_filters[$type] = (array) $filters;
    } else {
      $this->autoload_filters = (array) $filters;
    }
    return $this;
  }
  /**
   * Add autoload filters
   *
   * @param array $filters filters to load automatically
   * @param string $type  "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function addAutoloadFilters($filters, $type = null)
  {
    if ($type !== null) {
      if (!empty($this->autoload_filters[$type])) {
        $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters);
      } else {
        $this->autoload_filters[$type] = (array) $filters;
      }
    } else {
      foreach ((array) $filters as $key => $value) {
        if (!empty($this->autoload_filters[$key])) {
          $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value);
        } else {
          $this->autoload_filters[$key] = (array) $value;
        }
      }
    }
    return $this;
  }
  /**
   * Get autoload filters
   *
   * @param string $type type of filter to get autoloads for. Defaults to all autoload filters
   *
   * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type was specified
   */
  public function getAutoloadFilters($type = null)
  {
    if ($type !== null) {
      return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array();
    }
    return $this->autoload_filters;
  }
  /**
   * return name of debugging template
   *
   * @return string
   */
  public function getDebugTemplate()
  {
    return $this->debug_tpl;
  }
  /**
   * set the debug template
   *
   * @param string $tpl_name
   *
   * @return Smarty     current Smarty instance for chaining
   * @throws SmartyException if file is not readable
   */
  public function setDebugTemplate($tpl_name)
  {
    if (!is_readable($tpl_name)) {
      throw new SmartyException("Unknown file '{$tpl_name}'");
    }
    $this->debug_tpl = $tpl_name;
    return $this;
  }
  /**
   * creates a template object
   *
   * @param string $template  the resource handle of the template file
   * @param mixed  $cache_id  cache id to be used with this template
   * @param mixed  $compile_id compile id to be used with this template
   * @param object $parent   next higher level of Smarty variables
   * @param boolean $do_clone  flag is Smarty object shall be cloned
   *
   * @return object template object
   */
  public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
  {
    if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
      $parent = $cache_id;
      $cache_id = null;
    }
    if ($parent !== null && is_array($parent)) {
      $data = $parent;
      $parent = null;
    } else {
      $data = null;
    }
    // default to cache_id and compile_id of Smarty object
    $cache_id = $cache_id === null ? $this->cache_id : $cache_id;
    $compile_id = $compile_id === null ? $this->compile_id : $compile_id;
    // already in template cache?
    if ($this->allow_ambiguous_resources) {
      $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id;
    } else {
      $_templateId = $this->joined_template_dir . '#' . $template . $cache_id . $compile_id;
    }
    if (isset($_templateId[150])) {
      $_templateId = sha1($_templateId);
    }
    if ($do_clone) {
      if (isset($this->template_objects[$_templateId])) {
        // return cached template object
        $tpl = clone $this->template_objects[$_templateId];
        $tpl->smarty = clone $tpl->smarty;
        $tpl->parent = $parent;
        $tpl->tpl_vars = array();
        $tpl->config_vars = array();
      } else {
        $tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id);
      }
    } else {
      if (isset($this->template_objects[$_templateId])) {
        // return cached template object
        $tpl = $this->template_objects[$_templateId];
        $tpl->parent = $parent;
        $tpl->tpl_vars = array();
        $tpl->config_vars = array();
      } else {
        $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id);
      }
    }
    // fill data if present
    if (!empty($data) && is_array($data)) {
      // set up variable values
      foreach ($data as $_key => $_val) {
        $tpl->tpl_vars[$_key] = new Smarty_variable($_val);
      }
    }
    return $tpl;
  }
  /**
   * Takes unknown classes and loads plugin files for them
   * class name format: Smarty_PluginType_PluginName
   * plugin filename format: plugintype.pluginname.php
   *
   * @param string $plugin_name class plugin name to load
   * @param bool  $check    check if already loaded
   *
   * @throws SmartyException
   * @return string |boolean filepath of loaded file or false
   */
  public function loadPlugin($plugin_name, $check = true)
  {
    // if function or class exists, exit silently (already loaded)
    if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) {
      return true;
    }
    // Plugin name is expected to be: Smarty_[Type]_[Name]
    $_name_parts = explode('_', $plugin_name, 3);
    // class name must have three parts to be valid plugin
    // count($_name_parts) < 3 === !isset($_name_parts[2])
    if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') {
      throw new SmartyException("plugin {$plugin_name} is not a valid name format");
    }
    // if type is "internal", get plugin from sysplugins
    if (strtolower($_name_parts[1]) == 'internal') {
      $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php';
      if (file_exists($file)) {
        require_once($file);
        return $file;
      } else {
        return false;
      }
    }
    // plugin filename is expected to be: [type].[name].php
    $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php";
    $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
    // loop through plugin dirs and find the plugin
    foreach ($this->getPluginsDir() as $_plugin_dir) {
      $names = array(
        $_plugin_dir . $_plugin_filename,
        $_plugin_dir . strtolower($_plugin_filename),
      );
      foreach ($names as $file) {
        if (file_exists($file)) {
          require_once($file);
          return $file;
        }
        if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
          // try PHP include_path
          if ($_stream_resolve_include_path) {
            $file = stream_resolve_include_path($file);
          } else {
            $file = Smarty_Internal_Get_Include_Path::getIncludePath($file);
          }
          if ($file !== false) {
            require_once($file);
            return $file;
          }
        }
      }
    }
    // no plugin loaded
    return false;
  }
  /**
   * Compile all template files
   *
   * @param string $extension   file extension
   * @param bool  $force_compile force all to recompile
   * @param int  $time_limit
   * @param int  $max_errors
   *
   * @return integer number of template files recompiled
   */
  public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
  {
    return Smarty_Internal_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this);
  }
  /**
   * Compile all config files
   *
   * @param string $extension   file extension
   * @param bool  $force_compile force all to recompile
   * @param int  $time_limit
   * @param int  $max_errors
   *
   * @return integer number of template files recompiled
   */
  public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null)
  {
    return Smarty_Internal_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this);
  }
  /**
   * Delete compiled template file
   *
   * @param string $resource_name template name
   * @param string $compile_id  compile id
   * @param integer $exp_time   expiration time
   *
   * @return integer number of template files deleted
   */
  public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
  {
    return Smarty_Internal_Utility::clearCompiledTemplate($resource_name, $compile_id, $exp_time, $this);
  }
  /**
   * Return array of tag/attributes of all tags used by an template
   *
   * @param Smarty_Internal_Template $template
   *
   * @return array of tag/attributes
   */
  public function getTags(Smarty_Internal_Template $template)
  {
    return Smarty_Internal_Utility::getTags($template);
  }
  /**
   * Run installation test
   *
   * @param array $errors Array to write errors into, rather than outputting them
   *
   * @return boolean true if setup is fine, false if something is wrong
   */
  public function testInstall(&$errors = null)
  {
    return Smarty_Internal_Utility::testInstall($this, $errors);
  }
  /**
   * Error Handler to mute expected messages
   *
   * @link http://php.net/set_error_handler
   *
   * @param integer $errno Error level
   * @param     $errstr
   * @param     $errfile
   * @param     $errline
   * @param     $errcontext
   *
   * @return boolean
   */
  public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext)
  {
    $_is_muted_directory = false;
    // add the SMARTY_DIR to the list of muted directories
    if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) {
      $smarty_dir = realpath(SMARTY_DIR);
      if ($smarty_dir !== false) {
        Smarty::$_muted_directories[SMARTY_DIR] = array(
          'file'  => $smarty_dir,
          'length' => strlen($smarty_dir),
        );
      }
    }
    // walk the muted directories and test against $errfile
    foreach (Smarty::$_muted_directories as $key => &$dir) {
      if (!$dir) {
        // resolve directory and length for speedy comparisons
        $file = realpath($key);
        if ($file === false) {
          // this directory does not exist, remove and skip it
          unset(Smarty::$_muted_directories[$key]);
          continue;
        }
        $dir = array(
          'file'  => $file,
          'length' => strlen($file),
        );
      }
      if (!strncmp($errfile, $dir['file'], $dir['length'])) {
        $_is_muted_directory = true;
        break;
      }
    }
    // pass to next error handler if this error did not occur inside SMARTY_DIR
    // or the error was within smarty but masked to be ignored
    if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
      if (Smarty::$_previous_error_handler) {
        return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext);
      } else {
        return false;
      }
    }
  }
  /**
   * Enable error handler to mute expected messages
   *
   * @return void
   */
  public static function muteExpectedErrors()
  {
    /*
      error muting is done because some people implemented custom error_handlers using
      http://php.net/set_error_handler and for some reason did not understand the following paragraph:
        It is important to remember that the standard PHP error handler is completely bypassed for the
        error types specified by error_types unless the callback function returns FALSE.
        error_reporting() settings will have no effect and your error handler will be called regardless -
        however you are still able to read the current value of error_reporting and act appropriately.
        Of particular note is that this value will be 0 if the statement that caused the error was
        prepended by the @ error-control operator.
      Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include
        - @filemtime() is almost twice as fast as using an additional file_exists()
        - between file_exists() and filemtime() a possible race condition is opened,
         which does not exist using the simple @filemtime() approach.
    */
    $error_handler = array('Smarty', 'mutingErrorHandler');
    $previous = set_error_handler($error_handler);
    // avoid dead loops
    if ($previous !== $error_handler) {
      Smarty::$_previous_error_handler = $previous;
    }
  }
  /**
   * Disable error handler muting expected messages
   *
   * @return void
   */
  public static function unmuteExpectedErrors()
  {
    restore_error_handler();
  }
}
// Check if we're running on windows
Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
// let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
if (Smarty::$_CHARSET !== 'UTF-8') {
  Smarty::$_UTF8_MODIFIER = '';
}
/**
 * Smarty exception class
 *
 * @package Smarty
 */
class SmartyException extends Exception
{
  public static $escape = false;
  public function __toString()
  {
    return ' --> Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- ';
  }
}
/**
 * Smarty compiler exception class
 *
 * @package Smarty
 */
class SmartyCompilerException extends SmartyException
{
  public function __toString()
  {
    return ' --> Smarty Compiler: ' . $this->message . ' <-- ';
  }
  /**
   * The line number of the template error
   *
   * @type int|null
   */
  public $line = null;
  /**
   * The template source snippet relating to the error
   *
   * @type string|null
   */
  public $source = null;
  /**
   * The raw text of the error message
   *
   * @type string|null
   */
  public $desc = null;
  /**
   * The resource identifier or template name
   *
   * @type string|null
   */
  public $template = null;
}
/**
 * Autoloader
 */
function smartyAutoload($class)
{
  $_class = strtolower($class);
  static $_classes = array(
    'smarty_config_source'        => true,
    'smarty_config_compiled'       => true,
    'smarty_security'          => true,
    'smarty_cacheresource'        => true,
    'smarty_cacheresource_custom'    => true,
    'smarty_cacheresource_keyvaluestore' => true,
    'smarty_resource'          => true,
    'smarty_resource_custom'       => true,
    'smarty_resource_uncompiled'     => true,
    'smarty_resource_recompiled'     => true,
  );
  if (!strncmp($_class, 'smarty_internal_', 16) || isset($_classes[$_class])) {
    include SMARTY_SYSPLUGINS_DIR . $_class . '.php';
  }
}
<?php
/**
 * Project:   Smarty: the PHP compiling template engine
 * File:    Smarty.class.php
 * SVN:     $Id: Smarty.class.php 4848 2014-06-08 18:12:09Z Uwe.Tews@googlemail.com $
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 * For questions, help, comments, discussion, etc., please join the
 * Smarty mailing list. Send a blank e-mail to
 * smarty-discussion-subscribe@googlegroups.com
 *
 * @link   http://www.smarty.net/
 * @copyright 2008 New Digital Group, Inc.
 * @author  Monte Ohrt <monte at ohrt dot com>
 * @author  Uwe Tews
 * @author  Rodney Rehm
 * @package  Smarty
 * @version  3.1.19
 */
/**
 * define shorthand directory separator constant
 */
if (!defined('DS')) {
  define('DS', DIRECTORY_SEPARATOR);
}
/**
 * set SMARTY_DIR to absolute path to Smarty library files.
 * Sets SMARTY_DIR only if user application has not already defined it.
 */
if (!defined('SMARTY_DIR')) {
  define('SMARTY_DIR', dirname(__FILE__) . DS);
}
/**
 * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
 * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
 */
if (!defined('SMARTY_SYSPLUGINS_DIR')) {
  define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS);
}
if (!defined('SMARTY_PLUGINS_DIR')) {
  define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS);
}
if (!defined('SMARTY_MBSTRING')) {
  define('SMARTY_MBSTRING', function_exists('mb_split'));
}
if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
  // UTF-8 can only be done properly when mbstring is available!
  /**
   * @deprecated in favor of Smarty::$_CHARSET
   */
  define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
}
if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
  /**
   * @deprecated in favor of Smarty::$_DATE_FORMAT
   */
  define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
}
/**
 * register the class autoloader
 */
if (!defined('SMARTY_SPL_AUTOLOAD')) {
  define('SMARTY_SPL_AUTOLOAD', 0);
}
if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false) {
  $registeredAutoLoadFunctions = spl_autoload_functions();
  if (!isset($registeredAutoLoadFunctions['spl_autoload'])) {
    spl_autoload_register();
  }
} else {
  spl_autoload_register('smartyAutoload');
}
/**
 * Load always needed external class files
 */
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php';
include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_cacheresource_file.php';
/**
 * This is the main Smarty class
 *
 * @package Smarty
 */
class Smarty extends Smarty_Internal_TemplateBase
{
  /**#@+
   * constant definitions
   */
  /**
   * smarty version
   */
  const SMARTY_VERSION = 'Smarty-3.1.19';
  /**
   * define variable scopes
   */
  const SCOPE_LOCAL = 0;
  const SCOPE_PARENT = 1;
  const SCOPE_ROOT = 2;
  const SCOPE_GLOBAL = 3;
  /**
   * define caching modes
   */
  const CACHING_OFF = 0;
  const CACHING_LIFETIME_CURRENT = 1;
  const CACHING_LIFETIME_SAVED = 2;
  /**
   * define constant for clearing cache files be saved expiration datees
   */
  const CLEAR_EXPIRED = - 1;
  /**
   * define compile check modes
   */
  const COMPILECHECK_OFF = 0;
  const COMPILECHECK_ON = 1;
  const COMPILECHECK_CACHEMISS = 2;
  /**
   * modes for handling of "<?php ... ?>" tags in templates.
   */
  const PHP_PASSTHRU = 0; //-> print tags as plain text
  const PHP_QUOTE = 1; //-> escape tags as entities
  const PHP_REMOVE = 2; //-> escape tags as entities
  const PHP_ALLOW = 3; //-> escape tags as entities
  /**
   * filter types
   */
  const FILTER_POST = 'post';
  const FILTER_PRE = 'pre';
  const FILTER_OUTPUT = 'output';
  const FILTER_VARIABLE = 'variable';
  /**
   * plugin types
   */
  const PLUGIN_FUNCTION = 'function';
  const PLUGIN_BLOCK = 'block';
  const PLUGIN_COMPILER = 'compiler';
  const PLUGIN_MODIFIER = 'modifier';
  const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
  /**#@-*/
  /**
   * assigned global tpl vars
   */
  public static $global_tpl_vars = array();
  /**
   * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors()
   */
  public static $_previous_error_handler = null;
  /**
   * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors()
   */
  public static $_muted_directories = array();
  /**
   * Flag denoting if Multibyte String functions are available
   */
  public static $_MBSTRING = SMARTY_MBSTRING;
  /**
   * The character set to adhere to (e.g. "UTF-8")
   */
  public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
  /**
   * The date format to be used internally
   * (accepts date() and strftime())
   */
  public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
  /**
   * Flag denoting if PCRE should run in UTF-8 mode
   */
  public static $_UTF8_MODIFIER = 'u';
  /**
   * Flag denoting if operating system is windows
   */
  public static $_IS_WINDOWS = false;
  /**#@+
   * variables
   */
  /**
   * auto literal on delimiters with whitspace
   *
   * @var boolean
   */
  public $auto_literal = true;
  /**
   * display error on not assigned variables
   *
   * @var boolean
   */
  public $error_unassigned = false;
  /**
   * look up relative filepaths in include_path
   *
   * @var boolean
   */
  public $use_include_path = false;
  /**
   * template directory
   *
   * @var array
   */
  private $template_dir = array();
  /**
   * joined template directory string used in cache keys
   *
   * @var string
   */
  public $joined_template_dir = null;
  /**
   * joined config directory string used in cache keys
   *
   * @var string
   */
  public $joined_config_dir = null;
  /**
   * default template handler
   *
   * @var callable
   */
  public $default_template_handler_func = null;
  /**
   * default config handler
   *
   * @var callable
   */
  public $default_config_handler_func = null;
  /**
   * default plugin handler
   *
   * @var callable
   */
  public $default_plugin_handler_func = null;
  /**
   * compile directory
   *
   * @var string
   */
  private $compile_dir = null;
  /**
   * plugins directory
   *
   * @var array
   */
  private $plugins_dir = array();
  /**
   * cache directory
   *
   * @var string
   */
  private $cache_dir = null;
  /**
   * config directory
   *
   * @var array
   */
  private $config_dir = array();
  /**
   * force template compiling?
   *
   * @var boolean
   */
  public $force_compile = false;
  /**
   * check template for modifications?
   *
   * @var boolean
   */
  public $compile_check = true;
  /**
   * use sub dirs for compiled/cached files?
   *
   * @var boolean
   */
  public $use_sub_dirs = false;
  /**
   * allow ambiguous resources (that are made unique by the resource handler)
   *
   * @var boolean
   */
  public $allow_ambiguous_resources = false;
  /**
   * caching enabled
   *
   * @var boolean
   */
  public $caching = false;
  /**
   * merge compiled includes
   *
   * @var boolean
   */
  public $merge_compiled_includes = false;
  /**
   * template inheritance merge compiled includes
   *
   * @var boolean
   */
  public $inheritance_merge_compiled_includes = true;
  /**
   * cache lifetime in seconds
   *
   * @var integer
   */
  public $cache_lifetime = 3600;
  /**
   * force cache file creation
   *
   * @var boolean
   */
  public $force_cache = false;
  /**
   * Set this if you want different sets of cache files for the same
   * templates.
   *
   * @var string
   */
  public $cache_id = null;
  /**
   * Set this if you want different sets of compiled files for the same
   * templates.
   *
   * @var string
   */
  public $compile_id = null;
  /**
   * template left-delimiter
   *
   * @var string
   */
  public $left_delimiter = "{";
  /**
   * template right-delimiter
   *
   * @var string
   */
  public $right_delimiter = "}";
  /**#@+
   * security
   */
  /**
   * class name
   * This should be instance of Smarty_Security.
   *
   * @var string
   * @see Smarty_Security
   */
  public $security_class = 'Smarty_Security';
  /**
   * implementation of security class
   *
   * @var Smarty_Security
   */
  public $security_policy = null;
  /**
   * controls handling of PHP-blocks
   *
   * @var integer
   */
  public $php_handling = self::PHP_PASSTHRU;
  /**
   * controls if the php template file resource is allowed
   *
   * @var bool
   */
  public $allow_php_templates = false;
  /**
   * Should compiled-templates be prevented from being called directly?
   * {@internal
   * Currently used by Smarty_Internal_Template only.
   * }}
   *
   * @var boolean
   */
  public $direct_access_security = true;
  /**#@-*/
  /**
   * debug mode
   * Setting this to true enables the debug-console.
   *
   * @var boolean
   */
  public $debugging = false;
  /**
   * This determines if debugging is enable-able from the browser.
   * <ul>
   * <li>NONE => no debugging control allowed</li>
   * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
   * </ul>
   *
   * @var string
   */
  public $debugging_ctrl = 'NONE';
  /**
   * Name of debugging URL-param.
   * Only used when $debugging_ctrl is set to 'URL'.
   * The name of the URL-parameter that activates debugging.
   *
   * @var type
   */
  public $smarty_debug_id = 'SMARTY_DEBUG';
  /**
   * Path of debug template.
   *
   * @var string
   */
  public $debug_tpl = null;
  /**
   * When set, smarty uses this value as error_reporting-level.
   *
   * @var int
   */
  public $error_reporting = null;
  /**
   * Internal flag for getTags()
   *
   * @var boolean
   */
  public $get_used_tags = false;
  /**#@+
   * config var settings
   */
  /**
   * Controls whether variables with the same name overwrite each other.
   *
   * @var boolean
   */
  public $config_overwrite = true;
  /**
   * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
   *
   * @var boolean
   */
  public $config_booleanize = true;
  /**
   * Controls whether hidden config sections/vars are read from the file.
   *
   * @var boolean
   */
  public $config_read_hidden = false;
  /**#@-*/
  /**#@+
   * resource locking
   */
  /**
   * locking concurrent compiles
   *
   * @var boolean
   */
  public $compile_locking = true;
  /**
   * Controls whether cache resources should emply locking mechanism
   *
   * @var boolean
   */
  public $cache_locking = false;
  /**
   * seconds to wait for acquiring a lock before ignoring the write lock
   *
   * @var float
   */
  public $locking_timeout = 10;
  /**#@-*/
  /**
   * global template functions
   *
   * @var array
   */
  public $template_functions = array();
  /**
   * resource type used if none given
   * Must be an valid key of $registered_resources.
   *
   * @var string
   */
  public $default_resource_type = 'file';
  /**
   * caching type
   * Must be an element of $cache_resource_types.
   *
   * @var string
   */
  public $caching_type = 'file';
  /**
   * internal config properties
   *
   * @var array
   */
  public $properties = array();
  /**
   * config type
   *
   * @var string
   */
  public $default_config_type = 'file';
  /**
   * cached template objects
   *
   * @var array
   */
  public $template_objects = array();
  /**
   * check If-Modified-Since headers
   *
   * @var boolean
   */
  public $cache_modified_check = false;
  /**
   * registered plugins
   *
   * @var array
   */
  public $registered_plugins = array();
  /**
   * plugin search order
   *
   * @var array
   */
  public $plugin_search_order = array('function', 'block', 'compiler', 'class');
  /**
   * registered objects
   *
   * @var array
   */
  public $registered_objects = array();
  /**
   * registered classes
   *
   * @var array
   */
  public $registered_classes = array();
  /**
   * registered filters
   *
   * @var array
   */
  public $registered_filters = array();
  /**
   * registered resources
   *
   * @var array
   */
  public $registered_resources = array();
  /**
   * resource handler cache
   *
   * @var array
   */
  public $_resource_handlers = array();
  /**
   * registered cache resources
   *
   * @var array
   */
  public $registered_cache_resources = array();
  /**
   * cache resource handler cache
   *
   * @var array
   */
  public $_cacheresource_handlers = array();
  /**
   * autoload filter
   *
   * @var array
   */
  public $autoload_filters = array();
  /**
   * default modifier
   *
   * @var array
   */
  public $default_modifiers = array();
  /**
   * autoescape variable output
   *
   * @var boolean
   */
  public $escape_html = false;
  /**
   * global internal smarty vars
   *
   * @var array
   */
  public static $_smarty_vars = array();
  /**
   * start time for execution time calculation
   *
   * @var int
   */
  public $start_time = 0;
  /**
   * default file permissions
   *
   * @var int
   */
  public $_file_perms = 0644;
  /**
   * default dir permissions
   *
   * @var int
   */
  public $_dir_perms = 0771;
  /**
   * block tag hierarchy
   *
   * @var array
   */
  public $_tag_stack = array();
  /**
   * self pointer to Smarty object
   *
   * @var Smarty
   */
  public $smarty;
  /**
   * required by the compiler for BC
   *
   * @var string
   */
  public $_current_file = null;
  /**
   * internal flag to enable parser debugging
   *
   * @var bool
   */
  public $_parserdebug = false;
  /**
   * Saved parameter of merged templates during compilation
   *
   * @var array
   */
  public $merged_templates_func = array();
  /**#@-*/
  /**
   * Initialize new Smarty object
   */
  public function __construct()
  {
    // selfpointer needed by some other class methods
    $this->smarty = $this;
    if (is_callable('mb_internal_encoding')) {
      mb_internal_encoding(Smarty::$_CHARSET);
    }
    $this->start_time = microtime(true);
    // set default dirs
    $this->setTemplateDir('.' . DS . 'templates' . DS)
      ->setCompileDir('.' . DS . 'templates_c' . DS)
      ->setPluginsDir(SMARTY_PLUGINS_DIR)
      ->setCacheDir('.' . DS . 'cache' . DS)
      ->setConfigDir('.' . DS . 'configs' . DS);
    $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl';
    if (isset($_SERVER['SCRIPT_NAME'])) {
      $this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']);
    }
  }
  /**
   * Class destructor
   */
  public function __destruct()
  {
    // intentionally left blank
  }
  /**
   * <<magic>> set selfpointer on cloned object
   */
  public function __clone()
  {
    $this->smarty = $this;
  }
  /**
   * <<magic>> Generic getter.
   * Calls the appropriate getter function.
   * Issues an E_USER_NOTICE if no valid getter is found.
   *
   * @param string $name property name
   *
   * @return mixed
   */
  public function __get($name)
  {
    $allowed = array(
      'template_dir' => 'getTemplateDir',
      'config_dir'  => 'getConfigDir',
      'plugins_dir' => 'getPluginsDir',
      'compile_dir' => 'getCompileDir',
      'cache_dir'  => 'getCacheDir',
    );
    if (isset($allowed[$name])) {
      return $this->{$allowed[$name]}();
    } else {
      trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
    }
  }
  /**
   * <<magic>> Generic setter.
   * Calls the appropriate setter function.
   * Issues an E_USER_NOTICE if no valid setter is found.
   *
   * @param string $name property name
   * @param mixed $value parameter passed to setter
   */
  public function __set($name, $value)
  {
    $allowed = array(
      'template_dir' => 'setTemplateDir',
      'config_dir'  => 'setConfigDir',
      'plugins_dir' => 'setPluginsDir',
      'compile_dir' => 'setCompileDir',
      'cache_dir'  => 'setCacheDir',
    );
    if (isset($allowed[$name])) {
      $this->{$allowed[$name]}($value);
    } else {
      trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
    }
  }
  /**
   * Check if a template resource exists
   *
   * @param string $resource_name template name
   *
   * @return boolean status
   */
  public function templateExists($resource_name)
  {
    // create template object
    $save = $this->template_objects;
    $tpl = new $this->template_class($resource_name, $this);
    // check if it does exists
    $result = $tpl->source->exists;
    $this->template_objects = $save;
    return $result;
  }
  /**
   * Returns a single or all global variables
   *
   * @param string $varname variable name or null
   *
   * @return string variable value or or array of variables
   */
  public function getGlobal($varname = null)
  {
    if (isset($varname)) {
      if (isset(self::$global_tpl_vars[$varname])) {
        return self::$global_tpl_vars[$varname]->value;
      } else {
        return '';
      }
    } else {
      $_result = array();
      foreach (self::$global_tpl_vars AS $key => $var) {
        $_result[$key] = $var->value;
      }
      return $_result;
    }
  }
  /**
   * Empty cache folder
   *
   * @param integer $exp_time expiration time
   * @param string $type   resource type
   *
   * @return integer number of cache files deleted
   */
  public function clearAllCache($exp_time = null, $type = null)
  {
    // load cache resource and call clearAll
    $_cache_resource = Smarty_CacheResource::load($this, $type);
    Smarty_CacheResource::invalidLoadedCache($this);
    return $_cache_resource->clearAll($this, $exp_time);
  }
  /**
   * Empty cache for a specific template
   *
   * @param string $template_name template name
   * @param string $cache_id   cache id
   * @param string $compile_id  compile id
   * @param integer $exp_time   expiration time
   * @param string $type     resource type
   *
   * @return integer number of cache files deleted
   */
  public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
  {
    // load cache resource and call clear
    $_cache_resource = Smarty_CacheResource::load($this, $type);
    Smarty_CacheResource::invalidLoadedCache($this);
    return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time);
  }
  /**
   * Loads security class and enables security
   *
   * @param string|Smarty_Security $security_class if a string is used, it must be class-name
   *
   * @return Smarty         current Smarty instance for chaining
   * @throws SmartyException    when an invalid class name is provided
   */
  public function enableSecurity($security_class = null)
  {
    if ($security_class instanceof Smarty_Security) {
      $this->security_policy = $security_class;
      return $this;
    } elseif (is_object($security_class)) {
      throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security.");
    }
    if ($security_class == null) {
      $security_class = $this->security_class;
    }
    if (!class_exists($security_class)) {
      throw new SmartyException("Security class '$security_class' is not defined");
    } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) {
      throw new SmartyException("Class '$security_class' must extend Smarty_Security.");
    } else {
      $this->security_policy = new $security_class($this);
    }
    return $this;
  }
  /**
   * Disable security
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function disableSecurity()
  {
    $this->security_policy = null;
    return $this;
  }
  /**
   * Set template directory
   *
   * @param string|array $template_dir directory(s) of template sources
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setTemplateDir($template_dir)
  {
    $this->template_dir = array();
    foreach ((array) $template_dir as $k => $v) {
      $this->template_dir[$k] = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
    }
    $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir);
    return $this;
  }
  /**
   * Add template directory(s)
   *
   * @param string|array $template_dir directory(s) of template sources
   * @param string    $key     of the array element to assign the template dir to
   *
   * @return Smarty     current Smarty instance for chaining
   * @throws SmartyException when the given template directory is not valid
   */
  public function addTemplateDir($template_dir, $key = null)
  {
    // make sure we're dealing with an array
    $this->template_dir = (array) $this->template_dir;
    if (is_array($template_dir)) {
      foreach ($template_dir as $k => $v) {
        $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
        if (is_int($k)) {
          // indexes are not merged but appended
          $this->template_dir[] = $v;
        } else {
          // string indexes are overridden
          $this->template_dir[$k] = $v;
        }
      }
    } else {
      $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($template_dir, '/\\')) . DS;
      if ($key !== null) {
        // override directory at specified index
        $this->template_dir[$key] = $v;
      } else {
        // append new directory
        $this->template_dir[] = $v;
      }
    }
    $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir);
    return $this;
  }
  /**
   * Get template directories
   *
   * @param mixed $index index of directory to get, null to get all
   *
   * @return array|string list of template directories, or directory of $index
   */
  public function getTemplateDir($index = null)
  {
    if ($index !== null) {
      return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null;
    }
    return (array) $this->template_dir;
  }
  /**
   * Set config directory
   *
   * @param $config_dir
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setConfigDir($config_dir)
  {
    $this->config_dir = array();
    foreach ((array) $config_dir as $k => $v) {
      $this->config_dir[$k] = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
    }
    $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir);
    return $this;
  }
  /**
   * Add config directory(s)
   *
   * @param string|array    $config_dir directory(s) of config sources
   * @param mixed $key    key of the array element to assign the config dir to
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function addConfigDir($config_dir, $key = null)
  {
    // make sure we're dealing with an array
    $this->config_dir = (array) $this->config_dir;
    if (is_array($config_dir)) {
      foreach ($config_dir as $k => $v) {
        $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS;
        if (is_int($k)) {
          // indexes are not merged but appended
          $this->config_dir[] = $v;
        } else {
          // string indexes are overridden
          $this->config_dir[$k] = $v;
        }
      }
    } else {
      $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($config_dir, '/\\')) . DS;
      if ($key !== null) {
        // override directory at specified index
        $this->config_dir[$key] = rtrim($v, '/\\') . DS;
      } else {
        // append new directory
        $this->config_dir[] = rtrim($v, '/\\') . DS;
      }
    }
    $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir);
    return $this;
  }
  /**
   * Get config directory
   *
   * @param mixed $index index of directory to get, null to get all
   *
   * @return array|string configuration directory
   */
  public function getConfigDir($index = null)
  {
    if ($index !== null) {
      return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null;
    }
    return (array) $this->config_dir;
  }
  /**
   * Set plugins directory
   *
   * @param string|array $plugins_dir directory(s) of plugins
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setPluginsDir($plugins_dir)
  {
    $this->plugins_dir = array();
    foreach ((array) $plugins_dir as $k => $v) {
      $this->plugins_dir[$k] = rtrim($v, '/\\') . DS;
    }
    return $this;
  }
  /**
   * Adds directory of plugin files
   *
   * @param $plugins_dir
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function addPluginsDir($plugins_dir)
  {
    // make sure we're dealing with an array
    $this->plugins_dir = (array) $this->plugins_dir;
    if (is_array($plugins_dir)) {
      foreach ($plugins_dir as $k => $v) {
        if (is_int($k)) {
          // indexes are not merged but appended
          $this->plugins_dir[] = rtrim($v, '/\\') . DS;
        } else {
          // string indexes are overridden
          $this->plugins_dir[$k] = rtrim($v, '/\\') . DS;
        }
      }
    } else {
      // append new directory
      $this->plugins_dir[] = rtrim($plugins_dir, '/\\') . DS;
    }
    $this->plugins_dir = array_unique($this->plugins_dir);
    return $this;
  }
  /**
   * Get plugin directories
   *
   * @return array list of plugin directories
   */
  public function getPluginsDir()
  {
    return (array) $this->plugins_dir;
  }
  /**
   * Set compile directory
   *
   * @param string $compile_dir directory to store compiled templates in
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function setCompileDir($compile_dir)
  {
    $this->compile_dir = rtrim($compile_dir, '/\\') . DS;
    if (!isset(Smarty::$_muted_directories[$this->compile_dir])) {
      Smarty::$_muted_directories[$this->compile_dir] = null;
    }
    return $this;
  }
  /**
   * Get compiled directory
   *
   * @return string path to compiled templates
   */
  public function getCompileDir()
  {
    return $this->compile_dir;
  }
  /**
   * Set cache directory
   *
   * @param string $cache_dir directory to store cached templates in
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function setCacheDir($cache_dir)
  {
    $this->cache_dir = rtrim($cache_dir, '/\\') . DS;
    if (!isset(Smarty::$_muted_directories[$this->cache_dir])) {
      Smarty::$_muted_directories[$this->cache_dir] = null;
    }
    return $this;
  }
  /**
   * Get cache directory
   *
   * @return string path of cache directory
   */
  public function getCacheDir()
  {
    return $this->cache_dir;
  }
  /**
   * Set default modifiers
   *
   * @param array|string $modifiers modifier or list of modifiers to set
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function setDefaultModifiers($modifiers)
  {
    $this->default_modifiers = (array) $modifiers;
    return $this;
  }
  /**
   * Add default modifiers
   *
   * @param array|string $modifiers modifier or list of modifiers to add
   *
   * @return Smarty    current Smarty instance for chaining
   */
  public function addDefaultModifiers($modifiers)
  {
    if (is_array($modifiers)) {
      $this->default_modifiers = array_merge($this->default_modifiers, $modifiers);
    } else {
      $this->default_modifiers[] = $modifiers;
    }
    return $this;
  }
  /**
   * Get default modifiers
   *
   * @return array list of default modifiers
   */
  public function getDefaultModifiers()
  {
    return $this->default_modifiers;
  }
  /**
   * Set autoload filters
   *
   * @param array $filters filters to load automatically
   * @param string $type  "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function setAutoloadFilters($filters, $type = null)
  {
    if ($type !== null) {
      $this->autoload_filters[$type] = (array) $filters;
    } else {
      $this->autoload_filters = (array) $filters;
    }
    return $this;
  }
  /**
   * Add autoload filters
   *
   * @param array $filters filters to load automatically
   * @param string $type  "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types
   *
   * @return Smarty current Smarty instance for chaining
   */
  public function addAutoloadFilters($filters, $type = null)
  {
    if ($type !== null) {
      if (!empty($this->autoload_filters[$type])) {
        $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters);
      } else {
        $this->autoload_filters[$type] = (array) $filters;
      }
    } else {
      foreach ((array) $filters as $key => $value) {
        if (!empty($this->autoload_filters[$key])) {
          $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value);
        } else {
          $this->autoload_filters[$key] = (array) $value;
        }
      }
    }
    return $this;
  }
  /**
   * Get autoload filters
   *
   * @param string $type type of filter to get autoloads for. Defaults to all autoload filters
   *
   * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type was specified
   */
  public function getAutoloadFilters($type = null)
  {
    if ($type !== null) {
      return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array();
    }
    return $this->autoload_filters;
  }
  /**
   * return name of debugging template
   *
   * @return string
   */
  public function getDebugTemplate()
  {
    return $this->debug_tpl;
  }
  /**
   * set the debug template
   *
   * @param string $tpl_name
   *
   * @return Smarty     current Smarty instance for chaining
   * @throws SmartyException if file is not readable
   */
  public function setDebugTemplate($tpl_name)
  {
    if (!is_readable($tpl_name)) {
      throw new SmartyException("Unknown file '{$tpl_name}'");
    }
    $this->debug_tpl = $tpl_name;
    return $this;
  }
  /**
   * creates a template object
   *
   * @param string $template  the resource handle of the template file
   * @param mixed  $cache_id  cache id to be used with this template
   * @param mixed  $compile_id compile id to be used with this template
   * @param object $parent   next higher level of Smarty variables
   * @param boolean $do_clone  flag is Smarty object shall be cloned
   *
   * @return object template object
   */
  public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
  {
    if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
      $parent = $cache_id;
      $cache_id = null;
    }
    if ($parent !== null && is_array($parent)) {
      $data = $parent;
      $parent = null;
    } else {
      $data = null;
    }
    // default to cache_id and compile_id of Smarty object
    $cache_id = $cache_id === null ? $this->cache_id : $cache_id;
    $compile_id = $compile_id === null ? $this->compile_id : $compile_id;
    // already in template cache?
    if ($this->allow_ambiguous_resources) {
      $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id;
    } else {
      $_templateId = $this->joined_template_dir . '#' . $template . $cache_id . $compile_id;
    }
    if (isset($_templateId[150])) {
      $_templateId = sha1($_templateId);
    }
    if ($do_clone) {
      if (isset($this->template_objects[$_templateId])) {
        // return cached template object
        $tpl = clone $this->template_objects[$_templateId];
        $tpl->smarty = clone $tpl->smarty;
        $tpl->parent = $parent;
        $tpl->tpl_vars = array();
        $tpl->config_vars = array();
      } else {
        $tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id);
      }
    } else {
      if (isset($this->template_objects[$_templateId])) {
        // return cached template object
        $tpl = $this->template_objects[$_templateId];
        $tpl->parent = $parent;
        $tpl->tpl_vars = array();
        $tpl->config_vars = array();
      } else {
        $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id);
      }
    }
    // fill data if present
    if (!empty($data) && is_array($data)) {
      // set up variable values
      foreach ($data as $_key => $_val) {
        $tpl->tpl_vars[$_key] = new Smarty_variable($_val);
      }
    }
    return $tpl;
  }
  /**
   * Takes unknown classes and loads plugin files for them
   * class name format: Smarty_PluginType_PluginName
   * plugin filename format: plugintype.pluginname.php
   *
   * @param string $plugin_name class plugin name to load
   * @param bool  $check    check if already loaded
   *
   * @throws SmartyException
   * @return string |boolean filepath of loaded file or false
   */
  public function loadPlugin($plugin_name, $check = true)
  {
    // if function or class exists, exit silently (already loaded)
    if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) {
      return true;
    }
    // Plugin name is expected to be: Smarty_[Type]_[Name]
    $_name_parts = explode('_', $plugin_name, 3);
    // class name must have three parts to be valid plugin
    // count($_name_parts) < 3 === !isset($_name_parts[2])
    if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') {
      throw new SmartyException("plugin {$plugin_name} is not a valid name format");
    }
    // if type is "internal", get plugin from sysplugins
    if (strtolower($_name_parts[1]) == 'internal') {
      $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php';
      if (file_exists($file)) {
        require_once($file);
        return $file;
      } else {
        return false;
      }
    }
    // plugin filename is expected to be: [type].[name].php
    $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php";
    $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
    // loop through plugin dirs and find the plugin
    foreach ($this->getPluginsDir() as $_plugin_dir) {
      $names = array(
        $_plugin_dir . $_plugin_filename,
        $_plugin_dir . strtolower($_plugin_filename),
      );
      foreach ($names as $file) {
        if (file_exists($file)) {
          require_once($file);
          return $file;
        }
        if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
          // try PHP include_path
          if ($_stream_resolve_include_path) {
            $file = stream_resolve_include_path($file);
          } else {
            $file = Smarty_Internal_Get_Include_Path::getIncludePath($file);
          }
          if ($file !== false) {
            require_once($file);
            return $file;
          }
        }
      }
    }
    // no plugin loaded
    return false;
  }
  /**
   * Compile all template files
   *
   * @param string $extension   file extension
   * @param bool  $force_compile force all to recompile
   * @param int  $time_limit
   * @param int  $max_errors
   *
   * @return integer number of template files recompiled
   */
  public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
  {
    return Smarty_Internal_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this);
  }
  /**
   * Compile all config files
   *
   * @param string $extension   file extension
   * @param bool  $force_compile force all to recompile
   * @param int  $time_limit
   * @param int  $max_errors
   *
   * @return integer number of template files recompiled
   */
  public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null)
  {
    return Smarty_Internal_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this);
  }
  /**
   * Delete compiled template file
   *
   * @param string $resource_name template name
   * @param string $compile_id  compile id
   * @param integer $exp_time   expiration time
   *
   * @return integer number of template files deleted
   */
  public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
  {
    return Smarty_Internal_Utility::clearCompiledTemplate($resource_name, $compile_id, $exp_time, $this);
  }
  /**
   * Return array of tag/attributes of all tags used by an template
   *
   * @param Smarty_Internal_Template $template
   *
   * @return array of tag/attributes
   */
  public function getTags(Smarty_Internal_Template $template)
  {
    return Smarty_Internal_Utility::getTags($template);
  }
  /**
   * Run installation test
   *
   * @param array $errors Array to write errors into, rather than outputting them
   *
   * @return boolean true if setup is fine, false if something is wrong
   */
  public function testInstall(&$errors = null)
  {
    return Smarty_Internal_Utility::testInstall($this, $errors);
  }
  /**
   * Error Handler to mute expected messages
   *
   * @link http://php.net/set_error_handler
   *
   * @param integer $errno Error level
   * @param     $errstr
   * @param     $errfile
   * @param     $errline
   * @param     $errcontext
   *
   * @return boolean
   */
  public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext)
  {
    $_is_muted_directory = false;
    // add the SMARTY_DIR to the list of muted directories
    if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) {
      $smarty_dir = realpath(SMARTY_DIR);
      if ($smarty_dir !== false) {
        Smarty::$_muted_directories[SMARTY_DIR] = array(
          'file'  => $smarty_dir,
          'length' => strlen($smarty_dir),
        );
      }
    }
    // walk the muted directories and test against $errfile
    foreach (Smarty::$_muted_directories as $key => &$dir) {
      if (!$dir) {
        // resolve directory and length for speedy comparisons
        $file = realpath($key);
        if ($file === false) {
          // this directory does not exist, remove and skip it
          unset(Smarty::$_muted_directories[$key]);
          continue;
        }
        $dir = array(
          'file'  => $file,
          'length' => strlen($file),
        );
      }
      if (!strncmp($errfile, $dir['file'], $dir['length'])) {
        $_is_muted_directory = true;
        break;
      }
    }
    // pass to next error handler if this error did not occur inside SMARTY_DIR
    // or the error was within smarty but masked to be ignored
    if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
      if (Smarty::$_previous_error_handler) {
        return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext);
      } else {
        return false;
      }
    }
  }
  /**
   * Enable error handler to mute expected messages
   *
   * @return void
   */
  public static function muteExpectedErrors()
  {
    /*
      error muting is done because some people implemented custom error_handlers using
      http://php.net/set_error_handler and for some reason did not understand the following paragraph:
        It is important to remember that the standard PHP error handler is completely bypassed for the
        error types specified by error_types unless the callback function returns FALSE.
        error_reporting() settings will have no effect and your error handler will be called regardless -
        however you are still able to read the current value of error_reporting and act appropriately.
        Of particular note is that this value will be 0 if the statement that caused the error was
        prepended by the @ error-control operator.
      Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include
        - @filemtime() is almost twice as fast as using an additional file_exists()
        - between file_exists() and filemtime() a possible race condition is opened,
         which does not exist using the simple @filemtime() approach.
    */
    $error_handler = array('Smarty', 'mutingErrorHandler');
    $previous = set_error_handler($error_handler);
    // avoid dead loops
    if ($previous !== $error_handler) {
      Smarty::$_previous_error_handler = $previous;
    }
  }
  /**
   * Disable error handler muting expected messages
   *
   * @return void
   */
  public static function unmuteExpectedErrors()
  {
    restore_error_handler();
  }
}
// Check if we're running on windows
Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
// let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
if (Smarty::$_CHARSET !== 'UTF-8') {
  Smarty::$_UTF8_MODIFIER = '';
}
/**
 * Smarty exception class
 *
 * @package Smarty
 */
class SmartyException extends Exception
{
  public static $escape = false;
  public function __toString()
  {
    return ' --> Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- ';
  }
}
/**
 * Smarty compiler exception class
 *
 * @package Smarty
 */
class SmartyCompilerException extends SmartyException
{
  public function __toString()
  {
    return ' --> Smarty Compiler: ' . $this->message . ' <-- ';
  }
  /**
   * The line number of the template error
   *
   * @type int|null
   */
  public $line = null;
  /**
   * The template source snippet relating to the error
   *
   * @type string|null
   */
  public $source = null;
  /**
   * The raw text of the error message
   *
   * @type string|null
   */
  public $desc = null;
  /**
   * The resource identifier or template name
   *
   * @type string|null
   */
  public $template = null;
}
/**
 * Autoloader
 */
function smartyAutoload($class)
{
  $_class = strtolower($class);
  static $_classes = array(
    'smarty_config_source'        => true,
    'smarty_config_compiled'       => true,
    'smarty_security'          => true,
    'smarty_cacheresource'        => true,
    'smarty_cacheresource_custom'    => true,
    'smarty_cacheresource_keyvaluestore' => true,
    'smarty_resource'          => true,
    'smarty_resource_custom'       => true,
    'smarty_resource_uncompiled'     => true,
    'smarty_resource_recompiled'     => true,
  );
  if (!strncmp($_class, 'smarty_internal_', 16) || isset($_classes[$_class])) {
    include SMARTY_SYSPLUGINS_DIR . $_class . '.php';
  }
}

希望本文所述对大家基于smarty模板的PHP程序设计有所帮助。

PHP 相关文章推荐
使用php重新实现PHP脚本引擎内置函数
Mar 06 PHP
PHP连接Access数据库的方法小结
Jun 20 PHP
php实例分享之通过递归实现删除目录下的所有文件详解
May 15 PHP
php生成随机颜色方法汇总
Dec 03 PHP
PHP超牛逼无限极分类生成树方法
May 11 PHP
PHPStrom中实用的功能和快捷键大全
Sep 23 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
Oct 19 PHP
php脚本守护进程原理与实现方法详解
Jul 20 PHP
SCP远程VPS快速搬家和WDCP升级php5.3安装memcached和eaccelerator教程
Jul 27 PHP
Laravel学习教程之View模块详解
Sep 18 PHP
PHP parse_ini_file函数的应用与扩展操作示例
Jan 07 PHP
php+mysql开发的最简单在线题库(在线做题系统)完整案例
Mar 30 PHP
PHP内存缓存功能memcached示例
Oct 19 #PHP
PHP实现上传图片到 zimg 服务器
Oct 19 #PHP
php通过会话控制实现身份验证实例
Oct 18 #PHP
利用php_imagick实现复古效果的方法
Oct 18 #PHP
php封装的page分页类完整实例
Oct 18 #PHP
php封装的单文件(图片)上传类完整实例
Oct 18 #PHP
Thinkphp实现短信验证注册功能
Oct 18 #PHP
You might like
用PHP创建PDF中文文档
2006/10/09 PHP
php file_exists 检查文件或目录是否存在的函数
2010/05/10 PHP
php Static关键字实用方法
2010/06/04 PHP
thinkPHP分组后模板无法加载问题解决方法
2016/07/12 PHP
php格式文件打开的四种方法
2018/02/24 PHP
js类中获取外部函数名的方法
2007/08/19 Javascript
javascript循环变量注册dom事件 之强大的闭包
2010/09/08 Javascript
基于jQuery的计算文本框字数的代码
2012/06/06 Javascript
JS操作Cookie写入和读取实例代码
2013/10/20 Javascript
js实现的点击数量加一可操作数据库
2014/05/09 Javascript
js获取当前时间显示在页面上并每秒刷新
2014/12/24 Javascript
基于JavaScript代码实现pc与手机之间的跳转
2015/12/23 Javascript
浅析jquery与checkbox的checked属性的问题
2016/04/27 Javascript
ES6新特征数字、数组、字符串
2016/10/01 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
2017/03/01 Javascript
js实现悬浮窗效果(支持拖动)
2017/03/09 Javascript
WebStorm ES6 语法支持设置&amp;babel使用及自动编译(详解)
2017/09/08 Javascript
es6系列教程_ Map详解以及常用api介绍
2017/09/25 Javascript
AngularJs 终极购物车(实例讲解)
2017/11/08 Javascript
10个在JavaScript开发中常遇到的BUG
2017/12/18 Javascript
基于Vue中点击组件外关闭组件的实现方法
2018/03/06 Javascript
layui实现数据表格table分页功能(ajax异步)
2019/07/27 Javascript
python回溯法实现数组全排列输出实例分析
2015/03/17 Python
使用PYTHON解析Wireshark的PCAP文件方法
2019/07/23 Python
Python函数默认参数常见问题及解决方案
2020/03/26 Python
python3中sys.argv的实例用法
2020/04/24 Python
Application Cache未缓存文件无法访问无法加载问题
2014/05/31 HTML / CSS
Airbnb爱彼迎官网:成为爱彼迎房东,赚取收入
2019/03/14 全球购物
新西兰最大的连锁超市:Countdown
2020/06/04 全球购物
信用社员工先进事迹材料
2014/02/04 职场文书
市优秀教师事迹材料
2014/02/05 职场文书
企业爱岗敬业演讲稿
2014/09/04 职场文书
法人代表证明书
2014/09/18 职场文书
实习工作表现评语
2014/12/31 职场文书
党员干部公开承诺书范文
2015/04/27 职场文书
MySQL中连接查询和子查询的问题
2021/09/04 MySQL