PageRenderTime 55ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/smarty/vendor/smarty/Smarty.class.php

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