update Smarty to 3.1.29

git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1841 a1433add-5e2c-0410-b055-b7f2511e0802
pull/19/head
David Goodwin 9 years ago
parent 54603b0968
commit 2bed4110a5

@ -1,5 +1,7 @@
<?php <?php
require_once ("$incpath/smarty/libs/Smarty.class.php");
require_once(dirname(__FILE__) . '/smarty/libs/Autoloader.php');
Smarty_Autoloader::register();
/** /**
* Turn on sanitisation of all data by default so it's not possible for XSS flaws to occur in PFA * Turn on sanitisation of all data by default so it's not possible for XSS flaws to occur in PFA
@ -11,9 +13,9 @@ class PFASmarty {
//$this->template->debugging = true; //$this->template->debugging = true;
$incpath = dirname(__FILE__); $incpath = dirname(__FILE__);
$this->template->template_dir = $incpath.'/templates'; $this->template->setTemplateDir(dirname(__FILE__) . '/templates');
$this->template->compile_dir = $incpath.'/templates_c'; $this->template->setCompileDir(dirname(__FILE__) . '/templates_c');
$this->template->config_dir = $incpath.'/'.$this->template->config_dir[0]; $this->template->setConfigDir(dirname(__FILE__) . '/configs');
} }
public function assign($key, $value, $sanitise = true) { public function assign($key, $value, $sanitise = true) {

@ -0,0 +1,124 @@
<?php
/**
* Smarty Autoloader
*
* @package Smarty
*/
/**
* Smarty Autoloader
*
* @package Smarty
* @author Uwe Tews
* Usage:
* require_once '...path/Autoloader.php';
* Smarty_Autoloader::register();
* $smarty = new Smarty();
* Note: This autoloader is not needed if you use Composer.
* Composer will automatically add the classes of the Smarty package to it common autoloader.
*/
class Smarty_Autoloader
{
/**
* Filepath to Smarty root
*
* @var string
*/
public static $SMARTY_DIR = '';
/**
* Filepath to Smarty internal plugins
*
* @var string
*/
public static $SMARTY_SYSPLUGINS_DIR = '';
/**
* Array with Smarty core classes and their filename
*
* @var array
*/
public static $rootClasses = array('smarty' => 'Smarty.class.php', 'smartybc' => 'SmartyBC.class.php',);
/**
* Registers Smarty_Autoloader backward compatible to older installations.
*
* @param bool $prepend Whether to prepend the autoloader or not.
*/
public static function registerBC($prepend = false)
{
/**
* 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 {
self::register($prepend);
}
}
/**
* Registers Smarty_Autoloader as an SPL autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not.
*/
public static function register($prepend = false)
{
self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . DIRECTORY_SEPARATOR;
self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR :
self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR;
if (version_compare(phpversion(), '5.3.0', '>=')) {
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
} else {
spl_autoload_register(array(__CLASS__, 'autoload'));
}
}
/**
* Handles auto loading of classes.
*
* @param string $class A class name.
*/
public static function autoload($class)
{
$_class = strtolower($class);
$file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php';
if (strpos($_class, 'smarty_internal_') === 0) {
if (strpos($_class, 'smarty_internal_compile_') === 0) {
if (is_file($file)) {
require $file;
}
return;
}
@include $file;
return;
}
if (preg_match('/^(smarty_(((template_(source|config|cache|compiled|resource_base))|((cached|compiled)?resource)|(variable|security)))|(smarty(bc)?)$)/',
$_class, $match)) {
if (!empty($match[3])) {
@include $file;
return;
} elseif (!empty($match[9]) && isset(self::$rootClasses[$_class])) {
$file = self::$rootClasses[$_class];
require $file;
return;
}
}
if (0 !== strpos($_class, 'smarty')) {
return;
}
if (is_file($file)) {
require $file;
return;
}
return;
}
}

File diff suppressed because it is too large Load Diff

@ -44,6 +44,13 @@ class SmartyBC extends Smarty
*/ */
public $_version = self::SMARTY_VERSION; public $_version = self::SMARTY_VERSION;
/**
* This is an array of directories where trusted php scripts reside.
*
* @var array
*/
public $trusted_dir = array();
/** /**
* Initialize new SmartyBC object * Initialize new SmartyBC object
* *
@ -52,8 +59,6 @@ class SmartyBC extends Smarty
public function __construct(array $options = array()) public function __construct(array $options = array())
{ {
parent::__construct($options); parent::__construct($options);
// register {php} tag
$this->registerPlugin('block', 'php', 'smarty_php_tag');
} }
/** /**
@ -448,20 +453,3 @@ class SmartyBC extends Smarty
trigger_error("Smarty error: $error_msg", $error_type); trigger_error("Smarty error: $error_msg", $error_type);
} }
} }
/**
* Smarty {php}{/php} block function
*
* @param array $params parameter list
* @param string $content contents of the block
* @param object $template template object
* @param boolean &$repeat repeat flag
*
* @return string content re-formatted
*/
function smarty_php_tag($params, $content, $template, &$repeat)
{
eval($content);
return '';
}

@ -5,7 +5,7 @@
<title>Smarty Debug Console</title> <title>Smarty Debug Console</title>
<style type="text/css"> <style type="text/css">
{literal} {literal}
body, h1, h2, td, th, p { body, h1, h2, h3, td, th, p {
font-family: sans-serif; font-family: sans-serif;
font-weight: normal; font-weight: normal;
font-size: 0.9em; font-size: 0.9em;
@ -31,6 +31,13 @@
padding: 2px; padding: 2px;
border-top: 1px solid black; border-top: 1px solid black;
} }
h3 {
text-align: left;
font-weight: bold;
color: black;
font-size: 0.7em;
padding: 2px;
}
body { body {
background: black; background: black;
@ -54,7 +61,6 @@
font-family: monospace; font-family: monospace;
vertical-align: top; vertical-align: top;
text-align: left; text-align: left;
width: 50%;
} }
td { td {
@ -74,8 +80,20 @@
font-style: italic; font-style: italic;
} }
#bold div {
color: black;
font-weight: bold;
}
#blue h3 {
color: blue;
}
#normal div {
color: black;
font-weight: normal;
}
#table_assigned_vars th { #table_assigned_vars th {
color: blue; color: blue;
font-weight: bold;
} }
#table_config_vars th { #table_config_vars th {
@ -87,17 +105,16 @@
</head> </head>
<body> <body>
<h1>Smarty Debug Console <h1>Smarty {Smarty::SMARTY_VERSION} Debug Console
- {if isset($template_name)}{$template_name|debug_print_var nofilter}{else}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1> - {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
{if !empty($template_data)} {if !empty($template_data)}
<h2>included templates &amp; config files (load time in seconds)</h2> <h2>included templates &amp; config files (load time in seconds)</h2>
<div> <div>
{foreach $template_data as $template} {foreach $template_data as $template}
<font color=brown>{$template.name}</font> <font color=brown>{$template.name}</font>
<span class="exectime"> <br>&nbsp;&nbsp;<span class="exectime">
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"} (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
)
</span> </span>
<br> <br>
{/foreach} {/foreach}
@ -109,19 +126,24 @@
<table id="table_assigned_vars"> <table id="table_assigned_vars">
{foreach $assigned_vars as $vars} {foreach $assigned_vars as $vars}
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}"> <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
<th>${$vars@key|escape:'html'}</th> <td><h3><font color=blue>${$vars@key}</font></h3>
<td>{$vars|debug_print_var nofilter}</td> {if isset($vars['nocache'])}<b>Nocache</b></br>{/if}
</tr> {if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
</td>
<td><h3>Value</h3>{$vars['value']|debug_print_var:10:80 nofilter}</td>
<td>{if isset($vars['attributes'])}<h3>Attributes</h3>{$vars['attributes']|debug_print_var nofilter} {/if}</td>
{/foreach} {/foreach}
</table> </table>
<h2>assigned config file variables (outer template scope)</h2> <h2>assigned config file variables</h2>
<table id="table_config_vars"> <table id="table_config_vars">
{foreach $config_vars as $vars} {foreach $config_vars as $vars}
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}"> <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
<th>{$vars@key|escape:'html'}</th> <td><h3><font color=blue>#{$vars@key}#</font></h3>
<td>{$vars|debug_print_var nofilter}</td> {if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
</td>
<td>{$vars['value']|debug_print_var:10:80 nofilter}</td>
</tr> </tr>
{/foreach} {/foreach}
@ -130,8 +152,9 @@
</html> </html>
{/capture} {/capture}
<script type="text/javascript"> <script type="text/javascript">
{$id = $template_name|default:''|md5} {$id = '__Smarty__'}
_smarty_console = window.open("", "console{$id}", "width=680,height=600,resizable,scrollbars=yes"); {if $display_mode}{$id = "$offset$template_name"|md5}{/if}
_smarty_console = window.open("", "console{$id}", "width=1024,height=600,left={$offset},top={$offset},resizable,scrollbars=yes");
_smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}"); _smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}");
_smarty_console.document.close(); _smarty_console.document.close();
</script> </script>

@ -33,7 +33,7 @@ function smarty_modifier_date_format($string, $format = null, $default_date = ''
$format = Smarty::$_DATE_FORMAT; $format = Smarty::$_DATE_FORMAT;
} }
/** /**
* Include the {@link shared.make_timestamp.php} plugin * require_once the {@link shared.make_timestamp.php} plugin
*/ */
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php'); require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
if ($string != '' && $string != '0000-00-00' && $string != '0000-00-00 00:00:00') { if ($string != '' && $string != '0000-00-00' && $string != '0000-00-00 00:00:00') {

@ -15,25 +15,29 @@
* @author Monte Ohrt <monte at ohrt dot com> * @author Monte Ohrt <monte at ohrt dot com>
* *
* @param array|object $var variable to be formatted * @param array|object $var variable to be formatted
* @param integer $depth maximum recursion depth if $var is an array * @param int $max maximum recursion depth if $var is an array or object
* @param integer $length maximum string length if $var is a string * @param int $length maximum string length if $var is a string
* @param int $depth actual recursion depth
* @param array $objects processed objects in actual depth to prevent recursive object processing
* *
* @return string * @return string
*/ */
function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40) function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
{ {
$_replace = array("\n" => '<i>\n</i>', $_replace = array("\n" => '\n',
"\r" => '<i>\r</i>', "\r" => '\r',
"\t" => '<i>\t</i>' "\t" => '\t'
); );
switch (gettype($var)) { switch (gettype($var)) {
case 'array' : case 'array' :
$results = '<b>Array (' . count($var) . ')</b>'; $results = '<b>Array (' . count($var) . ')</b>';
if ($depth == $max) {
break;
}
foreach ($var as $curr_key => $curr_val) { foreach ($var as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
. '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; ' . '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length); . smarty_modifier_debug_print_var($curr_val, $max, $length, ++ $depth, $objects);
$depth --; $depth --;
} }
break; break;
@ -41,10 +45,18 @@ function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
case 'object' : case 'object' :
$object_vars = get_object_vars($var); $object_vars = get_object_vars($var);
$results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>'; $results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
if (in_array($var, $objects)) {
$results .= ' called recursive';
break;
}
if ($depth == $max) {
break;
}
$objects[] = $var;
foreach ($object_vars as $curr_key => $curr_val) { foreach ($object_vars as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
. '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = ' . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length); . smarty_modifier_debug_print_var($curr_val, $max, $length, ++ $depth, $objects);
$depth --; $depth --;
} }
break; break;

@ -19,10 +19,11 @@
* @param string $string input string * @param string $string input string
* @param string|array $search regular expression(s) to search for * @param string|array $search regular expression(s) to search for
* @param string|array $replace string(s) that should be replaced * @param string|array $replace string(s) that should be replaced
* @param int $limit the maximum number of replacements
* *
* @return string * @return string
*/ */
function smarty_modifier_regex_replace($string, $search, $replace) function smarty_modifier_regex_replace($string, $search, $replace, $limit = -1)
{ {
if (is_array($search)) { if (is_array($search)) {
foreach ($search as $idx => $s) { foreach ($search as $idx => $s) {
@ -32,7 +33,7 @@ function smarty_modifier_regex_replace($string, $search, $replace)
$search = _smarty_regex_replace_check($search); $search = _smarty_regex_replace_check($search);
} }
return preg_replace($search, $replace, $string); return preg_replace($search, $replace, $string, $limit);
} }
/** /**

@ -115,11 +115,11 @@ function smarty_modifiercompiler_escape($params, $compiler)
// could not optimize |escape call, so fallback to regular plugin // could not optimize |escape call, so fallback to regular plugin
if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) { if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) {
$compiler->template->required_plugins['nocache']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'modifier.escape.php'; $compiler->parent_compiler->template->compiled->required_plugins['nocache']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'modifier.escape.php';
$compiler->template->required_plugins['nocache']['escape']['modifier']['function'] = 'smarty_modifier_escape'; $compiler->parent_compiler->template->compiled->required_plugins['nocache']['escape']['modifier']['function'] = 'smarty_modifier_escape';
} else { } else {
$compiler->template->required_plugins['compiled']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'modifier.escape.php'; $compiler->parent_compiler->template->compiled->required_plugins['compiled']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'modifier.escape.php';
$compiler->template->required_plugins['compiled']['escape']['modifier']['function'] = 'smarty_modifier_escape'; $compiler->parent_compiler->template->compiled->required_plugins['compiled']['escape']['modifier']['function'] = 'smarty_modifier_escape';
} }
return 'smarty_modifier_escape(' . join(', ', $params) . ')'; return 'smarty_modifier_escape(' . join(', ', $params) . ')';

@ -12,7 +12,7 @@
* Name: strip_tags<br> * Name: strip_tags<br>
* Purpose: strip html tags from text * Purpose: strip html tags from text
* *
* @link http://www.smarty.net/manual/en/language.modifier.strip.tags.php strip_tags (Smarty online manual) * @link http://www.smarty.net/docs/en/language.modifier.strip.tags.tpl strip_tags (Smarty online manual)
* @author Uwe Tews * @author Uwe Tews
* *
* @param array $params parameters * @param array $params parameters

@ -34,11 +34,11 @@ function smarty_modifiercompiler_wordwrap($params, $compiler)
$function = 'wordwrap'; $function = 'wordwrap';
if (Smarty::$_MBSTRING) { if (Smarty::$_MBSTRING) {
if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) { if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) {
$compiler->template->required_plugins['nocache']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php'; $compiler->parent_compiler->template->compiled->required_plugins['nocache']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php';
$compiler->template->required_plugins['nocache']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap'; $compiler->template->required_plugins['nocache']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap';
} else { } else {
$compiler->template->required_plugins['compiled']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php'; $compiler->parent_compiler->template->compiled->required_plugins['compiled']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php';
$compiler->template->required_plugins['compiled']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap'; $compiler->parent_compiler->template->compiled->required_plugins['compiled']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap';
} }
$function = 'smarty_mb_wordwrap'; $function = 'smarty_mb_wordwrap';
} }

@ -45,7 +45,7 @@ function smarty_outputfilter_trimwhitespace($source)
// capture html elements not to be messed with // capture html elements not to be messed with
$_offset = 0; $_offset = 0;
if (preg_match_all('#<(script|pre|textarea)[^>]*>.*?</\\1>#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { if (preg_match_all('#(<script[^>]*>.*?</script[^>]*>)|(<textarea[^>]*>.*?</textarea[^>]*>)|(<pre[^>]*>.*?</pre[^>]*>)#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
foreach ($matches as $match) { foreach ($matches as $match) {
$store[] = $match[0][0]; $store[] = $match[0][0];
$_length = strlen($match[0][0]); $_length = strlen($match[0][0]);
@ -62,7 +62,7 @@ function smarty_outputfilter_trimwhitespace($source)
// can't remove them entirely, becaue that might break poorly implemented CSS display:inline-block elements // can't remove them entirely, becaue that might break poorly implemented CSS display:inline-block elements
'#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2', '#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2',
// remove spaces between attributes (but not in attribute values!) // remove spaces between attributes (but not in attribute values!)
'#(([a-z0-9]\s*=\s*(["\'])[^\3]*?\3)|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \4', '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
// note: for some very weird reason trim() seems to remove spaces inside attributes. // note: for some very weird reason trim() seems to remove spaces inside attributes.
// maybe a \0 byte or something is interfering? // maybe a \0 byte or something is interfering?
'#^\s+<#Ss' => '<', '#^\s+<#Ss' => '<',

@ -21,8 +21,8 @@ function smarty_make_timestamp($string)
if (empty($string)) { if (empty($string)) {
// use "now": // use "now":
return time(); return time();
} elseif ($string instanceof DateTime) { } elseif ($string instanceof DateTime || (interface_exists('DateTimeInterface', false) && $string instanceof DateTimeInterface)) {
return $string->getTimestamp(); return (int) $string->format('U'); // PHP 5.2 BC
} elseif (strlen($string) == 14 && ctype_digit($string)) { } elseif (strlen($string) == 14 && ctype_digit($string)) {
// it is mysql timestamp format of YYYYMMDDHHMMSS? // it is mysql timestamp format of YYYYMMDDHHMMSS?
return mktime(substr($string, 8, 2), substr($string, 10, 2), substr($string, 12, 2), return mktime(substr($string, 8, 2), substr($string, 10, 2), substr($string, 12, 2),

@ -15,21 +15,12 @@
*/ */
abstract class Smarty_CacheResource abstract class Smarty_CacheResource
{ {
/**
* cache for Smarty_CacheResource instances
*
* @var array
*/
public static $resources = array();
/** /**
* resource types provided by the core * resource types provided by the core
* *
* @var array * @var array
*/ */
protected static $sysplugins = array( protected static $sysplugins = array('file' => 'smarty_internal_cacheresource_file.php',);
'file' => true,
);
/** /**
* populate Cached Object with meta data from Resource * populate Cached Object with meta data from Resource
@ -55,10 +46,11 @@ abstract class Smarty_CacheResource
* *
* @param Smarty_Internal_Template $_template template object * @param Smarty_Internal_Template $_template template object
* @param Smarty_Template_Cached $cached cached object * @param Smarty_Template_Cached $cached cached object
* @param bool $update flag if called because cache update
* *
* @return boolean true or false if the cached content does not exist * @return bool true or false if the cached content does not exist
*/ */
abstract public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null); abstract public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null, $update = false);
/** /**
* Write the rendered template output to cache * Write the rendered template output to cache
@ -81,8 +73,8 @@ abstract class Smarty_CacheResource
{ {
if ($_template->cached->handler->process($_template)) { if ($_template->cached->handler->process($_template)) {
ob_start(); ob_start();
$_template->properties['unifunc']($_template); $unifunc = $_template->cached->unifunc;
$unifunc($_template);
return ob_get_clean(); return ob_get_clean();
} }
@ -193,32 +185,24 @@ abstract class Smarty_CacheResource
} }
// try smarty's cache // try smarty's cache
if (isset($smarty->_cacheresource_handlers[$type])) { if (isset($smarty->_cache['cacheresource_handlers'][$type])) {
return $smarty->_cacheresource_handlers[$type]; return $smarty->_cache['cacheresource_handlers'][$type];
} }
// try registered resource // try registered resource
if (isset($smarty->registered_cache_resources[$type])) { if (isset($smarty->registered_cache_resources[$type])) {
// do not cache these instances as they may vary from instance to instance // do not cache these instances as they may vary from instance to instance
return $smarty->_cacheresource_handlers[$type] = $smarty->registered_cache_resources[$type]; return $smarty->_cache['cacheresource_handlers'][$type] = $smarty->registered_cache_resources[$type];
} }
// try sysplugins dir // try sysplugins dir
if (isset(self::$sysplugins[$type])) { if (isset(self::$sysplugins[$type])) {
if (!isset(self::$resources[$type])) {
$cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type); $cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
self::$resources[$type] = new $cache_resource_class(); return $smarty->_cache['cacheresource_handlers'][$type] = new $cache_resource_class();
}
return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
} }
// try plugins dir // try plugins dir
$cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type); $cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type);
if ($smarty->loadPlugin($cache_resource_class)) { if ($smarty->loadPlugin($cache_resource_class)) {
if (!isset(self::$resources[$type])) { return $smarty->_cache['cacheresource_handlers'][$type] = new $cache_resource_class();
self::$resources[$type] = new $cache_resource_class();
}
return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
} }
// give up // give up
throw new SmartyException("Unable to load cache resource '{$type}'"); throw new SmartyException("Unable to load cache resource '{$type}'");
@ -229,214 +213,11 @@ abstract class Smarty_CacheResource
* *
* @param Smarty $smarty Smarty object * @param Smarty $smarty Smarty object
*/ */
public static function invalidLoadedCache(Smarty $smarty) public function invalidLoadedCache(Smarty $smarty)
{
foreach ($smarty->template_objects as $tpl) {
if (isset($tpl->cached)) {
$tpl->cached->valid = false;
$tpl->cached->processed = false;
}
}
}
}
/**
* Smarty Resource Data Object
* Cache Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
*/
class Smarty_Template_Cached
{
/**
* Source Filepath
*
* @var string
*/
public $filepath = false;
/**
* Source Content
*
* @var string
*/
public $content = null;
/**
* Source Timestamp
*
* @var integer
*/
public $timestamp = false;
/**
* Source Existence
*
* @var boolean
*/
public $exists = false;
/**
* Cache Is Valid
*
* @var boolean
*/
public $valid = false;
/**
* Cache was processed
*
* @var boolean
*/
public $processed = false;
/**
* CacheResource Handler
*
* @var Smarty_CacheResource
*/
public $handler = null;
/**
* Template Compile Id (Smarty_Internal_Template::$compile_id)
*
* @var string
*/
public $compile_id = null;
/**
* Template Cache Id (Smarty_Internal_Template::$cache_id)
*
* @var string
*/
public $cache_id = null;
/**
* Id for cache locking
*
* @var string
*/
public $lock_id = null;
/**
* flag that cache is locked by this instance
*
* @var bool
*/
public $is_locked = false;
/**
* Source Object
*
* @var Smarty_Template_Source
*/
public $source = null;
/**
* create Cached Object container
*
* @param Smarty_Internal_Template $_template template object
*/
public function __construct(Smarty_Internal_Template $_template)
{
$this->compile_id = $_template->compile_id;
$this->cache_id = $_template->cache_id;
$this->source = $_template->source;
$_template->cached = $this;
$smarty = $_template->smarty;
//
// load resource handler
//
$this->handler = $handler = Smarty_CacheResource::load($smarty); // Note: prone to circular references
//
// check if cache is valid
//
if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->recompiled) {
$handler->populate($this, $_template);
return;
}
while (true) {
while (true) {
$handler->populate($this, $_template);
if ($this->timestamp === false || $smarty->force_compile || $smarty->force_cache) {
$this->valid = false;
} else {
$this->valid = true;
}
if ($this->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)) {
// lifetime expired
$this->valid = false;
}
if ($this->valid || !$_template->smarty->cache_locking) {
break;
}
if (!$this->handler->locked($_template->smarty, $this)) {
$this->handler->acquireLock($_template->smarty, $this);
break 2;
}
}
if ($this->valid) {
if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) {
// load cache file for the following checks
if ($smarty->debugging) {
Smarty_Internal_Debug::start_cache($_template);
}
if ($handler->process($_template, $this) === false) {
$this->valid = false;
} else {
$this->processed = true;
}
if ($smarty->debugging) {
Smarty_Internal_Debug::end_cache($_template);
}
} else {
continue;
}
} else {
return;
}
if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && $_template->properties['cache_lifetime'] >= 0 && (time() > ($_template->cached->timestamp + $_template->properties['cache_lifetime']))) {
$this->valid = false;
}
if (!$this->valid && $_template->smarty->cache_locking) {
$this->handler->acquireLock($_template->smarty, $this);
return;
} else {
return;
}
}
}
/**
* Write this cache object to handler
*
* @param Smarty_Internal_Template $_template template object
* @param string $content content to cache
*
* @return boolean success
*/
public function write(Smarty_Internal_Template $_template, $content)
{ {
if (!$_template->source->recompiled) { $smarty->_cache['isCached'] = array();
if ($this->handler->writeCachedContent($_template, $content)) { if (isset($smarty->ext->_subtemplate)) {
$this->content = null; $smarty->ext->_subtemplate->tplObjects = array();
$this->timestamp = time();
$this->exists = true;
$this->valid = true;
if ($_template->smarty->cache_locking) {
$this->handler->releaseLock($_template->smarty, $this);
} }
return true;
}
}
return false;
} }
} }

@ -83,9 +83,12 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template) public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
{ {
$_cache_id = isset($cached->cache_id) ? preg_replace('![^\w\|]+!', '_', $cached->cache_id) : null; $_cache_id = isset($cached->cache_id) ? preg_replace('![^\w\|]+!', '_', $cached->cache_id) : null;
$_compile_id = isset($cached->compile_id) ? preg_replace('![^\w\|]+!', '_', $cached->compile_id) : null; $_compile_id = isset($cached->compile_id) ? preg_replace('![^\w]+!', '_', $cached->compile_id) : null;
$path = $cached->source->filepath . $_cache_id . $_compile_id;
$cached->filepath = sha1($cached->source->filepath . $_cache_id . $_compile_id); $cached->filepath = sha1($path);
if ($_template->smarty->cache_locking) {
$cached->lock_id = sha1('lock.' . $path);
}
$this->populateTimestamp($cached); $this->populateTimestamp($cached);
} }
@ -116,10 +119,11 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
* *
* @param Smarty_Internal_Template $_template template object * @param Smarty_Internal_Template $_template template object
* @param Smarty_Template_Cached $cached cached object * @param Smarty_Template_Cached $cached cached object
* @param bool $update flag if called because cache update
* *
* @return boolean true or false if the cached content does not exist * @return boolean true or false if the cached content does not exist
*/ */
public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null) public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null, $update = false)
{ {
if (!$cached) { if (!$cached) {
$cached = $_template->cached; $cached = $_template->cached;
@ -127,14 +131,7 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
$content = $cached->content ? $cached->content : null; $content = $cached->content ? $cached->content : null;
$timestamp = $cached->timestamp ? $cached->timestamp : null; $timestamp = $cached->timestamp ? $cached->timestamp : null;
if ($content === null || !$timestamp) { if ($content === null || !$timestamp) {
$this->fetch( $this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $content, $timestamp);
$_template->cached->filepath,
$_template->source->name,
$_template->cache_id,
$_template->compile_id,
$content,
$timestamp
);
} }
if (isset($content)) { if (isset($content)) {
/** @var Smarty_Internal_Template $_smarty_tpl /** @var Smarty_Internal_Template $_smarty_tpl
@ -142,7 +139,7 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
*/ */
$_smarty_tpl = $_template; $_smarty_tpl = $_template;
eval("?>" . $content); eval("?>" . $content);
$cached->content = null;
return true; return true;
} }
@ -159,14 +156,28 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
*/ */
public function writeCachedContent(Smarty_Internal_Template $_template, $content) public function writeCachedContent(Smarty_Internal_Template $_template, $content)
{ {
return $this->save( return $this->save($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $_template->cache_lifetime, $content);
$_template->cached->filepath, }
$_template->source->name,
$_template->cache_id, /**
$_template->compile_id, * Read cached template from cache
$_template->properties['cache_lifetime'], *
$content * @param Smarty_Internal_Template $_template template object
); *
* @return string content
*/
public function readCachedContent(Smarty_Internal_Template $_template)
{
$content = $_template->cached->content ? $_template->cached->content : null;
$timestamp = null;
if ($content === null) {
$timestamp = null;
$this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $content, $timestamp);
}
if (isset($content)) {
return $content;
}
return false;
} }
/** /**
@ -179,8 +190,6 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
*/ */
public function clearAll(Smarty $smarty, $exp_time = null) public function clearAll(Smarty $smarty, $exp_time = null)
{ {
$this->cache = array();
return $this->delete(null, null, null, $exp_time); return $this->delete(null, null, null, $exp_time);
} }
@ -197,32 +206,23 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
*/ */
public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
{ {
$this->cache = array();
$cache_name = null; $cache_name = null;
if (isset($resource_name)) { if (isset($resource_name)) {
$_save_stat = $smarty->caching; $source = Smarty_Template_Source::load(null, $smarty, $resource_name);
$smarty->caching = true; if ($source->exists) {
$tpl = new $smarty->template_class($resource_name, $smarty); $cache_name = $source->name;
$smarty->caching = $_save_stat;
if ($tpl->source->exists) {
$cache_name = $tpl->source->name;
} else { } else {
return 0; return 0;
} }
// remove from template cache // remove from template cache
if ($smarty->allow_ambiguous_resources) { if (isset($smarty->_cache['template_objects'])) {
$_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id; foreach ($smarty->_cache['template_objects'] as $key => $_tpl) {
} else { if (isset($_tpl->cached) && $_tpl->source->uid == $source->uid) {
$_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id; unset($smarty->_cache['template_objects'][$key]);
}
} }
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
} }
unset($smarty->template_objects[$_templateId]);
// template object no longer needed
unset($tpl);
} }
return $this->delete($cache_name, $cache_id, $compile_id, $exp_time); return $this->delete($cache_name, $cache_id, $compile_id, $exp_time);
@ -238,15 +238,14 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
*/ */
public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached) public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
{ {
$id = $cached->filepath; $id = $cached->lock_id;
$name = $cached->source->name . '.lock'; $name = $cached->source->name . '.lock';
$mtime = $this->fetchTimestamp($id, $name, null, null); $mtime = $this->fetchTimestamp($id, $name, $cached->cache_id, $cached->compile_id);
if ($mtime === null) { if ($mtime === null) {
$this->fetch($id, $name, null, null, $content, $mtime); $this->fetch($id, $name, $cached->cache_id, $cached->compile_id, $content, $mtime);
} }
return $mtime && ($t = time()) - $mtime < $smarty->locking_timeout;
return $mtime && time() - $mtime < $smarty->locking_timeout;
} }
/** /**
@ -260,10 +259,9 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached) public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
{ {
$cached->is_locked = true; $cached->is_locked = true;
$id = $cached->lock_id;
$id = $cached->filepath;
$name = $cached->source->name . '.lock'; $name = $cached->source->name . '.lock';
$this->save($id, $name, null, null, $smarty->locking_timeout, ''); $this->save($id, $name, $cached->cache_id, $cached->compile_id, $smarty->locking_timeout, '');
} }
/** /**
@ -277,8 +275,7 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached) public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
{ {
$cached->is_locked = false; $cached->is_locked = false;
$name = $cached->source->name . '.lock'; $name = $cached->source->name . '.lock';
$this->delete($name, null, null, null); $this->delete($name, $cached->cache_id, $cached->compile_id, null);
} }
} }

@ -36,6 +36,7 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
* @var array * @var array
*/ */
protected $contents = array(); protected $contents = array();
/** /**
* cache for timestamps * cache for timestamps
* *
@ -53,10 +54,8 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
*/ */
public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template) public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
{ {
$cached->filepath = $_template->source->uid $cached->filepath = $_template->source->uid . '#' . $this->sanitize($cached->source->resource) . '#' .
. '#' . $this->sanitize($cached->source->resource) $this->sanitize($cached->cache_id) . '#' . $this->sanitize($cached->compile_id);
. '#' . $this->sanitize($cached->cache_id)
. '#' . $this->sanitize($cached->compile_id);
$this->populateTimestamp($cached); $this->populateTimestamp($cached);
} }
@ -83,10 +82,11 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
* *
* @param Smarty_Internal_Template $_template template object * @param Smarty_Internal_Template $_template template object
* @param Smarty_Template_Cached $cached cached object * @param Smarty_Template_Cached $cached cached object
* @param bool $update flag if called because cache update
* *
* @return boolean true or false if the cached content does not exist * @return boolean true or false if the cached content does not exist
*/ */
public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null) public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null, $update = false)
{ {
if (!$cached) { if (!$cached) {
$cached = $_template->cached; $cached = $_template->cached;
@ -123,7 +123,29 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
{ {
$this->addMetaTimestamp($content); $this->addMetaTimestamp($content);
return $this->write(array($_template->cached->filepath => $content), $_template->properties['cache_lifetime']); return $this->write(array($_template->cached->filepath => $content), $_template->cache_lifetime);
}
/**
* Read cached template from cache
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function readCachedContent(Smarty_Internal_Template $_template)
{
$content = $_template->cached->content ? $_template->cached->content : null;
$timestamp = null;
if ($content === null) {
if (!$this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $content, $timestamp, $_template->source->uid)) {
return false;
}
}
if (isset($content)) {
return $content;
}
return false;
} }
/** /**
@ -142,7 +164,14 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
if (!$this->purge()) { if (!$this->purge()) {
$this->invalidate(null); $this->invalidate(null);
} }
// remove from template cache
if (isset($smarty->_cache['template_objects'])) {
foreach ($smarty->_cache['template_objects'] as $key => $tpl) {
if (isset($tpl->cached)) {
unset($smarty->_cache['template_objects'][$key]);
}
}
}
return - 1; return - 1;
} }
@ -163,11 +192,21 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
*/ */
public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
{ {
$uid = $this->getTemplateUid($smarty, $resource_name, $cache_id, $compile_id); $uid = $this->getTemplateUid($smarty, $resource_name);
$cid = $uid . '#' . $this->sanitize($resource_name) . '#' . $this->sanitize($cache_id) . '#' . $this->sanitize($compile_id); $cid = $uid . '#' . $this->sanitize($resource_name) . '#' . $this->sanitize($cache_id) . '#' .
$this->sanitize($compile_id);
$this->delete(array($cid)); $this->delete(array($cid));
$this->invalidate($cid, $resource_name, $cache_id, $compile_id, $uid); $this->invalidate($cid, $resource_name, $cache_id, $compile_id, $uid);
// remove from template cache
if (isset($resource_name) && isset($smarty->_cache['template_objects'])) {
if (isset($smarty->_cache['template_objects'])) {
foreach ($smarty->_cache['template_objects'] as $key => $tpl) {
if ($tpl->source->uid == $uid && isset($tpl->cached)) {
unset($smarty->_cache['template_objects'][$key]);
}
}
}
}
return - 1; return - 1;
} }
@ -176,33 +215,20 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
* *
* @param Smarty $smarty Smarty object * @param Smarty $smarty Smarty object
* @param string $resource_name template name * @param string $resource_name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* *
* @return string filepath of cache file * @return string filepath of cache file
* @throws \SmartyException
*
*/ */
protected function getTemplateUid(Smarty $smarty, $resource_name, $cache_id, $compile_id) protected function getTemplateUid(Smarty $smarty, $resource_name)
{ {
$uid = '';
if (isset($resource_name)) { if (isset($resource_name)) {
$tpl = new $smarty->template_class($resource_name, $smarty); $source = Smarty_Template_Source::load(null, $smarty, $resource_name);
if ($tpl->source->exists) { if ($source->exists) {
$uid = $tpl->source->uid; return $source->uid;
}
// remove from template cache
if ($smarty->allow_ambiguous_resources) {
$_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id;
} else {
$_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id;
} }
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
} }
unset($smarty->template_objects[$_templateId]); return '';
}
return $uid;
} }
/** /**
@ -214,12 +240,10 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
*/ */
protected function sanitize($string) protected function sanitize($string)
{ {
// some poeple smoke bad weed
$string = trim($string, '|'); $string = trim($string, '|');
if (!$string) { if (!$string) {
return null; return null;
} }
return preg_replace('#[^\w\|]+#S', '_', $string); return preg_replace('#[^\w\|]+#S', '_', $string);
} }
@ -275,11 +299,8 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
*/ */
protected function getMetaTimestamp(&$content) protected function getMetaTimestamp(&$content)
{ {
$s = unpack("N", substr($content, 0, 4)); extract(unpack('N1s/N1m/a*content', $content));
$m = unpack("N", substr($content, 4, 4)); return $s + ($m / 100000000);
$content = substr($content, 8);
return $s[1] + ($m[1] / 100000000);
} }
/** /**
@ -380,7 +401,6 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
$t[] = 'IVK#COMPILE' . $_compile; $t[] = 'IVK#COMPILE' . $_compile;
} }
$_name .= '#'; $_name .= '#';
// some poeple smoke bad weed
$cid = trim($cache_id, '|'); $cid = trim($cache_id, '|');
if (!$cid) { if (!$cid) {
return $t; return $t;

@ -1,94 +0,0 @@
<?php
/**
* Smarty Internal Plugin
*
* @package Smarty
* @subpackage TemplateResources
*/
/**
* Smarty Resource Data Object
* Meta Data Container for Config Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
* @property string $content
* @property int $timestamp
* @property bool $exists
*/
class Smarty_Config_Source extends Smarty_Template_Source
{
/**
* create Config Object container
*
* @param Smarty_Resource $handler Resource Handler this source object communicates with
* @param Smarty $smarty Smarty instance this source object belongs to
* @param string $resource full config_resource
* @param string $type type of resource
* @param string $name resource name
* @param string $unique_resource unqiue resource name
*/
public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name, $unique_resource)
{
$this->handler = $handler; // Note: prone to circular references
// Note: these may be ->config_compiler_class etc in the future
//$this->config_compiler_class = $handler->config_compiler_class;
//$this->config_lexer_class = $handler->config_lexer_class;
//$this->config_parser_class = $handler->config_parser_class;
$this->smarty = $smarty;
$this->resource = $resource;
$this->type = $type;
$this->name = $name;
$this->unique_resource = $unique_resource;
}
/**
* <<magic>> Generic setter.
*
* @param string $property_name valid: content, timestamp, exists
* @param mixed $value newly assigned value (not check for correct type)
*
* @throws SmartyException when the given property name is not valid
*/
public function __set($property_name, $value)
{
switch ($property_name) {
case 'content':
case 'timestamp':
case 'exists':
$this->$property_name = $value;
break;
default:
throw new SmartyException("invalid config property '$property_name'.");
}
}
/**
* <<magic>> Generic getter.
*
* @param string $property_name valid: content, timestamp, exists
*
* @return mixed|void
* @throws SmartyException when the given property name is not valid
*/
public function __get($property_name)
{
switch ($property_name) {
case 'timestamp':
case 'exists':
$this->handler->populateTimestamp($this);
return $this->$property_name;
case 'content':
return $this->content = $this->handler->getContent($this);
default:
throw new SmartyException("config property '$property_name' does not exist.");
}
}
}

@ -0,0 +1,68 @@
<?php
/**
* Smarty Plugin Data
* This file contains the data object
*
* @package Smarty
* @subpackage Template
* @author Uwe Tews
*/
/**
* class for the Smarty data object
* The Smarty data object will hold Smarty variables in the current scope
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Data extends Smarty_Internal_Data
{
/**
* Counter
*
* @var int
*/
static $count = 0;
/**
* Data block name
*
* @var string
*/
public $dataObjectName = '';
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* create Smarty data object
*
* @param Smarty|array $_parent parent template
* @param Smarty|Smarty_Internal_Template $smarty global smarty instance
* @param string $name optional data block name
*
* @throws SmartyException
*/
public function __construct($_parent = null, $smarty = null, $name = null)
{
parent::__construct();
self::$count ++;
$this->dataObjectName = 'Data_object ' . (isset($name) ? "'{$name}'" : self::$count);
$this->smarty = $smarty;
if (is_object($_parent)) {
// when object set up back pointer
$this->parent = $_parent;
} elseif (is_array($_parent)) {
// set up variable values
foreach ($_parent as $_key => $_val) {
$this->tpl_vars[$_key] = new Smarty_Variable($_val);
}
} elseif ($_parent != null) {
throw new SmartyException("Wrong type for template variables");
}
}
}

@ -29,14 +29,12 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
{ {
$_source_file_path = str_replace(':', '.', $_template->source->filepath); $_source_file_path = str_replace(':', '.', $_template->source->filepath);
$_cache_id = isset($_template->cache_id) ? preg_replace('![^\w\|]+!', '_', $_template->cache_id) : null; $_cache_id = isset($_template->cache_id) ? preg_replace('![^\w\|]+!', '_', $_template->cache_id) : null;
$_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w]+!', '_', $_template->compile_id) : null;
$_filepath = $_template->source->uid; $_filepath = $_template->source->uid;
// if use_sub_dirs, break file into directories // if use_sub_dirs, break file into directories
if ($_template->smarty->use_sub_dirs) { if ($_template->smarty->use_sub_dirs) {
$_filepath = substr($_filepath, 0, 2) . DS $_filepath = substr($_filepath, 0, 2) . DS . substr($_filepath, 2, 2) . DS . substr($_filepath, 4, 2) . DS .
. substr($_filepath, 2, 2) . DS $_filepath;
. substr($_filepath, 4, 2) . DS
. $_filepath;
} }
$_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^';
if (isset($_cache_id)) { if (isset($_cache_id)) {
@ -60,9 +58,12 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
} }
$cached->lock_id = $_lock_dir . sha1($_cache_id . $_compile_id . $_template->source->uid) . '.lock'; $cached->lock_id = $_lock_dir . sha1($_cache_id . $_compile_id . $_template->source->uid) . '.lock';
} }
$cached->filepath = $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($_source_file_path) . '.php'; $cached->filepath = $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($_source_file_path) .
$cached->timestamp = @filemtime($cached->filepath); '.php';
$cached->exists = !!$cached->timestamp; $cached->timestamp = $cached->exists = is_file($cached->filepath);
if ($cached->exists) {
$cached->timestamp = filemtime($cached->filepath);
}
} }
/** /**
@ -74,8 +75,10 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/ */
public function populateTimestamp(Smarty_Template_Cached $cached) public function populateTimestamp(Smarty_Template_Cached $cached)
{ {
$cached->timestamp = @filemtime($cached->filepath); $cached->timestamp = $cached->exists = is_file($cached->filepath);
$cached->exists = !!$cached->timestamp; if ($cached->exists) {
$cached->timestamp = filemtime($cached->filepath);
}
} }
/** /**
@ -83,18 +86,23 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
* *
* @param Smarty_Internal_Template $_template template object * @param Smarty_Internal_Template $_template template object
* @param Smarty_Template_Cached $cached cached object * @param Smarty_Template_Cached $cached cached object
* @param bool $update flag if called because cache update
* *
* @return boolean true or false if the cached content does not exist * @return boolean true or false if the cached content does not exist
*/ */
public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null) public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null, $update = false)
{ {
/** @var Smarty_Internal_Template $_smarty_tpl /** @var Smarty_Internal_Template $_smarty_tpl
* used in included file * used in included file
*/ */
$_smarty_tpl = $_template; $_smarty_tpl = $_template;
$_template->cached->valid = false;
if ($update && defined('HHVM_VERSION')) {
return $_template->smarty->ext->_hhvm->includeHhvm($_template, $_template->cached->filepath);
} else {
return @include $_template->cached->filepath; return @include $_template->cached->filepath;
} }
}
/** /**
* Write the rendered template output to cache * Write the rendered template output to cache
@ -106,14 +114,32 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/ */
public function writeCachedContent(Smarty_Internal_Template $_template, $content) public function writeCachedContent(Smarty_Internal_Template $_template, $content)
{ {
if (Smarty_Internal_Write_File::writeFile($_template->cached->filepath, $content, $_template->smarty) === true) { if ($_template->smarty->ext->_writeFile->writeFile($_template->cached->filepath, $content, $_template->smarty) === true) {
$_template->cached->timestamp = @filemtime($_template->cached->filepath); if (function_exists('opcache_invalidate')) {
$_template->cached->exists = !!$_template->cached->timestamp; opcache_invalidate($_template->cached->filepath);
if ($_template->cached->exists) { }
$cached = $_template->cached;
$cached->timestamp = $cached->exists = is_file($cached->filepath);
if ($cached->exists) {
$cached->timestamp = filemtime($cached->filepath);
return true; return true;
} }
} }
return false;
}
/**
* Read cached template from cache
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function readCachedContent(Smarty_Internal_Template $_template)
{
if (is_file($_template->cached->filepath)) {
return file_get_contents($_template->cached->filepath);
}
return false; return false;
} }
@ -127,7 +153,7 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/ */
public function clearAll(Smarty $smarty, $exp_time = null) public function clearAll(Smarty $smarty, $exp_time = null)
{ {
return $this->clear($smarty, null, null, null, $exp_time); return Smarty_Internal_Extension_Clear::clear($smarty, null, null, null, $exp_time);
} }
/** /**
@ -143,108 +169,7 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/ */
public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
{ {
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null; return Smarty_Internal_Extension_Clear::clear($smarty, $resource_name, $cache_id, $compile_id, $exp_time);
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
$_dir_sep = $smarty->use_sub_dirs ? '/' : '^';
$_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0;
if (($_dir = realpath($smarty->getCacheDir())) === false) {
return 0;
}
$_dir .= '/';
$_dir_length = strlen($_dir);
if (isset($_cache_id)) {
$_cache_id_parts = explode('|', $_cache_id);
$_cache_id_parts_count = count($_cache_id_parts);
if ($smarty->use_sub_dirs) {
foreach ($_cache_id_parts as $id_part) {
$_dir .= $id_part . DS;
}
}
}
if (isset($resource_name)) {
$_save_stat = $smarty->caching;
$smarty->caching = true;
$tpl = new $smarty->template_class($resource_name, $smarty);
$smarty->caching = $_save_stat;
// remove from template cache
$tpl->source; // have the template registered before unset()
if ($smarty->allow_ambiguous_resources) {
$_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id;
} else {
$_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id;
}
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
}
unset($smarty->template_objects[$_templateId]);
if ($tpl->source->exists) {
$_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath));
} else {
return 0;
}
}
$_count = 0;
$_time = time();
if (file_exists($_dir)) {
$_cacheDirs = new RecursiveDirectoryIterator($_dir);
$_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($_cache as $_file) {
if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) {
continue;
}
// directory ?
if ($_file->isDir()) {
if (!$_cache->isDot()) {
// delete folder if empty
@rmdir($_file->getPathname());
}
} else {
$_parts = explode($_dir_sep, str_replace('\\', '/', substr((string) $_file, $_dir_length)));
$_parts_count = count($_parts);
// check name
if (isset($resource_name)) {
if ($_parts[$_parts_count - 1] != $_resourcename_parts) {
continue;
}
}
// check compile id
if (isset($_compile_id) && (!isset($_parts[$_parts_count - 2 - $_compile_id_offset]) || $_parts[$_parts_count - 2 - $_compile_id_offset] != $_compile_id)) {
continue;
}
// check cache id
if (isset($_cache_id)) {
// count of cache id parts
$_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset : $_parts_count - 1 - $_compile_id_offset;
if ($_parts_count < $_cache_id_parts_count) {
continue;
}
for ($i = 0; $i < $_cache_id_parts_count; $i ++) {
if ($_parts[$i] != $_cache_id_parts[$i]) {
continue 2;
}
}
}
// expired ?
if (isset($exp_time)) {
if ($exp_time < 0) {
preg_match('#\'cache_lifetime\' =>\s*(\d*)#', file_get_contents($_file), $match);
if ($_time < (@filemtime($_file) + $match[1])) {
continue;
}
} else {
if ($_time - @filemtime($_file) < $exp_time) {
continue;
}
}
}
$_count += @unlink((string) $_file) ? 1 : 0;
}
}
}
return $_count;
} }
/** /**
@ -262,9 +187,12 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
} else { } else {
clearstatcache(); clearstatcache();
} }
if (is_file($cached->lock_id)) {
$t = @filemtime($cached->lock_id); $t = @filemtime($cached->lock_id);
return $t && (time() - $t < $smarty->locking_timeout); return $t && (time() - $t < $smarty->locking_timeout);
} else {
return false;
}
} }
/** /**

@ -20,12 +20,12 @@ class Smarty_Internal_Compile_Append extends Smarty_Internal_Compile_Assign
* Compiles code for the {append} tag * Compiles code for the {append} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// the following must be assigned at runtime because it will be overwritten in parent class // the following must be assigned at runtime because it will be overwritten in parent class
$this->required_attributes = array('var', 'value'); $this->required_attributes = array('var', 'value');

@ -16,23 +16,31 @@
*/ */
class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
{ {
/**
* Valid scope names
*
* @var array
*/
public $valid_scopes = array('local' => true, 'parent' => true, 'root' => true, 'global' => true,
'smarty' => true, 'tpl_root' => true);
/** /**
* Compiles code for the {assign} tag * Compiles code for the {assign} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// the following must be assigned at runtime because it will be overwritten in Smarty_Internal_Compile_Append // the following must be assigned at runtime because it will be overwritten in Smarty_Internal_Compile_Append
$this->required_attributes = array('var', 'value'); $this->required_attributes = array('var', 'value');
$this->shorttag_order = array('var', 'value'); $this->shorttag_order = array('var', 'value');
$this->optional_attributes = array('scope'); $this->optional_attributes = array('scope', 'bubble_up');
$_nocache = 'null'; $_nocache = 'null';
$_scope = Smarty::SCOPE_LOCAL;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
// nocache ? // nocache ?
@ -42,43 +50,47 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
if (isset($compiler->template->tpl_vars[trim($_attr['var'], "'")])) { if (isset($compiler->template->tpl_vars[trim($_attr['var'], "'")])) {
$compiler->template->tpl_vars[trim($_attr['var'], "'")]->nocache = true; $compiler->template->tpl_vars[trim($_attr['var'], "'")]->nocache = true;
} else { } else {
$compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_variable(null, true); $compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_Variable(null, true);
} }
} }
// scope setup // scope setup
$_scope = Smarty::SCOPE_LOCAL;
if (isset($_attr['scope'])) { if (isset($_attr['scope'])) {
$_attr['scope'] = trim($_attr['scope'], "'\""); $_attr['scope'] = trim($_attr['scope'], "'\"");
if (!isset($this->valid_scopes[$_attr['scope']])) {
$compiler->trigger_template_error("illegal value '{$_attr['scope']}' for \"scope\" attribute", null, true);
}
if ($_attr['scope'] != 'local') {
if ($_attr['scope'] == 'parent') { if ($_attr['scope'] == 'parent') {
$_scope = Smarty::SCOPE_PARENT; $_scope = Smarty::SCOPE_PARENT;
} elseif ($_attr['scope'] == 'root') { } elseif ($_attr['scope'] == 'root') {
$_scope = Smarty::SCOPE_ROOT; $_scope = Smarty::SCOPE_ROOT;
} elseif ($_attr['scope'] == 'global') { } elseif ($_attr['scope'] == 'global') {
$_scope = Smarty::SCOPE_GLOBAL; $_scope = Smarty::SCOPE_GLOBAL;
} else { } elseif ($_attr['scope'] == 'smarty') {
$compiler->trigger_template_error('illegal value for "scope" attribute', $compiler->lex->taglineno); $_scope = Smarty::SCOPE_SMARTY;
} elseif ($_attr['scope'] == 'tpl_root') {
$_scope = Smarty::SCOPE_TPL_ROOT;
}
$_scope += (isset($_attr['bubble_up']) && $_attr['bubble_up'] == 'false') ? 0 : Smarty::SCOPE_BUBBLE_UP;
} }
} }
// compiled output // compiled output
if (isset($parameter['smarty_internal_index'])) { if (isset($parameter['smarty_internal_index'])) {
$output = "<?php \$_smarty_tpl->createLocalArrayVariable($_attr[var], $_nocache, $_scope);\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value$parameter[smarty_internal_index] = $_attr[value];"; $output =
"<?php \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, $_attr[var], $_nocache);\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value$parameter[smarty_internal_index] = $_attr[value];";
} else { } else {
// implement Smarty2's behaviour of variables assigned by reference // implement Smarty2's behaviour of variables assigned by reference
if ($compiler->template->smarty instanceof SmartyBC) { if ($compiler->template->smarty instanceof SmartyBC) {
$output = "<?php if (isset(\$_smarty_tpl->tpl_vars[$_attr[var]])) {\$_smarty_tpl->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];"; $output =
$output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache; \$_smarty_tpl->tpl_vars[$_attr[var]]->scope = $_scope;"; "<?php if (isset(\$_smarty_tpl->tpl_vars[$_attr[var]])) {\$_smarty_tpl->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);"; $output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache;";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache);";
} else { } else {
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);"; $output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache);";
}
}
if ($_scope == Smarty::SCOPE_PARENT) {
$output .= "\nif (\$_smarty_tpl->parent != null) \$_smarty_tpl->parent->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
} elseif ($_scope == Smarty::SCOPE_ROOT || $_scope == Smarty::SCOPE_GLOBAL) {
$output .= "\n\$_ptr = \$_smarty_tpl->parent; while (\$_ptr != null) {\$_ptr->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]]; \$_ptr = \$_ptr->parent; }";
} }
if ($_scope == Smarty::SCOPE_GLOBAL) {
$output .= "\nSmarty::\$global_tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
} }
$output .= "\n\$_smarty_tpl->ext->_updateScope->updateScope(\$_smarty_tpl, $_attr[var], $_scope);";
$output .= '?>'; $output .= '?>';
return $output; return $output;

@ -1,24 +1,20 @@
<?php <?php
/*
/** * This file is part of Smarty.
* Smarty Internal Plugin Compile Block
* Compiles the {block}{/block} tags
* *
* @package Smarty * (c) 2015 Uwe Tews
* @subpackage Compiler *
* @author Uwe Tews * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/ */
/** /**
* Smarty Internal Plugin Compile Block Class * Smarty Internal Plugin Compile Block Class
* *
* @package Smarty * @author Uwe Tews <uwe.tews@googlemail.com>
* @subpackage Compiler
*/ */
class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inheritance
{ {
const parent = '____SMARTY_BLOCK_PARENT____';
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -41,7 +37,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
* @var array * @var array
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $option_flags = array('hide', 'append', 'prepend', 'nocache'); public $option_flags = array('hide', 'nocache');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@ -49,396 +45,248 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
* @var array * @var array
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('internal_file', 'internal_uid', 'internal_line'); public $optional_attributes = array('assign');
/** /**
* nested child block names * nesting level of block tags
* *
* @var array * @var int
*/ */
public static $nested_block_names = array(); public static $blockTagNestingLevel = 0;
/** /**
* child block source buffer * Saved compiler object
* *
* @var array * @var Smarty_Internal_TemplateCompilerBase
*/ */
public static $block_data = array(); public $compiler = null;
/** /**
* Compiles code for the {block} tag * Compiles code for the {block} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
* *
* @return boolean true * @return bool true
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes if (!isset($compiler->_cache['blockNesting'])) {
$_attr = $this->getAttributes($compiler, $args); $compiler->_cache['blockNesting'] = 0;
$_name = trim($_attr['name'], "\"'");
// existing child must override parent settings
if (isset($compiler->template->block_data[$_name]) && $compiler->template->block_data[$_name]['mode'] == 'replace') {
$_attr['append'] = false;
$_attr['prepend'] = false;
}
// check if we process an inheritance child template
if ($compiler->inheritance_child) {
array_unshift(self::$nested_block_names, $_name);
// build {block} for child block
self::$block_data[$_name]['source'] =
"{$compiler->smarty->left_delimiter}private_child_block name={$_attr['name']} file='{$compiler->template->source->filepath}' type='{$compiler->template->source->type}' resource='{$compiler->template->template_resource}'" .
" uid='{$compiler->template->source->uid}' line={$compiler->lex->line}";
if ($_attr['nocache']) {
self::$block_data[$_name]['source'] .= ' nocache';
} }
self::$block_data[$_name]['source'] .= $compiler->smarty->right_delimiter; if ($compiler->_cache['blockNesting'] == 0) {
// make sure that inheritance gets initialized in template code
$save = array($_attr, $compiler->inheritance); $this->registerInit($compiler);
$this->openTag($compiler, 'block', $save); $this->option_flags = array('hide', 'nocache', 'append', 'prepend');
// set flag for {block} tag } else {
$compiler->inheritance = true; $this->option_flags = array('hide', 'nocache');
$compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
$compiler->has_code = false;
return;
} }
// must merge includes // check and get attributes
if ($_attr['nocache'] == true) { $_attr = $this->getAttributes($compiler, $args);
$compiler->tag_nocache = true; $compiler->_cache['blockNesting'] ++;
$compiler->_cache['blockName'][$compiler->_cache['blockNesting']] = $_attr['name'];
$compiler->_cache['blockParams'][$compiler->_cache['blockNesting']][0] = 'block_' . preg_replace('![^\w]+!', '_', uniqid(rand(), true));
$compiler->_cache['blockParams'][$compiler->_cache['blockNesting']][1] = false;
$this->openTag($compiler, 'block', array($_attr, $compiler->nocache, $compiler->parser->current_buffer,
$compiler->template->compiled->has_nocache_code,
$compiler->template->caching));
// must whole block be nocache ?
if ($compiler->tag_nocache) {
$i = 0;
} }
$save = array($_attr, $compiler->inheritance, $compiler->parser->current_buffer, $compiler->nocache);
$this->openTag($compiler, 'block', $save);
$compiler->inheritance = true;
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
// $compiler->suppressNocacheProcessing = true;
$compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser); if ($_attr['nocache'] === true) {
$compiler->has_code = false; //$compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->taglineno);
}
return true; $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$compiler->template->compiled->has_nocache_code = false;
$compiler->suppressNocacheProcessing = true;
} }
/** /**
* Compile saved child block source * Compile saved child block source
* *
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase compiler object
* @param string $_name optional name of child block * @param string $_name optional name of child block
* *
* @return string compiled code of child block * @return string compiled code of child block
*/ */
static function compileChildBlock($compiler, $_name = null) static function compileChildBlock(Smarty_Internal_TemplateCompilerBase $compiler, $_name = null)
{ {
if ($compiler->inheritance_child) { if (!isset($compiler->_cache['blockNesting'])) {
$name1 = Smarty_Internal_Compile_Block::$nested_block_names[0]; $compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ',
if (isset($compiler->template->block_data[$name1])) { $compiler->parser->lex->taglineno);
// replace inner block name with generic
Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= $compiler->template->block_data[$name1]['source'];
Smarty_Internal_Compile_Block::$block_data[$name1]['child'] = true;
}
$compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
$compiler->has_code = false;
return;
}
// if called by {$smarty.block.child} we must search the name of enclosing {block}
if ($_name == null) {
$stack_count = count($compiler->_tag_stack);
while (--$stack_count >= 0) {
if ($compiler->_tag_stack[$stack_count][0] == 'block') {
$_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
break;
}
}
}
if ($_name == null) {
$compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', $compiler->lex->taglineno);
}
// undefined child?
if (!isset($compiler->template->block_data[$_name]['source'])) {
$compiler->popTrace();
return '';
}
// flag that child is already compile by {$smarty.block.child} inclusion
$compiler->template->block_data[$_name]['compiled'] = true;
$_tpl = new Smarty_Internal_template('string:' . $compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id,
$compiler->template->compile_id, $compiler->template->caching, $compiler->template->cache_lifetime);
if ($compiler->smarty->debugging) {
Smarty_Internal_Debug::ignore($_tpl);
}
$_tpl->tpl_vars = $compiler->template->tpl_vars;
$_tpl->variable_filters = $compiler->template->variable_filters;
$_tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash'];
$_tpl->allow_relative_path = true;
$_tpl->compiler->inheritance = true;
$_tpl->compiler->suppressHeader = true;
$_tpl->compiler->suppressFilter = true;
$_tpl->compiler->suppressTemplatePropertyHeader = true;
$_tpl->compiler->suppressMergedTemplates = true;
$nocache = $compiler->nocache || $compiler->tag_nocache;
if (strpos($compiler->template->block_data[$_name]['source'], self::parent) !== false) {
$_output = str_replace(self::parent, $compiler->parser->current_buffer->to_smarty_php(), $_tpl->compiler->compileTemplate($_tpl, $nocache));
} elseif ($compiler->template->block_data[$_name]['mode'] == 'prepend') {
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache) . $compiler->parser->current_buffer->to_smarty_php();
} elseif ($compiler->template->block_data[$_name]['mode'] == 'append') {
$_output = $compiler->parser->current_buffer->to_smarty_php() . $_tpl->compiler->compileTemplate($_tpl, $nocache);
} elseif (!empty($compiler->template->block_data[$_name])) {
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache);
}
$compiler->template->properties['file_dependency'] = array_merge($compiler->template->properties['file_dependency'], $_tpl->properties['file_dependency']);
$compiler->template->properties['function'] = array_merge($compiler->template->properties['function'], $_tpl->properties['function']);
$compiler->merged_templates = array_merge($compiler->merged_templates, $_tpl->compiler->merged_templates);
$compiler->template->variable_filters = $_tpl->variable_filters;
if ($_tpl->has_nocache_code) {
$compiler->template->has_nocache_code = true;
} }
foreach ($_tpl->required_plugins as $key => $tmp1) {
if ($compiler->nocache && $compiler->template->caching) {
$code = 'nocache';
} else {
$code = $key;
}
foreach ($tmp1 as $name => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->template->required_plugins[$code][$name][$type] = $data;
}
}
}
unset($_tpl);
$compiler->has_code = true; $compiler->has_code = true;
return $_output; $compiler->suppressNocacheProcessing = true;
$compiler->_cache['blockParams'][$compiler->_cache['blockNesting']][1] = true;
$output = "<?php \n\$_smarty_tpl->ext->_inheritance->processBlock(\$_smarty_tpl, 2, {$compiler->_cache['blockName'][$compiler->_cache['blockNesting']]}, null, \$_blockParentStack);\n?>\n";
return $output;
} }
/** /**
* Compile $smarty.block.parent * Compile $smarty.block.parent
* *
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param string $_name optional name of child block * @param string $_name optional name of child block
* *
* @return string compiled code of child block * @return string compiled code of child block
*/ */
static function compileParentBlock($compiler, $_name = null) static function compileParentBlock(Smarty_Internal_TemplateCompilerBase $compiler, $_name = null)
{ {
// if called by {$smarty.block.parent} we must search the name of enclosing {block} if (!isset($compiler->_cache['blockNesting'])) {
if ($_name == null) { $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ',
$stack_count = count($compiler->_tag_stack); $compiler->parser->lex->taglineno);
while (--$stack_count >= 0) {
if ($compiler->_tag_stack[$stack_count][0] == 'block') {
$_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
break;
} }
} $compiler->suppressNocacheProcessing = true;
} $compiler->has_code = true;
if ($_name == null) { $output = "<?php \n\$_smarty_tpl->ext->_inheritance->processBlock(\$_smarty_tpl, 4, {$compiler->_cache['blockName'][$compiler->_cache['blockNesting']]}, null, \$_blockParentStack);\n?>\n";
$compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->lex->taglineno); return $output;
}
if (empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
$compiler->trigger_template_error(' illegal {$smarty.block.parent} in parent template ', $compiler->lex->taglineno);
}
Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= Smarty_Internal_Compile_Block::parent;
$compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
$compiler->has_code = false;
return;
}
/**
* Process block source
*
* @param $compiler
* @param string $source source text
*
*/
static function blockSource($compiler, $source)
{
Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= $source;
} }
} }
/** /**
* Smarty Internal Plugin Compile BlockClose Class * Smarty Internal Plugin Compile BlockClose Class
* *
* @package Smarty
* @subpackage Compiler
*/ */
class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_Inheritance
{ {
/** /**
* Compiles code for the {/block} tag * Compiles code for the {/block} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return bool true
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$compiler->has_code = true; list($_attr, $_nocache, $_buffer, $_has_nocache_code, $_caching) = $this->closeTag($compiler, array('block'));
// check and get attributes // init block parameter
$_attr = $this->getAttributes($compiler, $args); $_block = $compiler->_cache['blockParams'][$compiler->_cache['blockNesting']];
$saved_data = $this->closeTag($compiler, array('block')); unset($compiler->_cache['blockParams'][$compiler->_cache['blockNesting']]);
$_name = trim($saved_data[0]['name'], "\"'"); $_block[2] = $_block[3] = 0;
// reset flag for {block} tag $_name = trim($_attr['name'], "'\"");
$compiler->inheritance = $saved_data[1]; $_assign = isset($_attr['assign']) ? $_attr['assign'] : null;
// check if we process an inheritance child template unset($_attr['assign'], $_attr['name']);
if ($compiler->inheritance_child) { foreach ($_attr as $name => $stat) {
$name1 = Smarty_Internal_Compile_Block::$nested_block_names[0]; if ((is_bool($stat) && $stat !== false) || (!is_bool($stat) && $stat != 'false')) {
Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= "{$compiler->smarty->left_delimiter}/private_child_block{$compiler->smarty->right_delimiter}"; $_block[$name] = is_string($stat) ? trim($stat, "'\"") : $stat;
array_shift(Smarty_Internal_Compile_Block::$nested_block_names); }
if (!empty(Smarty_Internal_Compile_Block::$nested_block_names)) { }
$name2 = Smarty_Internal_Compile_Block::$nested_block_names[0]; $_funcName = $_block[0];
if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) { // get compiled block code
if (isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child']) || !isset($compiler->template->block_data[$name1])) { $_functionCode = $compiler->parser->current_buffer;
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source']; // setup buffer for template function code
} else { $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
if ($compiler->template->block_data[$name1]['mode'] == 'append') {
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'] . $compiler->template->block_data[$name1]['source']; if ($compiler->template->compiled->has_nocache_code) {
} elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') { // $compiler->parent_compiler->template->tpl_function[$_name]['call_name_caching'] = $_funcNameCaching;
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'] . Smarty_Internal_Compile_Block::$block_data[$name1]['source']; $_block[6] = $_funcNameCaching = $_funcName . '_nocache';
} else { $output = "<?php\n";
Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source']; $output .= "/* {block '{$_name}'} {$compiler->template->source->type}:{$compiler->template->source->name} */\n";
} $output .= "function {$_funcNameCaching} (\$_smarty_tpl, \$_blockParentStack) {\n";
} $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n";
} $output .= "\$_smarty_tpl->cached->hashes['{$compiler->template->compiled->nocache_hash}'] = true;\n";
unset(Smarty_Internal_Compile_Block::$block_data[$name1]); if (isset($_assign)) {
$compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK); $output .= "ob_start();\n";
} else { }
if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) { $output .= "?>\n";
if (isset($compiler->template->block_data[$name1]) && !isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child'])) { $compiler->parser->current_buffer->append_subtree($compiler->parser,
if (strpos($compiler->template->block_data[$name1]['source'], Smarty_Internal_Compile_Block::parent) !== false) { new Smarty_Internal_ParseTree_Tag($compiler->parser,
$compiler->template->block_data[$name1]['source'] = $output));
str_replace(Smarty_Internal_Compile_Block::parent, Smarty_Internal_Compile_Block::$block_data[$name1]['source'], $compiler->template->block_data[$name1]['source']); $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
} elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') { $output = "<?php\n";
$compiler->template->block_data[$name1]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source']; if (isset($_assign)) {
} elseif ($compiler->template->block_data[$name1]['mode'] == 'append') { $output .= "\$_smarty_tpl->tpl_vars[{$_assign}] = new Smarty_Variable(ob_get_clean());\n";
$compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'] . $compiler->template->block_data[$name1]['source']; }
} $output .= "/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n";
} else { $output .= "}\n";
$compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source']; $output .= "/* {/block '{$_name}'} */\n\n";
} $output .= "?>\n";
$compiler->template->block_data[$name1]['mode'] = 'replace'; $compiler->parser->current_buffer->append_subtree($compiler->parser,
if ($saved_data[0]['append']) { new Smarty_Internal_ParseTree_Tag($compiler->parser,
$compiler->template->block_data[$name1]['mode'] = 'append'; $output));
} $compiler->blockOrFunctionCode .= $f = $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
if ($saved_data[0]['prepend']) { $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$compiler->template->block_data[$name1]['mode'] = 'prepend'; $this->compiler = $compiler;
} $_functionCode = new Smarty_Internal_ParseTree_Tag($compiler->parser,
} preg_replace_callback("/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/",
unset(Smarty_Internal_Compile_Block::$block_data[$name1]); array($this, 'removeNocache'),
$compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY); $_functionCode->to_smarty_php($compiler->parser)));
} $this->compiler = null;
$compiler->has_code = false; }
return; $output = "<?php\n";
} $output .= "/* {block '{$_name}'} {$compiler->template->source->type}:{$compiler->template->source->name} */\n";
if (isset($compiler->template->block_data[$_name]) && !isset($compiler->template->block_data[$_name]['compiled'])) { $output .= "function {$_funcName}(\$_smarty_tpl, \$_blockParentStack) {\n";
$_output = Smarty_Internal_Compile_Block::compileChildBlock($compiler, $_name); if (isset($_assign)) {
} else { $output .= "ob_start();\n";
if ($saved_data[0]['hide'] && !isset($compiler->template->block_data[$_name]['source'])) { }
$_output = ''; $output .= "?>\n";
} else { $compiler->parser->current_buffer->append_subtree($compiler->parser,
$_output = $compiler->parser->current_buffer->to_smarty_php(); new Smarty_Internal_ParseTree_Tag($compiler->parser,
$output));
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
$output = "<?php\n";
if (isset($_assign)) {
$output .= "\$_smarty_tpl->tpl_vars[{$_assign}] = new Smarty_Variable(ob_get_clean());\n";
}
$output .= "}\n";
$output .= "/* {/block '{$_name}'} */\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser,
new Smarty_Internal_ParseTree_Tag($compiler->parser,
$output));
$compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
// nocache plugins must be copied
if (!empty($compiler->template->compiled->required_plugins['nocache'])) {
foreach ($compiler->template->compiled->required_plugins['nocache'] as $plugin => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->parent_compiler->template->compiled->required_plugins['compiled'][$plugin][$type] =
$data;
} }
} }
unset($compiler->template->block_data[$_name]['compiled']);
// reset flags
$compiler->parser->current_buffer = $saved_data[2];
if ($compiler->nocache) {
$compiler->tag_nocache = true;
} }
$compiler->nocache = $saved_data[3];
// $_output content has already nocache code processed
$compiler->suppressNocacheProcessing = true;
return $_output;
}
}
/** // restore old status
* Smarty Internal Plugin Compile Child Block Class $compiler->template->compiled->has_nocache_code = $_has_nocache_code;
* $compiler->tag_nocache = $compiler->nocache;
* @package Smarty $compiler->nocache = $_nocache;
* @subpackage Compiler $compiler->parser->current_buffer = $_buffer;
*/ $output = "<?php \n";
class Smarty_Internal_Compile_Private_Child_Block extends Smarty_Internal_CompileBase if ($compiler->_cache['blockNesting'] == 1) {
{ $output .= "\$_smarty_tpl->ext->_inheritance->processBlock(\$_smarty_tpl, 0, {$compiler->_cache['blockName'][$compiler->_cache['blockNesting']]}, " .
var_export($_block, true) . ");\n";
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $required_attributes = array('name', 'file', 'uid', 'line', 'type', 'resource');
/**
* Compiles code for the {private_child_block} tag
*
* @param array $args array with attributes from parser
* @param object $compiler compiler object
*
* @return boolean true
*/
public function compile($args, $compiler)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
// update template with original template resource of {block}
if (trim($_attr['type'], "'") == 'file') {
$compiler->template->template_resource = 'file:' . realpath(trim($_attr['file'], "'"));
} else { } else {
$compiler->template->template_resource = trim($_attr['resource'], "'"); $output .= "\$_smarty_tpl->ext->_inheritance->processBlock(\$_smarty_tpl, 0, {$compiler->_cache['blockName'][$compiler->_cache['blockNesting']]}, " .
} var_export($_block, true) . ", \$_blockParentStack);\n";
// source object
unset ($compiler->template->source);
$exists = $compiler->template->source->exists;
// must merge includes
if ($_attr['nocache'] == true) {
$compiler->tag_nocache = true;
} }
$save = array($_attr, $compiler->nocache); $output .= "?>\n";
$compiler->_cache['blockNesting'] --;
// set trace back to child block if ($compiler->_cache['blockNesting'] == 0) {
$compiler->pushTrace(trim($_attr['file'], "\"'"), trim($_attr['uid'], "\"'"), $_attr['line'] - $compiler->lex->line); unset($compiler->_cache['blockNesting']);
$this->openTag($compiler, 'private_child_block', $save);
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$compiler->has_code = false;
return true;
} }
$compiler->has_code = true;
$compiler->suppressNocacheProcessing = true;
return $output;
} }
/** /**
* Smarty Internal Plugin Compile Child Block Close Class * @param $match
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Private_Child_Blockclose extends Smarty_Internal_CompileBase
{
/**
* Compiles code for the {/private_child_block} tag
*
* @param array $args array with attributes from parser
* @param object $compiler compiler object
* *
* @return boolean true * @return mixed
*/ */
public function compile($args, $compiler) function removeNocache($match)
{ {
// check and get attributes $code =
$_attr = $this->getAttributes($compiler, $args); preg_replace("/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/",
'', $match[0]);
$saved_data = $this->closeTag($compiler, array('private_child_block')); $code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code);
return $code;
// end of child block
$compiler->popTrace();
$compiler->nocache = $saved_data[1];
$compiler->has_code = false;
return true;
} }
} }

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('levels'); public $optional_attributes = array('levels');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -35,24 +36,25 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
* Compiles code for the {break} tag * Compiles code for the {break} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true); static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true);
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', null, true);
} }
if (isset($_attr['levels'])) { if (isset($_attr['levels'])) {
if (!is_numeric($_attr['levels'])) { if (!is_numeric($_attr['levels'])) {
$compiler->trigger_template_error('level attribute must be a numeric constant', $compiler->lex->taglineno); $compiler->trigger_template_error('level attribute must be a numeric constant', null, true);
} }
$_levels = $_attr['levels']; $_levels = $_attr['levels'];
} else { } else {
@ -67,7 +69,7 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
$stack_count --; $stack_count --;
} }
if ($level_count != 0) { if ($level_count != 0) {
$compiler->trigger_template_error("cannot break {$_levels} level(s)", $compiler->lex->taglineno); $compiler->trigger_template_error("cannot break {$_levels} level(s)", null, true);
} }
return "<?php break {$_levels};?>"; return "<?php break {$_levels};?>";

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('name'); public $required_attributes = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -30,6 +31,7 @@ class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('name'); public $shorttag_order = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -55,13 +57,11 @@ class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
// output will be stored in a smarty variable instead of being displayed // output will be stored in a smarty variable instead of being displayed
$_assign = $_attr['assign']; $_assign = $_attr['assign'];
} }
//$_name = trim($_attr['name'], "'\"");
$_name = $_attr['name']; $_name = $_attr['name'];
if ($compiler->compiles_template_function) {
$compiler->called_functions[] = trim($_name, "'\"");
}
unset($_attr['name'], $_attr['assign'], $_attr['nocache']); unset($_attr['name'], $_attr['assign'], $_attr['nocache']);
// set flag (compiled code of {function} must be included in cache file // set flag (compiled code of {function} must be included in cache file
if ($compiler->nocache || $compiler->tag_nocache) { if (!$compiler->template->caching || $compiler->nocache || $compiler->tag_nocache) {
$_nocache = 'true'; $_nocache = 'true';
} else { } else {
$_nocache = 'false'; $_nocache = 'false';
@ -74,54 +74,16 @@ class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
$_paramsArray[] = "'$_key'=>$_value"; $_paramsArray[] = "'$_key'=>$_value";
} }
} }
if (isset($compiler->template->properties['function'][$_name]['parameter'])) {
foreach ($compiler->template->properties['function'][$_name]['parameter'] as $_key => $_value) {
if (!isset($_attr[$_key])) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
}
}
}
} elseif (isset($compiler->smarty->template_functions[$_name]['parameter'])) {
foreach ($compiler->smarty->template_functions[$_name]['parameter'] as $_key => $_value) {
if (!isset($_attr[$_key])) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
}
}
}
}
//variable name?
if (!(strpos($_name, '$') === false)) {
$call_cache = $_name;
$call_function = '$tmp = "smarty_template_function_".' . $_name . '; $tmp';
} else {
$_name = trim($_name, "'\"");
$call_cache = "'{$_name}'";
$call_function = 'smarty_template_function_' . $_name;
}
$_params = 'array(' . implode(",", $_paramsArray) . ')'; $_params = 'array(' . implode(",", $_paramsArray) . ')';
$_hash = str_replace('-', '_', $compiler->template->properties['nocache_hash']); //$compiler->suppressNocacheProcessing = true;
// was there an assign attribute // was there an assign attribute
if (isset($_assign)) { if (isset($_assign)) {
if ($compiler->template->caching) { $_output =
$_output = "<?php ob_start(); Smarty_Internal_Function_Call_Handler::call ({$call_cache},\$_smarty_tpl,{$_params},'{$_hash}',{$_nocache}); \$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n"; "<?php ob_start();\n\$_smarty_tpl->smarty->ext->_tplFunction->callTemplateFunction(\$_smarty_tpl, {$_name}, {$_params}, {$_nocache});\n\$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n";
} else {
$_output = "<?php ob_start(); {$call_function}(\$_smarty_tpl,{$_params}); \$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n";
}
} else { } else {
if ($compiler->template->caching) { $_output =
$_output = "<?php Smarty_Internal_Function_Call_Handler::call ({$call_cache},\$_smarty_tpl,{$_params},'{$_hash}',{$_nocache});?>\n"; "<?php \$_smarty_tpl->smarty->ext->_tplFunction->callTemplateFunction(\$_smarty_tpl, {$_name}, {$_params}, {$_nocache});?>\n";
} else {
$_output = "<?php {$call_function}(\$_smarty_tpl,{$_params});?>\n";
}
} }
return $_output; return $_output;
} }
} }

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Capture extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('name'); public $shorttag_order = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -35,11 +36,11 @@ class Smarty_Internal_Compile_Capture extends Smarty_Internal_CompileBase
* Compiles code for the {capture} tag * Compiles code for the {capture} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@ -51,10 +52,30 @@ class Smarty_Internal_Compile_Capture extends Smarty_Internal_CompileBase
$compiler->_capture_stack[0][] = array($buffer, $assign, $append, $compiler->nocache); $compiler->_capture_stack[0][] = array($buffer, $assign, $append, $compiler->nocache);
// maybe nocache because of nocache variables // maybe nocache because of nocache variables
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$_output = "<?php \$_smarty_tpl->_capture_stack[0][] = array($buffer, $assign, $append); ob_start(); ?>"; $_output = "<?php \$_smarty_tpl->_cache['capture_stack'][] = array($buffer, $assign, $append); ob_start(); ?>";
return $_output; return $_output;
} }
/**
* Compiles code for the {$smarty.capture.xxx}
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string compiled code
* @throws \SmartyCompilerException
*/
public static function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
$tag = strtolower(trim($parameter[ 0 ], '"\''));
$name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : false;
if (!$name) {
$compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true);
}
return "(isset(\$_smarty_tpl->_cache['__smarty_capture']['{$name}']) ? \$_smarty_tpl->_cache['__smarty_capture']['{$name}'] : null)";
}
} }
/** /**
@ -69,11 +90,11 @@ class Smarty_Internal_Compile_CaptureClose extends Smarty_Internal_CompileBase
* Compiles code for the {/capture} tag * Compiles code for the {/capture} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@ -84,11 +105,11 @@ class Smarty_Internal_Compile_CaptureClose extends Smarty_Internal_CompileBase
list($buffer, $assign, $append, $compiler->nocache) = array_pop($compiler->_capture_stack[0]); list($buffer, $assign, $append, $compiler->nocache) = array_pop($compiler->_capture_stack[0]);
$_output = "<?php list(\$_capture_buffer, \$_capture_assign, \$_capture_append) = array_pop(\$_smarty_tpl->_capture_stack[0]);\n"; $_output = "<?php list(\$_capture_buffer, \$_capture_assign, \$_capture_append) = array_pop(\$_smarty_tpl->_cache['capture_stack']);\n";
$_output .= "if (!empty(\$_capture_buffer)) {\n"; $_output .= "if (!empty(\$_capture_buffer)) {\n";
$_output .= " if (isset(\$_capture_assign)) \$_smarty_tpl->assign(\$_capture_assign, ob_get_contents());\n"; $_output .= " if (isset(\$_capture_assign)) \$_smarty_tpl->assign(\$_capture_assign, ob_get_contents());\n";
$_output .= " if (isset( \$_capture_append)) \$_smarty_tpl->append( \$_capture_append, ob_get_contents());\n"; $_output .= " if (isset( \$_capture_append)) \$_smarty_tpl->append( \$_capture_append, ob_get_contents());\n";
$_output .= " Smarty::\$_smarty_vars['capture'][\$_capture_buffer]=ob_get_clean();\n"; $_output .= "\$_smarty_tpl->_cache['__smarty_capture'][\$_capture_buffer]=ob_get_clean();\n";
$_output .= "} else \$_smarty_tpl->capture_error();?>"; $_output .= "} else \$_smarty_tpl->capture_error();?>";
return $_output; return $_output;

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('file'); public $required_attributes = array('file');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -30,30 +31,39 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('file', 'section'); public $shorttag_order = array('file', 'section');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('section', 'scope'); public $optional_attributes = array('section', 'scope', 'bubble_up');
/**
* Valid scope names
*
* @var array
*/
public $valid_scopes = array('local' => true, 'parent' => true, 'root' => true, 'global' => true,
'smarty' => true, 'tpl_root' => true);
/** /**
* Compiles code for the {config_load} tag * Compiles code for the {config_load} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
static $_is_legal_scope = array('local' => true, 'parent' => true, 'root' => true, 'global' => true);
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', null, true);
} }
// save possible attributes // save possible attributes
@ -63,19 +73,31 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase
} else { } else {
$section = 'null'; $section = 'null';
} }
$scope = 'local'; $_scope = Smarty::SCOPE_LOCAL;
// scope setup
if (isset($_attr['scope'])) { if (isset($_attr['scope'])) {
$_attr['scope'] = trim($_attr['scope'], "'\""); $_attr['scope'] = trim($_attr['scope'], "'\"");
if (isset($_is_legal_scope[$_attr['scope']])) { if (!isset($this->valid_scopes[$_attr['scope']])) {
$scope = $_attr['scope']; $compiler->trigger_template_error("illegal value '{$_attr['scope']}' for \"scope\" attribute", null, true);
} else { }
$compiler->trigger_template_error('illegal value for "scope" attribute', $compiler->lex->taglineno); if ($_attr['scope'] != 'local') {
if ($_attr['scope'] == 'parent') {
$_scope = Smarty::SCOPE_PARENT;
} elseif ($_attr['scope'] == 'root') {
$_scope = Smarty::SCOPE_ROOT;
} elseif ($_attr['scope'] == 'global') {
$_scope = Smarty::SCOPE_GLOBAL;
} elseif ($_attr['scope'] == 'smarty') {
$_scope = Smarty::SCOPE_SMARTY;
} elseif ($_attr['scope'] == 'tpl_root') {
$_scope = Smarty::SCOPE_TPL_ROOT;
} }
$_scope += (isset($_attr['bubble_up']) && $_attr['bubble_up'] == 'false') ? 0 : Smarty::SCOPE_BUBBLE_UP;
} }
}
// create config object // create config object
$_output = "<?php \$_config = new Smarty_Internal_Config($conf_file, \$_smarty_tpl->smarty, \$_smarty_tpl);"; $_output =
$_output .= "\$_config->loadConfigVars($section, '$scope'); ?>"; "<?php\n\$_smarty_tpl->smarty->ext->configLoad->_loadConfigFile(\$_smarty_tpl, {$conf_file}, {$section}, {$_scope});\n?>\n";
return $_output; return $_output;
} }

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Continue extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('levels'); public $optional_attributes = array('levels');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -35,24 +36,25 @@ class Smarty_Internal_Compile_Continue extends Smarty_Internal_CompileBase
* Compiles code for the {continue} tag * Compiles code for the {continue} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true); static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true);
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', null, true);
} }
if (isset($_attr['levels'])) { if (isset($_attr['levels'])) {
if (!is_numeric($_attr['levels'])) { if (!is_numeric($_attr['levels'])) {
$compiler->trigger_template_error('level attribute must be a numeric constant', $compiler->lex->taglineno); $compiler->trigger_template_error('level attribute must be a numeric constant', null, true);
} }
$_levels = $_attr['levels']; $_levels = $_attr['levels'];
} else { } else {
@ -67,7 +69,7 @@ class Smarty_Internal_Compile_Continue extends Smarty_Internal_CompileBase
$stack_count --; $stack_count --;
} }
if ($level_count != 0) { if ($level_count != 0) {
$compiler->trigger_template_error("cannot continue {$_levels} level(s)", $compiler->lex->taglineno); $compiler->trigger_template_error("cannot continue {$_levels} level(s)", null, true);
} }
return "<?php continue {$_levels};?>"; return "<?php continue {$_levels};?>";

@ -34,8 +34,8 @@ class Smarty_Internal_Compile_Debug extends Smarty_Internal_CompileBase
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
// display debug template // display debug template
$_output = "<?php \$_smarty_tpl->smarty->loadPlugin('Smarty_Internal_Debug'); Smarty_Internal_Debug::display_debug(\$_smarty_tpl); ?>"; $_output = "<?php \$_smarty_debug = new Smarty_Internal_Debug;\n \$_smarty_debug->display_debug(\$_smarty_tpl);\n";
$_output .= "unset(\$_smarty_debug);\n?>";
return $_output; return $_output;
} }
} }

@ -15,7 +15,7 @@
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inheritance
{ {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@ -24,6 +24,15 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('file'); public $required_attributes = array('file');
/**
* Array of names of optional attribute required by tag
* use array('_any') if there is no restriction of attributes names
*
* @var array
*/
public $optional_attributes = array('extends_resource');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -33,53 +42,93 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase
public $shorttag_order = array('file'); public $shorttag_order = array('file');
/** /**
* Compiles code for the {extends} tag * Compiles code for the {extends} tag extends: resource
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
* @throws \SmartyException
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->line - 1);
} }
if (strpos($_attr['file'], '$_tmp') !== false) { if (strpos($_attr['file'], '$_tmp') !== false) {
$compiler->trigger_template_error('illegal value for file attribute', $compiler->lex->taglineno); $compiler->trigger_template_error('illegal value for file attribute', $compiler->parser->lex->line - 1);
}
$name = $_attr['file'];
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
eval("\$tpl_name = $name;");
// create template object
$_template = new $compiler->smarty->template_class($tpl_name, $compiler->smarty, $compiler->template);
// check for recursion
$uid = $_template->source->uid;
if (isset($compiler->extends_uid[$uid])) {
$compiler->trigger_template_error("illegal recursive call of \"$include_file\"", $compiler->lex->line - 1);
} }
$compiler->extends_uid[$uid] = true; // add code to initialize inheritance
if (empty($_template->source->components)) { $this->registerInit($compiler, true);
array_unshift($compiler->sources, $_template->source); $file = trim($_attr['file'], '\'"');
if (strlen($file) > 8 && substr($file, 0, 8) == 'extends:') {
// generate code for each template
$files = array_reverse(explode('|', substr($file, 8)));
$i = 0;
foreach ($files as $file) {
if ($file[0] == '"') {
$file = trim($file, '".');
} else { } else {
foreach ($_template->source->components as $source) { $file = "'{$file}'";
array_unshift($compiler->sources, $source); }
$uid = $source->uid; $i ++;
if (isset($compiler->extends_uid[$uid])) { if ($i == count($files) && isset($_attr['extends_resource'])) {
$compiler->trigger_template_error("illegal recursive call of \"{$source->filepath}\"", $compiler->lex->line - 1); $this->compileEndChild($compiler);
} }
$compiler->extends_uid[$uid] = true; $this->compileInclude($compiler, $file);
} }
if (!isset($_attr['extends_resource'])) {
$this->compileEndChild($compiler);
}
} else {
$this->compileEndChild($compiler);
$this->compileInclude($compiler, $_attr['file']);
} }
unset ($_template); $compiler->has_code = false;
$compiler->inheritance_child = true;
$compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
return ''; return '';
} }
/**
* Add code for inheritance endChild() method to end of template
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
*/
private function compileEndChild(Smarty_Internal_TemplateCompilerBase $compiler)
{
$compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag($compiler->parser,
"<?php \$_smarty_tpl->ext->_inheritance->endChild(\$_smarty_tpl);\n?>\n");
}
/**
* Add code for including subtemplate to end of template
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param string $file subtemplate name
*/
private function compileInclude(Smarty_Internal_TemplateCompilerBase $compiler, $file)
{
$compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag($compiler->parser,
$compiler->compileTag('include',
array($file,
array('scope' => 'parent'))));
}
/**
* Create source code for {extends} from source components array
*
* @param []\Smarty_Internal_Template_Source $components
*
* @return string
*/
public static function extendsSourceArrayCode($components)
{
$resources = array();
foreach ($components as $source) {
$resources[] = $source->resource;
}
return '{extends file=\'extends:' . join('|', $resources) . '\' extends_resource=true}';
}
} }

@ -34,6 +34,7 @@ class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, $compiler, $parameter)
{ {
$compiler->loopNesting++;
if ($parameter == 0) { if ($parameter == 0) {
$this->required_attributes = array('start', 'to'); $this->required_attributes = array('start', 'to');
$this->optional_attributes = array('max', 'step'); $this->optional_attributes = array('max', 'step');
@ -44,30 +45,51 @@ class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
$output = "<?php "; $output = "<?php\n";
if ($parameter == 1) { if ($parameter == 1) {
foreach ($_attr['start'] as $_statement) { foreach ($_attr['start'] as $_statement) {
$output .= " \$_smarty_tpl->tpl_vars[$_statement[var]] = new Smarty_Variable;"; if (is_array($_statement['var'])) {
$output .= " \$_smarty_tpl->tpl_vars[$_statement[var]]->value = $_statement[value];\n"; $var = $_statement['var']['var'];
$index = $_statement['var']['smarty_internal_index'];
} else {
$var = $_statement['var'];
$index = '';
}
$output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable;\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n";
}
if (is_array($_attr['var'])) {
$var = $_attr['var']['var'];
$index = $_attr['var']['smarty_internal_index'];
} else {
$var = $_attr['var'];
$index = '';
} }
$output .= " if ($_attr[ifexp]) { for (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$_attr[var]]->value$_attr[step]) {\n"; $output .= "if ($_attr[ifexp]) {\nfor (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$var]->value{$index}$_attr[step]) {\n";
} else { } else {
$_statement = $_attr['start']; $_statement = $_attr['start'];
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]] = new Smarty_Variable;"; if (is_array($_statement['var'])) {
$var = $_statement['var']['var'];
$index = $_statement['var']['smarty_internal_index'];
} else {
$var = $_statement['var'];
$index = '';
}
$output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable;";
if (isset($_attr['step'])) { if (isset($_attr['step'])) {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->step = $_attr[step];"; $output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];";
} else { } else {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->step = 1;"; $output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;";
} }
if (isset($_attr['max'])) { if (isset($_attr['max'])) {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$_statement[var]]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$_statement[var]]->step)),$_attr[max]);\n"; $output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step)),$_attr[max]);\n";
} else { } else {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$_statement[var]]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$_statement[var]]->step));\n"; $output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step));\n";
} }
$output .= "if (\$_smarty_tpl->tpl_vars[$_statement[var]]->total > 0) {\n"; $output .= "if (\$_smarty_tpl->tpl_vars[$var]->total > 0) {\n";
$output .= "for (\$_smarty_tpl->tpl_vars[$_statement[var]]->value = $_statement[value], \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration = 1;\$_smarty_tpl->tpl_vars[$_statement[var]]->iteration <= \$_smarty_tpl->tpl_vars[$_statement[var]]->total;\$_smarty_tpl->tpl_vars[$_statement[var]]->value += \$_smarty_tpl->tpl_vars[$_statement[var]]->step, \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration++) {\n"; $output .= "for (\$_smarty_tpl->tpl_vars[$var]->value{$index} = $_statement[value], \$_smarty_tpl->tpl_vars[$var]->iteration = 1;\$_smarty_tpl->tpl_vars[$var]->iteration <= \$_smarty_tpl->tpl_vars[$var]->total;\$_smarty_tpl->tpl_vars[$var]->value{$index} += \$_smarty_tpl->tpl_vars[$var]->step, \$_smarty_tpl->tpl_vars[$var]->iteration++) {\n";
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->first = \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration == 1;"; $output .= "\$_smarty_tpl->tpl_vars[$var]->first = \$_smarty_tpl->tpl_vars[$var]->iteration == 1;";
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->last = \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration == \$_smarty_tpl->tpl_vars[$_statement[var]]->total;"; $output .= "\$_smarty_tpl->tpl_vars[$var]->last = \$_smarty_tpl->tpl_vars[$var]->iteration == \$_smarty_tpl->tpl_vars[$var]->total;";
} }
$output .= "?>"; $output .= "?>";
@ -127,6 +149,7 @@ class Smarty_Internal_Compile_Forclose extends Smarty_Internal_CompileBase
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, $compiler, $parameter)
{ {
$compiler->loopNesting--;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
// must endblock be nocache? // must endblock be nocache?
@ -136,10 +159,11 @@ class Smarty_Internal_Compile_Forclose extends Smarty_Internal_CompileBase
list($openTag, $compiler->nocache) = $this->closeTag($compiler, array('for', 'forelse')); list($openTag, $compiler->nocache) = $this->closeTag($compiler, array('for', 'forelse'));
if ($openTag == 'forelse') { $output = "<?php }\n";
return "<?php } ?>"; if ($openTag != 'forelse') {
} else { $output .= "}\n";
return "<?php }} ?>";
} }
$output .= "?>\n";
return $output;
} }
} }

@ -14,7 +14,7 @@
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class Smarty_Internal_Compile_Foreach extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Foreach extends Smarty_Internal_Compile_Private_ForeachSection
{ {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Foreach extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('from', 'item'); public $required_attributes = array('from', 'item');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -30,6 +31,7 @@ class Smarty_Internal_Compile_Foreach extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('name', 'key'); public $optional_attributes = array('name', 'key');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -38,129 +40,232 @@ class Smarty_Internal_Compile_Foreach extends Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('from', 'item', 'key', 'name'); public $shorttag_order = array('from', 'item', 'key', 'name');
/**
* counter
*
* @var int
*/
public $counter = 0;
/**
* Name of this tag
*
* @var string
*/
public $tagName = 'foreach';
/**
* Valid properties of $smarty.foreach.name.xxx variable
*
* @var array
*/
public $nameProperties = array('first', 'last', 'index', 'iteration', 'show', 'total');
/**
* Valid properties of $item@xxx variable
*
* @var array
*/
public $itemProperties = array('first', 'last', 'index', 'iteration', 'show', 'total', 'key');
/**
* Flag if tag had name attribute
*
* @var bool
*/
public $isNamed = false;
/** /**
* Compiles code for the {foreach} tag * Compiles code for the {foreach} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$compiler->loopNesting ++;
// init
$this->isNamed = false;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
$from = $_attr['from']; $from = $_attr['from'];
$item = $_attr['item']; $item = $compiler->getId($_attr['item']);
if (!strncmp("\$_smarty_tpl->tpl_vars[$item]", $from, strlen($item) + 24)) { if ($item === false) {
$compiler->trigger_template_error("item variable {$item} may not be the same variable as at 'from'", $compiler->lex->taglineno); $item = $compiler->getVariableName($_attr['item']);
} }
$attributes = array('item' => $item);
if (isset($_attr['key'])) { if (isset($_attr['key'])) {
$key = $_attr['key']; $key = $compiler->getId($_attr['key']);
} else { if ($key === false) {
$key = null; $key = $compiler->getVariableName($_attr['key']);
}
$attributes['key'] = $key;
}
if (isset($_attr['name'])) {
$this->isNamed = true;
$attributes['name'] = $compiler->getId($_attr['name']);
}
foreach ($attributes as $a => $v) {
if ($v === false) {
$compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true);
}
}
$fromName = $compiler->getVariableName($_attr['from']);
if ($fromName) {
foreach (array('item', 'key') as $a) {
if (isset($attributes[$a]) && $attributes[$a] == $fromName) {
$compiler->trigger_template_error("'{$a}' and 'from' may not have same variable name '{$fromName}'",
null, true);
}
}
}
$itemVar = "\$_smarty_tpl->tpl_vars['{$item}']";
$local = '$__foreach_' . (isset($attributes['name']) ? $attributes['name'] : $attributes['item']) . '_' .
$this->counter ++ . '_';
$needIteration = false;
// search for used tag attributes
$itemAttr = array();
$namedAttr = array();
$this->scanForProperties($attributes, $compiler);
if (!empty($this->matchResults['item'])) {
$itemAttr = $this->matchResults['item'];
}
if (!empty($this->matchResults['named'])) {
$namedAttr = $this->matchResults['named'];
}
if (isset($itemAttr['last'])) {
$needIteration = true;
}
if (isset($namedAttr['last'])) {
$needIteration = true;
} }
$this->openTag($compiler, 'foreach', array('foreach', $compiler->nocache, $item, $key)); $keyTerm = '';
if (isset($itemAttr['key'])) {
$keyTerm = "{$itemVar}->key => ";
} elseif (isset($attributes['key'])) {
$keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => ";
}
$saveVars = array();
$restoreVars = array();
if ($this->isNamed) {
$foreachVar = "\$_smarty_tpl->tpl_vars['__smarty_foreach_{$attributes['name']}']";
if (!empty($namedAttr)) {
$saveVars['saved'] = "isset({$foreachVar}) ? {$foreachVar} : false;";
$restoreVars[] = "if ({$local}saved) {\n{$foreachVar} = {$local}saved;\n}\n";
}
}
foreach (array('item', 'key') as $a) {
if (isset($attributes[$a])) {
$saveVars['saved_' . $a] =
"isset(\$_smarty_tpl->tpl_vars['{$attributes[$a]}']) ? \$_smarty_tpl->tpl_vars['{$attributes[$a]}'] : false;";
$restoreVars[] =
"if ({$local}saved_{$a}) {\n\$_smarty_tpl->tpl_vars['{$attributes[$a]}'] = {$local}saved_{$a};\n}\n";
}
}
$this->openTag($compiler, 'foreach',
array('foreach', $compiler->nocache, $local, $restoreVars, $itemVar, true));
// maybe nocache because of nocache variables // maybe nocache because of nocache variables
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
if (isset($_attr['name'])) {
$name = $_attr['name'];
$has_name = true;
$SmartyVarName = '$smarty.foreach.' . trim($name, '\'"') . '.';
} else {
$name = null;
$has_name = false;
}
$ItemVarName = '$' . trim($item, '\'"') . '@';
// evaluates which Smarty variables and properties have to be computed
if ($has_name) {
$usesSmartyFirst = strpos($compiler->lex->data, $SmartyVarName . 'first') !== false;
$usesSmartyLast = strpos($compiler->lex->data, $SmartyVarName . 'last') !== false;
$usesSmartyIndex = strpos($compiler->lex->data, $SmartyVarName . 'index') !== false;
$usesSmartyIteration = strpos($compiler->lex->data, $SmartyVarName . 'iteration') !== false;
$usesSmartyShow = strpos($compiler->lex->data, $SmartyVarName . 'show') !== false;
$usesSmartyTotal = strpos($compiler->lex->data, $SmartyVarName . 'total') !== false;
} else {
$usesSmartyFirst = false;
$usesSmartyLast = false;
$usesSmartyTotal = false;
$usesSmartyShow = false;
}
$usesPropFirst = $usesSmartyFirst || strpos($compiler->lex->data, $ItemVarName . 'first') !== false;
$usesPropLast = $usesSmartyLast || strpos($compiler->lex->data, $ItemVarName . 'last') !== false;
$usesPropIndex = $usesPropFirst || strpos($compiler->lex->data, $ItemVarName . 'index') !== false;
$usesPropIteration = $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'iteration') !== false;
$usesPropShow = strpos($compiler->lex->data, $ItemVarName . 'show') !== false;
$usesPropTotal = $usesSmartyTotal || $usesSmartyShow || $usesPropShow || $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'total') !== false;
// generate output code // generate output code
$output = "<?php "; $output = "<?php\n";
$output .= " \$_smarty_tpl->tpl_vars[$item] = new Smarty_Variable; \$_smarty_tpl->tpl_vars[$item]->_loop = false;\n"; $output .= "\$_from = $from;\n";
if ($key != null) { $output .= "if (!is_array(\$_from) && !is_object(\$_from)) {\n";
$output .= " \$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable;\n"; $output .= "settype(\$_from, 'array');\n";
$output .= "}\n";
foreach ($saveVars as $k => $code) {
$output .= "{$local}{$k} = {$code}\n";
}
if (isset($itemAttr['show']) || isset($itemAttr['total']) || isset($namedAttr['total']) || isset($namedAttr['show']) || isset($itemAttr['last']) || isset($namedAttr['last'])) {
$output .= "{$local}total = \$_smarty_tpl->smarty->ext->_foreach->count(\$_from);\n";
} }
$output .= " \$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array');}\n"; $output .= "{$itemVar} = new Smarty_Variable();\n";
if ($usesPropTotal) { if (isset($itemAttr['show'])) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->total= \$_smarty_tpl->_count(\$_from);\n"; $output .= "{$itemVar}->show = ({$local}total > 0);\n";
} }
if ($usesPropIteration) { if (isset($itemAttr['total'])) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->iteration=0;\n"; $output .= "{$itemVar}->total= {$local}total;\n";
} }
if ($usesPropIndex) { if ($this->isNamed) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->index=-1;\n"; $prop = array();
if (isset($namedAttr['total'])) {
$prop['total'] = "'total' => {$local}total";
} }
if ($usesPropShow) { if (isset($namedAttr['iteration'])) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->tpl_vars[$item]->total > 0);\n"; $prop['iteration'] = "'iteration' => 0";
} }
if ($has_name) { if (isset($namedAttr['index'])) {
if ($usesSmartyTotal) { $prop['index'] = "'index' => -1";
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['total'] = \$_smarty_tpl->tpl_vars[$item]->total;\n";
} }
if ($usesSmartyIteration) { if (isset($namedAttr['show'])) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['iteration']=0;\n"; $prop['show'] = "'show' => ({$local}total > 0)";
} }
if ($usesSmartyIndex) { if (!empty($namedAttr)) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['index']=-1;\n"; $_vars = 'array(' . join(', ', $prop) . ')';
$output .= "{$foreachVar} = new Smarty_Variable({$_vars});\n";
} }
if ($usesSmartyShow) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['show']=(\$_smarty_tpl->tpl_vars[$item]->total > 0);\n";
} }
if (isset($attributes['key'])) {
$output .= "\$_smarty_tpl->tpl_vars['{$key}'] = new Smarty_Variable();\n";
} }
$output .= "foreach (\$_from as \$_smarty_tpl->tpl_vars[$item]->key => \$_smarty_tpl->tpl_vars[$item]->value) {\n\$_smarty_tpl->tpl_vars[$item]->_loop = true;\n"; if (isset($namedAttr['first']) || isset($itemAttr['first'])) {
if ($key != null) { $output .= "{$local}first = true;\n";
$output .= " \$_smarty_tpl->tpl_vars[$key]->value = \$_smarty_tpl->tpl_vars[$item]->key;\n";
} }
if ($usesPropIteration) { if (isset($itemAttr['iteration'])) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->iteration++;\n"; $output .= "{$itemVar}->iteration=0;\n";
} }
if ($usesPropIndex) { if (isset($itemAttr['index'])) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->index++;\n"; $output .= "{$itemVar}->index=-1;\n";
} }
if ($usesPropFirst) { if ($needIteration) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->index === 0;\n"; $output .= "{$local}iteration=0;\n";
} }
if ($usesPropLast) { $output .= "{$itemVar}->_loop = false;\n";
$output .= " \$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->iteration === \$_smarty_tpl->tpl_vars[$item]->total;\n"; $output .= "foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n";
$output .= "{$itemVar}->_loop = true;\n";
if (isset($attributes['key']) && isset($itemAttr['key'])) {
$output .= "\$_smarty_tpl->tpl_vars['{$key}']->value = {$itemVar}->key;\n";
} }
if ($has_name) { if (isset($itemAttr['iteration'])) {
if ($usesSmartyFirst) { $output .= "{$itemVar}->iteration++;\n";
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['first'] = \$_smarty_tpl->tpl_vars[$item]->first;\n";
} }
if ($usesSmartyIteration) { if (isset($itemAttr['index'])) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['iteration']++;\n"; $output .= "{$itemVar}->index++;\n";
} }
if ($usesSmartyIndex) { if ($needIteration) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['index']++;\n"; $output .= "{$local}iteration++;\n";
} }
if ($usesSmartyLast) { if (isset($itemAttr['first'])) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['last'] = \$_smarty_tpl->tpl_vars[$item]->last;\n"; $output .= "{$itemVar}->first = {$local}first;\n";
} }
if (isset($itemAttr['last'])) {
$output .= "{$itemVar}->last = {$local}iteration == {$local}total;\n";
} }
if ($this->isNamed) {
if (isset($namedAttr['iteration'])) {
$output .= "{$foreachVar}->value['iteration']++;\n";
}
if (isset($namedAttr['index'])) {
$output .= "{$foreachVar}->value['index']++;\n";
}
if (isset($namedAttr['first'])) {
$output .= "{$foreachVar}->value['first'] = {$local}first;\n";
}
if (isset($namedAttr['last'])) {
$output .= "{$foreachVar}->value['last'] = {$local}iteration == {$local}total;\n";
}
}
if (isset($namedAttr['first']) || isset($itemAttr['first'])) {
$output .= "{$local}first = false;\n";
}
$output .= "{$local}saved_local_item = {$itemVar};\n";
$output .= "?>"; $output .= "?>";
return $output; return $output;
@ -179,20 +284,23 @@ class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase
* Compiles code for the {foreachelse} tag * Compiles code for the {foreachelse} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
list($openTag, $nocache, $item, $key) = $this->closeTag($compiler, array('foreach')); list($openTag, $nocache, $local, $restoreVars, $itemVar, $foo) = $this->closeTag($compiler, array('foreach'));
$this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $item, $key)); $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $local, $restoreVars, $itemVar, false));
$output = "<?php\n";
return "<?php }\nif (!\$_smarty_tpl->tpl_vars[$item]->_loop) {\n?>"; $output .= "{$itemVar} = {$local}saved_local_item;\n";
$output .= "}\n";
$output .= "if (!{$itemVar}->_loop) {\n?>";
return $output;
} }
} }
@ -208,22 +316,32 @@ class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase
* Compiles code for the {/foreach} tag * Compiles code for the {/foreach} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes $compiler->loopNesting --;
$_attr = $this->getAttributes($compiler, $args);
// must endblock be nocache? // must endblock be nocache?
if ($compiler->nocache) { if ($compiler->nocache) {
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
} }
list($openTag, $compiler->nocache, $item, $key) = $this->closeTag($compiler, array('foreach', 'foreachelse')); list($openTag, $compiler->nocache, $local, $restoreVars, $itemVar, $restore) =
$this->closeTag($compiler, array('foreach', 'foreachelse'));
$output = "<?php\n";
return "<?php } ?>"; if ($restore) {
$output .= "{$itemVar} = {$local}saved_local_item;\n";
}
$output .= "}\n";
foreach ($restoreVars as $restore) {
$output .= $restore;
}
$output .= "?>";
return $output;
} }
} }

@ -16,6 +16,7 @@
*/ */
class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
{ {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -23,6 +24,7 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('name'); public $required_attributes = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -30,6 +32,7 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('name'); public $shorttag_order = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -42,53 +45,30 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
* Compiles code for the {function} tag * Compiles code for the {function} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return boolean true * @return bool true
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$compiler->loopNesting++;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', null, true);
} }
unset($_attr['nocache']); unset($_attr['nocache']);
$save = array($_attr, $compiler->parser->current_buffer,
$compiler->template->has_nocache_code, $compiler->template->required_plugins);
$this->openTag($compiler, 'function', $save);
$_name = trim($_attr['name'], "'\""); $_name = trim($_attr['name'], "'\"");
unset($_attr['name']); $compiler->parent_compiler->tpl_function[$_name] = $compiler->parent_compiler->template->tpl_function[$_name] = array();
// set flag that we are compiling a template function $save = array($_attr, $compiler->parser->current_buffer, $compiler->template->compiled->has_nocache_code,
$compiler->compiles_template_function = true; $compiler->template->caching);
$compiler->template->properties['function'][$_name]['parameter'] = array(); $this->openTag($compiler, 'function', $save);
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
foreach ($_attr as $_key => $_data) {
eval ('$tmp=' . $_data . ';');
$compiler->template->properties['function'][$_name]['parameter'][$_key] = $tmp;
}
$compiler->smarty->template_functions[$_name]['parameter'] = $compiler->template->properties['function'][$_name]['parameter'];
if ($compiler->template->caching) {
$output = '';
} else {
$output = "<?php if (!function_exists('smarty_template_function_{$_name}')) {
function smarty_template_function_{$_name}(\$_smarty_tpl,\$params) {
\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;
foreach (\$_smarty_tpl->smarty->template_functions['{$_name}']['parameter'] as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);};
foreach (\$params as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);}?>";
}
// Init temporary context // Init temporary context
$compiler->template->required_plugins = array('compiled' => array(), 'nocache' => array()); $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser); $compiler->template->compiled->has_nocache_code = false;
$compiler->parser->current_buffer->append_subtree(new _smarty_tag($compiler->parser, $output));
$compiler->template->has_nocache_code = false;
$compiler->has_code = false;
$compiler->template->properties['function'][$_name]['compiled'] = '';
return true; return true;
} }
} }
@ -101,62 +81,130 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
*/ */
class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
{ {
/**
* Compiler object
*
* @var object
*/
private $compiler = null;
/** /**
* Compiles code for the {/function} tag * Compiles code for the {/function} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param object|\Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return boolean true * @return bool true
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$_attr = $this->getAttributes($compiler, $args); $compiler->loopNesting--;
$this->compiler = $compiler;
$saved_data = $this->closeTag($compiler, array('function')); $saved_data = $this->closeTag($compiler, array('function'));
$_name = trim($saved_data[0]['name'], "'\""); $_attr = $saved_data[0];
// build plugin include code $_name = trim($_attr['name'], "'\"");
$plugins_string = ''; $compiler->parent_compiler->tpl_function[$_name]['called_functions'] = $compiler->parent_compiler->template->tpl_function[$_name]['called_functions'] = $compiler->called_functions;
if (!empty($compiler->template->required_plugins['compiled'])) { $compiler->parent_compiler->tpl_function[$_name]['compiled_filepath'] = $compiler->parent_compiler->template->tpl_function[$_name]['compiled_filepath'] = $compiler->parent_compiler->template->compiled->filepath;
$plugins_string = '<?php '; $compiler->parent_compiler->tpl_function[$_name]['uid'] = $compiler->parent_compiler->template->tpl_function[$_name]['uid'] = $compiler->template->source->uid;
foreach ($compiler->template->required_plugins['compiled'] as $tmp) { $compiler->called_functions = array();
foreach ($tmp as $data) { $_parameter = $_attr;
$plugins_string .= "if (!is_callable('{$data['function']}')) include '{$data['file']}';\n"; unset($_parameter['name']);
// default parameter
$_paramsArray = array();
foreach ($_parameter as $_key => $_value) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
} }
} }
$plugins_string .= '?>'; if (!empty($_paramsArray)) {
$_params = 'array(' . implode(",", $_paramsArray) . ')';
$_paramsCode = "\$params = array_merge($_params, \$params);\n";
} else {
$_paramsCode = '';
} }
if (!empty($compiler->template->required_plugins['nocache'])) { $_functionCode = $compiler->parser->current_buffer;
$plugins_string .= "<?php echo '/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php "; // setup buffer for template function code
foreach ($compiler->template->required_plugins['nocache'] as $tmp) { $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
foreach ($tmp as $data) {
$plugins_string .= "if (!is_callable(\'{$data['function']}\')) include \'{$data['file']}\';\n"; $_funcName = "smarty_template_function_{$_name}_{$compiler->template->compiled->nocache_hash}";
$_funcNameCaching = $_funcName . '_nocache';
if ($compiler->template->compiled->has_nocache_code) {
$compiler->parent_compiler->tpl_function[$_name]['call_name_caching'] = $compiler->parent_compiler->template->tpl_function[$_name]['call_name_caching'] = $_funcNameCaching;
$output = "<?php\n";
$output .= "/* {$_funcNameCaching} */\n";
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
$output .= "function {$_funcNameCaching} (\$_smarty_tpl,\$params) {\n";
$output .= "ob_start();\n";
$output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n";
$output .= $_paramsCode;
$output .= "\$_smarty_tpl->_cache['saved_tpl_vars'][] = \$_smarty_tpl->tpl_vars;\n";
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}";
$output .= "\$params = var_export(\$params, true);\n";
$output .= "echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
$output .= "\\\$saved_tpl_vars = \\\$_smarty_tpl->tpl_vars;\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new Smarty_Variable(\\\$value);\n}\n?>";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n\";?>";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
$output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
$output .= "foreach (Smarty::\\\$global_tpl_vars as \\\$key => \\\$value){\n";
$output .= "if (!isset(\\\$_smarty_tpl->tpl_vars[\\\$key]) || \\\$_smarty_tpl->tpl_vars[\\\$key] === \\\$value) \\\$saved_tpl_vars[\\\$key] = \\\$value;\n}\n";
$output .= "\\\$_smarty_tpl->tpl_vars = \\\$saved_tpl_vars;?>\n";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>";
$output .= "<?php echo str_replace('{$compiler->template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash, ob_get_clean());\n";
$output .= "\$_smarty_tpl->tpl_vars = array_pop(\$_smarty_tpl->_cache['saved_tpl_vars']);\n}\n}\n";
$output .= "/*/ {$_funcName}_nocache */\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$_functionCode = new Smarty_Internal_ParseTree_Tag($compiler->parser, preg_replace_callback("/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", array($this,
'removeNocache'), $_functionCode->to_smarty_php($compiler->parser)));
} }
$compiler->parent_compiler->tpl_function[$_name]['call_name'] = $compiler->parent_compiler->template->tpl_function[$_name]['call_name'] = $_funcName;
$output = "<?php\n";
$output .= "/* {$_funcName} */\n";
$output .= "if (!function_exists('{$_funcName}')) {\n";
$output .= "function {$_funcName}(\$_smarty_tpl,\$params) {\n";
$output .= "\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;\n";
$output .= $_paramsCode;
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}?>";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
$output = "<?php foreach (Smarty::\$global_tpl_vars as \$key => \$value){\n";
$output .= "if (!isset(\$_smarty_tpl->tpl_vars[\$key]) || \$_smarty_tpl->tpl_vars[\$key] === \$value) \$saved_tpl_vars[\$key] = \$value;\n}\n";
$output .= "\$_smarty_tpl->tpl_vars = \$saved_tpl_vars;\n}\n}\n";
$output .= "/*/ {$_funcName} */\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parent_compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
// nocache plugins must be copied
if (!empty($compiler->template->compiled->required_plugins['nocache'])) {
foreach ($compiler->template->compiled->required_plugins['nocache'] as $plugin => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->parent_compiler->template->compiled->required_plugins['compiled'][$plugin][$type] = $data;
} }
$plugins_string .= "?>/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/';?>\n";
} }
// if caching save template function for possible nocache call
if ($compiler->template->caching) {
$compiler->template->properties['function'][$_name]['compiled'] .= $plugins_string
. $compiler->parser->current_buffer->to_smarty_php();
$compiler->template->properties['function'][$_name]['nocache_hash'] = $compiler->template->properties['nocache_hash'];
$compiler->template->properties['function'][$_name]['has_nocache_code'] = $compiler->template->has_nocache_code;
$compiler->template->properties['function'][$_name]['called_functions'] = $compiler->called_functions;
$compiler->called_functions = array();
$compiler->smarty->template_functions[$_name] = $compiler->template->properties['function'][$_name];
$compiler->has_code = false;
$output = true;
} else {
$output = $plugins_string . $compiler->parser->current_buffer->to_smarty_php() . "<?php \$_smarty_tpl->tpl_vars = \$saved_tpl_vars;
foreach (Smarty::\$global_tpl_vars as \$key => \$value) if(!isset(\$_smarty_tpl->tpl_vars[\$key])) \$_smarty_tpl->tpl_vars[\$key] = \$value;}}?>\n";
} }
// reset flag that we are compiling a template function // restore old buffer
$compiler->compiles_template_function = false;
// restore old compiler status
$compiler->parser->current_buffer = $saved_data[1]; $compiler->parser->current_buffer = $saved_data[1];
$compiler->template->has_nocache_code = $compiler->template->has_nocache_code | $saved_data[2]; // restore old status
$compiler->template->required_plugins = $saved_data[3]; $compiler->template->compiled->has_nocache_code = $saved_data[2];
$compiler->template->caching = $saved_data[3];
return true;
}
return $output; /**
* @param $match
*
* @return mixed
*/
function removeNocache($match)
{
$code = preg_replace("/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", '', $match[0]);
$code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code);
return $code;
} }
} }

@ -20,12 +20,13 @@ class Smarty_Internal_Compile_If extends Smarty_Internal_CompileBase
* Compiles code for the {if} tag * Compiles code for the {if} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@ -34,7 +35,7 @@ class Smarty_Internal_Compile_If extends Smarty_Internal_CompileBase
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
if (!array_key_exists("if condition", $parameter)) { if (!array_key_exists("if condition", $parameter)) {
$compiler->trigger_template_error("missing if condition", $compiler->lex->taglineno); $compiler->trigger_template_error("missing if condition", null, true);
} }
if (is_array($parameter['if condition'])) { if (is_array($parameter['if condition'])) {
@ -42,19 +43,32 @@ class Smarty_Internal_Compile_If extends Smarty_Internal_CompileBase
$_nocache = ',true'; $_nocache = ',true';
// create nocache var to make it know for further compiling // create nocache var to make it know for further compiling
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true); $var = trim($parameter['if condition']['var']['var'], "'");
} else { } else {
$compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true); $var = trim($parameter['if condition']['var'], "'");
}
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
} }
} else { } else {
$_nocache = ''; $_nocache = '';
} }
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] .
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . $parameter['if condition']['value'] . ") {?>"; "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] .
"]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " . $parameter['if condition']['var']['var'] .
"$_nocache);\n";
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" .
$parameter['if condition']['var']['smarty_internal_index'] . " = " .
$parameter['if condition']['value'] . ") {?>";
} else { } else {
$_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});"; $_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] .
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " . $parameter['if condition']['value'] . ") {?>"; "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] .
"] = new Smarty_Variable(null{$_nocache});";
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " .
$parameter['if condition']['value'] . ") {?>";
} }
return $_output; return $_output;
@ -76,12 +90,12 @@ class Smarty_Internal_Compile_Else extends Smarty_Internal_CompileBase
* Compiles code for the {else} tag * Compiles code for the {else} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
list($nesting, $compiler->tag_nocache) = $this->closeTag($compiler, array('if', 'elseif')); list($nesting, $compiler->tag_nocache) = $this->closeTag($compiler, array('if', 'elseif'));
$this->openTag($compiler, 'else', array($nesting, $compiler->tag_nocache)); $this->openTag($compiler, 'else', array($nesting, $compiler->tag_nocache));
@ -102,12 +116,13 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
* Compiles code for the {elseif} tag * Compiles code for the {elseif} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@ -115,7 +130,7 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
list($nesting, $compiler->tag_nocache) = $this->closeTag($compiler, array('if', 'elseif')); list($nesting, $compiler->tag_nocache) = $this->closeTag($compiler, array('if', 'elseif'));
if (!array_key_exists("if condition", $parameter)) { if (!array_key_exists("if condition", $parameter)) {
$compiler->trigger_template_error("missing elseif condition", $compiler->lex->taglineno); $compiler->trigger_template_error("missing elseif condition", null, true);
} }
if (is_array($parameter['if condition'])) { if (is_array($parameter['if condition'])) {
@ -124,9 +139,14 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
$_nocache = ',true'; $_nocache = ',true';
// create nocache var to make it know for further compiling // create nocache var to make it know for further compiling
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true); $var = trim($parameter['if condition']['var']['var'], "'");
} else {
$var = trim($parameter['if condition']['var'], "'");
}
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else { } else {
$compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true); $compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
} }
} else { } else {
$_nocache = ''; $_nocache = '';
@ -139,11 +159,20 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
if ($condition_by_assign) { if ($condition_by_assign) {
$this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache)); $this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache));
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$_output = "<?php } else { if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output = "<?php } else { if (!isset(\$_smarty_tpl->tpl_vars[" .
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . $parameter['if condition']['value'] . ") {?>"; $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" .
$parameter['if condition']['var']['var'] .
"]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " .
$parameter['if condition']['var']['var'] . "$_nocache);\n";
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" .
$parameter['if condition']['var']['smarty_internal_index'] . " = " .
$parameter['if condition']['value'] . ") {?>";
} else { } else {
$_output = "<?php } else { if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});"; $_output = "<?php } else { if (!isset(\$_smarty_tpl->tpl_vars[" .
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " . $parameter['if condition']['value'] . ") {?>"; $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" .
$parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});";
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " .
$parameter['if condition']['value'] . ") {?>";
} }
return $_output; return $_output;
@ -155,22 +184,35 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
} else { } else {
$tmp = ''; $tmp = '';
foreach ($compiler->prefix_code as $code) { foreach ($compiler->prefix_code as $code) {
$tmp .= $code; $tmp = $compiler->appendCode($tmp, $code);
} }
$compiler->prefix_code = array(); $compiler->prefix_code = array();
$tmp = $compiler->appendCode("<?php } else {?>", $tmp);
$this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache)); $this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache));
if ($condition_by_assign) { if ($condition_by_assign) {
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$_output = "<?php } else {?>{$tmp}<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output = $compiler->appendCode($tmp, "<?php if (!isset(\$_smarty_tpl->tpl_vars[" .
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . $parameter['if condition']['value'] . ") {?>"; $parameter['if condition']['var']['var'] .
"]) || !is_array(\$_smarty_tpl->tpl_vars[" .
$parameter['if condition']['var']['var'] .
"]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " .
$parameter['if condition']['var']['var'] . "$_nocache);\n");
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" .
$parameter['if condition']['var']['smarty_internal_index'] . " = " .
$parameter['if condition']['value'] . ") {?>";
} else { } else {
$_output = "<?php } else {?>{$tmp}<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});"; $_output = $compiler->appendCode($tmp, "<?php if (!isset(\$_smarty_tpl->tpl_vars[" .
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " . $parameter['if condition']['value'] . ") {?>"; $parameter['if condition']['var'] .
"])) \$_smarty_tpl->tpl_vars[" .
$parameter['if condition']['var'] .
"] = new Smarty_Variable(null{$_nocache});");
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " .
$parameter['if condition']['value'] . ") {?>";
} }
return $_output; return $_output;
} else { } else {
return "<?php } else {?>{$tmp}<?php if ({$parameter['if condition']}) {?>"; return $compiler->appendCode($tmp, "<?php if ({$parameter['if condition']}) {?>");
} }
} }
} }
@ -188,12 +230,12 @@ class Smarty_Internal_Compile_Ifclose extends Smarty_Internal_CompileBase
* Compiles code for the {/if} tag * Compiles code for the {/if} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// must endblock be nocache? // must endblock be nocache?
if ($compiler->nocache) { if ($compiler->nocache) {

@ -20,6 +20,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
* caching mode to create nocache code but no cache file * caching mode to create nocache code but no cache file
*/ */
const CACHING_NOCACHE_CODE = 9999; const CACHING_NOCACHE_CODE = 9999;
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -27,6 +28,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('file'); public $required_attributes = array('file');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -34,13 +36,15 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('file'); public $shorttag_order = array('file');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $option_flags = array('nocache', 'inline', 'caching'); public $option_flags = array('nocache', 'inline', 'caching', 'bubble_up');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -49,217 +53,314 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('_any'); public $optional_attributes = array('_any');
/**
* Valid scope names
*
* @var array
*/
public $valid_scopes = array('local' => true, 'parent' => true, 'root' => true, 'global' => true,
'smarty' => true, 'tpl_root' => true);
/** /**
* Compiles code for the {include} tag * Compiles code for the {include} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param Smarty_Internal_SmartyTemplateCompiler $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @throws SmartyCompilerException
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
// save possible attributes
$include_file = $_attr['file']; $hashResourceName = $fullResourceName = $source_resource = $_attr['file'];
$variable_template = false;
$cache_tpl = false;
// parse resource_name
if (preg_match('/^([\'"])(([A-Za-z0-9_\-]{2,})[:])?(([^$()]+)|(.+))\1$/', $source_resource, $match)) {
$type = !empty($match[3]) ? $match[3] : $compiler->template->smarty->default_resource_type;
$name = !empty($match[5]) ? $match[5] : $match[6];
$handler = Smarty_Resource::load($compiler->smarty, $type);
if ($handler->recompiled || $handler->uncompiled) {
$variable_template = true;
}
if (!$variable_template) {
if ($type != 'string') {
$fullResourceName = "{$type}:{$name}";
$compiled = $compiler->parent_compiler->template->compiled;
if (isset($compiled->includes[$fullResourceName])) {
$compiled->includes[$fullResourceName] ++;
$cache_tpl = true;
} else {
$compiled->includes[$fullResourceName] = 1;
}
$fullResourceName = '"' . $fullResourceName . '"';
}
}
if (empty($match[5])) {
$variable_template = true;
}
} else {
$variable_template = true;
}
if (isset($_attr['assign'])) { if (isset($_attr['assign'])) {
// output will be stored in a smarty variable instead of being displayed // output will be stored in a smarty variable instead of being displayed
$_assign = $_attr['assign']; $_assign = $_attr['assign'];
} }
$_parent_scope = Smarty::SCOPE_LOCAL; // scope setup
$_scope = Smarty::SCOPE_LOCAL;
if (isset($_attr['scope'])) { if (isset($_attr['scope'])) {
$_attr['scope'] = trim($_attr['scope'], "'\""); $_attr['scope'] = trim($_attr['scope'], "'\"");
if (!isset($this->valid_scopes[$_attr['scope']])) {
$compiler->trigger_template_error("illegal value '{$_attr['scope']}' for \"scope\" attribute", null, true);
}
if ($_attr['scope'] != 'local') {
if ($_attr['scope'] == 'parent') { if ($_attr['scope'] == 'parent') {
$_parent_scope = Smarty::SCOPE_PARENT; $_scope = Smarty::SCOPE_PARENT;
} elseif ($_attr['scope'] == 'root') { } elseif ($_attr['scope'] == 'root') {
$_parent_scope = Smarty::SCOPE_ROOT; $_scope = Smarty::SCOPE_ROOT;
} elseif ($_attr['scope'] == 'global') { } elseif ($_attr['scope'] == 'global') {
$_parent_scope = Smarty::SCOPE_GLOBAL; $_scope = Smarty::SCOPE_GLOBAL;
} elseif ($_attr['scope'] == 'smarty') {
$_scope = Smarty::SCOPE_SMARTY;
} elseif ($_attr['scope'] == 'tpl_root') {
$_scope = Smarty::SCOPE_TPL_ROOT;
} }
if ($_attr['bubble_up'] === true) {
$_scope = $_scope + Smarty::SCOPE_BUBBLE_UP;
} }
$_caching = Smarty::CACHING_OFF;
// flag if included template code should be merged into caller
$merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) || $_attr['inline'] === true) && !$compiler->template->source->recompiled;
// set default when in nocache mode
// if ($compiler->template->caching && ($compiler->nocache || $compiler->tag_nocache || $compiler->forceNocache == 2)) {
if ($compiler->template->caching && ((!$compiler->inheritance && !$compiler->nocache && !$compiler->tag_nocache) || ($compiler->inheritance && ($compiler->nocache || $compiler->tag_nocache)))) {
$_caching = self::CACHING_NOCACHE_CODE;
} }
/*
* if the {include} tag provides individual parameter for caching
* it will not be included into the common cache file and treated like
* a nocache section
*/
if (isset($_attr['cache_lifetime'])) {
$_cache_lifetime = $_attr['cache_lifetime'];
$compiler->tag_nocache = true;
$_caching = Smarty::CACHING_LIFETIME_CURRENT;
} else {
$_cache_lifetime = 'null';
}
if (isset($_attr['cache_id'])) {
$_cache_id = $_attr['cache_id'];
$compiler->tag_nocache = true;
$_caching = Smarty::CACHING_LIFETIME_CURRENT;
} else {
$_cache_id = '$_smarty_tpl->cache_id';
} }
if (isset($_attr['compile_id'])) {
$_compile_id = $_attr['compile_id']; // set flag to cache subtemplate object when called within loop or template name is variable.
if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) {
$_cache_tpl = 'true';
} else { } else {
$_compile_id = '$_smarty_tpl->compile_id'; $_cache_tpl = 'false';
}
if ($_attr['caching'] === true) {
$_caching = Smarty::CACHING_LIFETIME_CURRENT;
} }
// assume caching is off
$_caching = Smarty::CACHING_OFF;
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
if ($merge_compiled_includes) {
$_caching = self::CACHING_NOCACHE_CODE;
} else {
$_caching = Smarty::CACHING_OFF;
} }
$call_nocache = $compiler->tag_nocache || $compiler->nocache;
// caching was on and {include} is not in nocache mode
if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) {
$_caching = self::CACHING_NOCACHE_CODE;
} }
$has_compiled_template = false; // flag if included template code should be merged into caller
$merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr['inline'] === true) &&
!$compiler->template->source->handler->recompiled;
if ($merge_compiled_includes && $_attr['inline'] !== true) { if ($merge_compiled_includes && $_attr['inline'] !== true) {
// variable template name ? // variable template name ?
if ($compiler->has_variable_string || !((substr_count($include_file, '"') == 2 || substr_count($include_file, "'") == 2)) if ($variable_template) {
|| substr_count($include_file, '(') != 0 || substr_count($include_file, '$_smarty_tpl->') != 0
) {
$merge_compiled_includes = false; $merge_compiled_includes = false;
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) { if ($compiler->template->caching) {
$compiler->trigger_template_error(' variable template file names not allow within {block} tags'); // must use individual cache file
//$_attr['caching'] = 1;
} }
} }
// variable compile_id? // variable compile_id?
if (isset($_attr['compile_id'])) { if (isset($_attr['compile_id'])) {
if (!((substr_count($_attr['compile_id'], '"') == 2 || substr_count($_attr['compile_id'], "'") == 2)) if (!((substr_count($_attr['compile_id'], '"') == 2 || substr_count($_attr['compile_id'], "'") == 2 ||
|| substr_count($_attr['compile_id'], '(') != 0 || substr_count($_attr['compile_id'], '$_smarty_tpl->') != 0 is_numeric($_attr['compile_id']))) || substr_count($_attr['compile_id'], '(') != 0 ||
substr_count($_attr['compile_id'], '$_smarty_tpl->') != 0
) { ) {
$merge_compiled_includes = false; $merge_compiled_includes = false;
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) { if ($compiler->template->caching) {
$compiler->trigger_template_error(' variable compile_id not allow within {block} tags'); // must use individual cache file
//$_attr['caching'] = 1;
} }
} }
} }
} }
if ($merge_compiled_includes) {
if ($compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache) && $_caching != self::CACHING_NOCACHE_CODE) { /*
$merge_compiled_includes = false; * if the {include} tag provides individual parameter for caching or compile_id
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) { * the subtemplate must not be included into the common cache file and is treated like
$compiler->trigger_template_error(' invalid caching mode of subtemplate within {block} tags'); * a call in nocache mode.
} *
*/
if ($_attr['nocache'] !== true && $_attr['caching']) {
$_caching = $_new_caching = (int) $_attr['caching'];
$call_nocache = true;
} else {
$_new_caching = Smarty::CACHING_LIFETIME_CURRENT;
} }
if (isset($_attr['cache_lifetime'])) {
$_cache_lifetime = $_attr['cache_lifetime'];
$call_nocache = true;
$_caching = $_new_caching;
} else {
$_cache_lifetime = '$_smarty_tpl->cache_lifetime';
} }
if ($merge_compiled_includes) { if (isset($_attr['cache_id'])) {
// we must observe different compile_id $_cache_id = $_attr['cache_id'];
$uid = sha1($_compile_id); $call_nocache = true;
$tpl_name = null; $_caching = $_new_caching;
$nocache = false; } else {
/** @var Smarty_Internal_Template $_smarty_tpl $_cache_id = '$_smarty_tpl->cache_id';
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
eval("\$tpl_name = $include_file;");
if (!isset($compiler->smarty->merged_templates_func[$tpl_name][$uid])) {
$tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template, $compiler->template->cache_id, $compiler->template->compile_id);
// save unique function name
$compiler->smarty->merged_templates_func[$tpl_name][$uid]['func'] = $tpl->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
// use current nocache hash for inlined code
$compiler->smarty->merged_templates_func[$tpl_name][$uid]['nocache_hash'] = $tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash'];
if ($compiler->template->caching && $_caching == self::CACHING_NOCACHE_CODE) {
// all code must be nocache
$nocache = true;
} }
if ($compiler->inheritance) { if (isset($_attr['compile_id'])) {
$tpl->compiler->inheritance = true; $_compile_id = $_attr['compile_id'];
} else {
$_compile_id = '$_smarty_tpl->compile_id';
} }
// make sure whole chain gets compiled
$tpl->mustCompile = true;
if (!($tpl->source->uncompiled) && $tpl->source->exists) {
// get compiled code // if subtemplate will be called in nocache mode do not merge
$compiled_code = $tpl->compiler->compileTemplate($tpl, $nocache); if ($compiler->template->caching && $call_nocache) {
// release compiler object to free memory $merge_compiled_includes = false;
unset($tpl->compiler);
// merge compiled code for {function} tags
$compiler->template->properties['function'] = array_merge($compiler->template->properties['function'], $tpl->properties['function']);
// merge filedependency
$tpl->properties['file_dependency'][$tpl->source->uid] = array($tpl->source->filepath, $tpl->source->timestamp, $tpl->source->type);
$compiler->template->properties['file_dependency'] = array_merge($compiler->template->properties['file_dependency'], $tpl->properties['file_dependency']);
// remove header code
$compiled_code = preg_replace("/(<\?php \/\*%%SmartyHeaderCode:{$tpl->properties['nocache_hash']}%%\*\/(.+?)\/\*\/%%SmartyHeaderCode%%\*\/\?>\n)/s", '', $compiled_code);
if ($tpl->has_nocache_code) {
// replace nocache_hash
$compiled_code = str_replace("{$tpl->properties['nocache_hash']}", $compiler->template->properties['nocache_hash'], $compiled_code);
$compiler->template->has_nocache_code = true;
}
$compiler->merged_templates[$tpl->properties['unifunc']] = $compiled_code;
$has_compiled_template = true;
unset ($tpl);
} }
$has_compiled_template = false;
if ($merge_compiled_includes) {
$c_id = isset($_attr['compile_id']) ? $_attr['compile_id'] : $compiler->template->compile_id;
// we must observe different compile_id and caching
$t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash])) {
$has_compiled_template =
$this->compileInlineTemplate($compiler, $fullResourceName, $_caching, $hashResourceName, $t_hash,
$c_id);
} else { } else {
$has_compiled_template = true; $has_compiled_template = true;
} }
} }
// delete {include} standard attributes // delete {include} standard attributes
unset($_attr['file'], $_attr['assign'], $_attr['cache_id'], $_attr['compile_id'], $_attr['cache_lifetime'], $_attr['nocache'], $_attr['caching'], $_attr['scope'], $_attr['inline']); unset($_attr['file'], $_attr['assign'], $_attr['cache_id'], $_attr['compile_id'], $_attr['cache_lifetime'], $_attr['nocache'], $_attr['caching'], $_attr['scope'], $_attr['inline'], $_attr['bubble_up']);
// remaining attributes must be assigned as smarty variable // remaining attributes must be assigned as smarty variable
$_vars_nc = '';
if (!empty($_attr)) { if (!empty($_attr)) {
if ($_parent_scope == Smarty::SCOPE_LOCAL) { if ($_scope == Smarty::SCOPE_LOCAL) {
$_pairs = array();
// create variables // create variables
$nccode = '';
foreach ($_attr as $key => $value) { foreach ($_attr as $key => $value) {
$_pairs[] = "'$key'=>$value"; $_pairs[] = "'$key'=>$value";
$nccode .= "\$_smarty_tpl->tpl_vars['$key'] = new Smarty_variable($value);\n"; $_vars_nc .= "\$_smarty_tpl->tpl_vars['$key'] = new Smarty_Variable($value);\n";
} }
$_vars = 'array(' . join(',', $_pairs) . ')'; $_vars = 'array(' . join(',', $_pairs) . ')';
} else { } else {
$compiler->trigger_template_error('variable passing not allowed in parent/global scope', $compiler->lex->taglineno); $compiler->trigger_template_error('variable passing not allowed in parent/global scope', null, true);
} }
} else { } else {
$_vars = 'array()'; $_vars = 'array()';
} }
if ($has_compiled_template) { $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache &&
// never call inline templates in nocache mode $_compile_id != '$_smarty_tpl->compile_id';
$compiler->suppressNocacheProcessing = true; if ($has_compiled_template && !$call_nocache) {
$_hash = $compiler->smarty->merged_templates_func[$tpl_name][$uid]['nocache_hash']; $_output = "<?php\n";
$_output = "<?php /* Call merged included template \"" . $tpl_name . "\" */\n"; if ($update_compile_id) {
$_output .= "\$_tpl_stack[] = \$_smarty_tpl;\n"; $_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n");
if (!empty($nccode) && $_caching == 9999 && $_smarty_tpl->caching) { }
$compiler->suppressNocacheProcessing = false; if (!empty($_vars_nc) && $_caching == 9999 && $compiler->template->caching) {
$_output .= substr($compiler->processNocacheCode('<?php ' .$nccode . "?>\n", true), 6, -3); //$compiler->suppressNocacheProcessing = false;
$compiler->suppressNocacheProcessing = true; $_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, - 3);
} //$compiler->suppressNocacheProcessing = true;
$_output .= " \$_smarty_tpl = \$_smarty_tpl->setupInlineSubTemplate($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, '$_hash');\n"; }
if (isset($_assign)) { if (isset($_assign)) {
$_output .= 'ob_start(); '; $_output .= "ob_start();\n";
} }
$_output .= $compiler->smarty->merged_templates_func[$tpl_name][$uid]['func'] . "(\$_smarty_tpl);\n"; $_output .= "\$_smarty_tpl->smarty->ext->_subtemplate->render(\$_smarty_tpl, {$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func']}');\n";
$_output .= "\$_smarty_tpl = array_pop(\$_tpl_stack); ";
if (isset($_assign)) { if (isset($_assign)) {
$_output .= " \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_variable(ob_get_clean());"; $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
}
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
} }
$_output .= "\n/* End of included template \"" . $tpl_name . "\" */?>"; $_output .= "?>\n";
return $_output; return $_output;
} }
if ($call_nocache) {
$compiler->tag_nocache = true;
}
$_output = "<?php ";
if ($update_compile_id) {
$_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n";
}
// was there an assign attribute // was there an assign attribute
if (isset($_assign)) { if (isset($_assign)) {
$_output = "<?php \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_variable(\$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope));?>\n";; $_output .= "ob_start();\n";
} else {
$_output = "<?php echo \$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope);?>\n";
} }
$_output .= "\$_smarty_tpl->smarty->ext->_subtemplate->render(\$_smarty_tpl, {$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_scope, {$_cache_tpl});\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
}
if ($update_compile_id) {
$_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";
}
$_output .= "?>\n";
return $_output; return $_output;
} }
/**
* Compile inline sub template
*
* @param \Smarty_Internal_SmartyTemplateCompiler $compiler
* @param $fullResourceName
* @param $_caching
* @param $hashResourceName
* @param $t_hash
* @param $c_id
*
* @return bool
*/
public function compileInlineTemplate(Smarty_Internal_SmartyTemplateCompiler $compiler, $fullResourceName,
$_caching, $hashResourceName, $t_hash, $c_id)
{
$compiler->smarty->allow_ambiguous_resources = true;
/* @var Smarty_Internal_Template $tpl */
$tpl =
new $compiler->smarty->template_class (trim($fullResourceName, '"\''), $compiler->smarty, $compiler->template,
$compiler->template->cache_id, $c_id, $_caching);
if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) {
$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid'] = $tpl->source->uid;
if (isset($compiler->template->_inheritance)) {
$tpl->_inheritance = clone $compiler->template->_inheritance;
}
$tpl->compiled = new Smarty_Template_Compiled();
$tpl->compiled->nocache_hash = $compiler->parent_compiler->template->compiled->nocache_hash;
$tpl->loadCompiler();
// save unique function name
$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func'] =
$tpl->compiled->unifunc = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
// make sure whole chain gets compiled
$tpl->mustCompile = true;
$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['nocache_hash'] =
$tpl->compiled->nocache_hash;
// get compiled code
$compiled_code = "<?php\n\n";
$compiled_code .= "/* Start inline template \"{$tpl->source->type}:{$tpl->source->name}\" =============================*/\n";
$compiled_code .= "function {$tpl->compiled->unifunc} (\$_smarty_tpl) {\n";
$compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
$compiled_code .= "<?php\n";
$compiled_code .= "}\n?>\n";
$compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode);
$compiled_code .= "<?php\n\n";
$compiled_code .= "/* End inline template \"{$tpl->source->type}:{$tpl->source->name}\" =============================*/\n";
$compiled_code .= "?>";
unset($tpl->compiler);
if ($tpl->compiled->has_nocache_code) {
// replace nocache_hash
$compiled_code =
str_replace("{$tpl->compiled->nocache_hash}", $compiler->template->compiled->nocache_hash,
$compiled_code);
$compiler->template->compiled->has_nocache_code = true;
}
$compiler->parent_compiler->mergedSubTemplatesCode[$tpl->compiled->unifunc] = $compiled_code;
return true;
} else {
return false;
}
}
} }

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('file'); public $required_attributes = array('file');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -30,6 +31,7 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('file'); public $shorttag_order = array('file');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -42,12 +44,13 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
* Compiles code for the {include_php} tag * Compiles code for the {include_php} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @throws SmartyException * @return string
* @return string compiled code * @throws \SmartyCompilerException
* @throws \SmartyException
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
if (!($compiler->smarty instanceof SmartyBC)) { if (!($compiler->smarty instanceof SmartyBC)) {
throw new SmartyException("{include_php} is deprecated, use SmartyBC class to enable"); throw new SmartyException("{include_php} is deprecated, use SmartyBC class to enable");
@ -60,9 +63,10 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
*/ */
$_smarty_tpl = $compiler->template; $_smarty_tpl = $compiler->template;
$_filepath = false; $_filepath = false;
eval('$_file = ' . $_attr['file'] . ';'); $_file = null;
eval('$_file = @' . $_attr['file'] . ';');
if (!isset($compiler->smarty->security_policy) && file_exists($_file)) { if (!isset($compiler->smarty->security_policy) && file_exists($_file)) {
$_filepath = $_file; $_filepath = $compiler->smarty->_realpath($_file, true);
} else { } else {
if (isset($compiler->smarty->security_policy)) { if (isset($compiler->smarty->security_policy)) {
$_dir = $compiler->smarty->security_policy->trusted_dir; $_dir = $compiler->smarty->security_policy->trusted_dir;
@ -71,16 +75,16 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
} }
if (!empty($_dir)) { if (!empty($_dir)) {
foreach ((array) $_dir as $_script_dir) { foreach ((array) $_dir as $_script_dir) {
$_script_dir = rtrim($_script_dir, '/\\') . DS; $_path = $compiler->smarty->_realpath($_script_dir . DS . $_file, true);
if (file_exists($_script_dir . $_file)) { if (file_exists($_path)) {
$_filepath = $_script_dir . $_file; $_filepath = $_path;
break; break;
} }
} }
} }
} }
if ($_filepath == false) { if ($_filepath == false) {
$compiler->trigger_template_error("{include_php} file '{$_file}' is not readable", $compiler->lex->taglineno); $compiler->trigger_template_error("{include_php} file '{$_file}' is not readable", null, true);
} }
if (isset($compiler->smarty->security_policy)) { if (isset($compiler->smarty->security_policy)) {
@ -99,7 +103,7 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
} }
if (isset($_assign)) { if (isset($_assign)) {
return "<?php ob_start(); include{$_once} ('{$_filepath}'); \$_smarty_tpl->assign({$_assign},ob_get_contents()); ob_end_clean();?>"; return "<?php ob_start();\ninclude{$_once} ('{$_filepath}');\n\$_smarty_tpl->assign({$_assign},ob_get_clean());\n?>";
} else { } else {
return "<?php include{$_once} ('{$_filepath}');?>\n"; return "<?php include{$_once} ('{$_filepath}');?>\n";
} }

@ -24,6 +24,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('name'); public $required_attributes = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -31,6 +32,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('name'); public $shorttag_order = array('name');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -43,16 +45,20 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
* Compiles code for the {insert} tag * Compiles code for the {insert} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
// never compile as nocache code $nocacheParam = $compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache);
if (!$nocacheParam) {
// do not compile as nocache code
$compiler->suppressNocacheProcessing = true; $compiler->suppressNocacheProcessing = true;
}
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
$_smarty_tpl = $compiler->template; $_smarty_tpl = $compiler->template;
$_name = null; $_name = null;
@ -60,19 +66,24 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
$_output = '<?php '; $_output = '<?php ';
// save possible attributes // save possible attributes
eval('$_name = ' . $_attr['name'] . ';'); eval('$_name = @' . $_attr['name'] . ';');
if (isset($_attr['assign'])) { if (isset($_attr['assign'])) {
// output will be stored in a smarty variable instead of being displayed // output will be stored in a smarty variable instead of being displayed
$_assign = $_attr['assign']; $_assign = $_attr['assign'];
// create variable to make sure that the compiler knows about its nocache status // create variable to make sure that the compiler knows about its nocache status
$compiler->template->tpl_vars[trim($_attr['assign'], "'")] = new Smarty_Variable(null, true); $var = trim($_attr['assign'], "'");
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
}
} }
if (isset($_attr['script'])) { if (isset($_attr['script'])) {
// script which must be included // script which must be included
$_function = "smarty_insert_{$_name}"; $_function = "smarty_insert_{$_name}";
$_smarty_tpl = $compiler->template; $_smarty_tpl = $compiler->template;
$_filepath = false; $_filepath = false;
eval('$_script = ' . $_attr['script'] . ';'); eval('$_script = @' . $_attr['script'] . ';');
if (!isset($compiler->smarty->security_policy) && file_exists($_script)) { if (!isset($compiler->smarty->security_policy) && file_exists($_script)) {
$_filepath = $_script; $_filepath = $_script;
} else { } else {
@ -92,13 +103,13 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
} }
} }
if ($_filepath == false) { if ($_filepath == false) {
$compiler->trigger_template_error("{insert} missing script file '{$_script}'", $compiler->lex->taglineno); $compiler->trigger_template_error("{insert} missing script file '{$_script}'", null, true);
} }
// code for script file loading // code for script file loading
$_output .= "require_once '{$_filepath}' ;"; $_output .= "require_once '{$_filepath}' ;";
require_once $_filepath; require_once $_filepath;
if (!is_callable($_function)) { if (!is_callable($_function)) {
$compiler->trigger_template_error(" {insert} function '{$_function}' is not callable in script file '{$_script}'", $compiler->lex->taglineno); $compiler->trigger_template_error(" {insert} function '{$_function}' is not callable in script file '{$_script}'", null, true);
} }
} else { } else {
$_filepath = 'null'; $_filepath = 'null';
@ -107,7 +118,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
if (!is_callable($_function)) { if (!is_callable($_function)) {
// try plugin // try plugin
if (!$_function = $compiler->getPlugin($_name, 'insert')) { if (!$_function = $compiler->getPlugin($_name, 'insert')) {
$compiler->trigger_template_error("{insert} no function or plugin found for '{$_name}'", $compiler->lex->taglineno); $compiler->trigger_template_error("{insert} no function or plugin found for '{$_name}'", null, true);
} }
} }
} }
@ -121,14 +132,14 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
$_params = 'array(' . implode(", ", $_paramsArray) . ')'; $_params = 'array(' . implode(", ", $_paramsArray) . ')';
// call insert // call insert
if (isset($_assign)) { if (isset($_assign)) {
if ($_smarty_tpl->caching) { if ($_smarty_tpl->caching && !$nocacheParam) {
$_output .= "echo Smarty_Internal_Nocache_Insert::compile ('{$_function}',{$_params}, \$_smarty_tpl, '{$_filepath}',{$_assign});?>"; $_output .= "echo Smarty_Internal_Nocache_Insert::compile ('{$_function}',{$_params}, \$_smarty_tpl, '{$_filepath}',{$_assign});?>";
} else { } else {
$_output .= "\$_smarty_tpl->assign({$_assign} , {$_function} ({$_params},\$_smarty_tpl), true);?>"; $_output .= "\$_smarty_tpl->assign({$_assign} , {$_function} ({$_params},\$_smarty_tpl), true);?>";
} }
} else { } else {
$compiler->has_output = true; $compiler->has_output = true;
if ($_smarty_tpl->caching) { if ($_smarty_tpl->caching && !$nocacheParam) {
$_output .= "echo Smarty_Internal_Nocache_Insert::compile ('{$_function}',{$_params}, \$_smarty_tpl, '{$_filepath}');?>"; $_output .= "echo Smarty_Internal_Nocache_Insert::compile ('{$_function}',{$_params}, \$_smarty_tpl, '{$_filepath}');?>";
} else { } else {
$_output .= "echo {$_function}({$_params},\$_smarty_tpl);?>"; $_output .= "echo {$_function}({$_params},\$_smarty_tpl);?>";

@ -21,15 +21,16 @@ class Smarty_Internal_Compile_Ldelim extends Smarty_Internal_CompileBase
* This tag does output the left delimiter * This tag does output the left delimiter
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', null, true);
} }
// this tag does not return compiled code // this tag does not return compiled code
$compiler->has_code = true; $compiler->has_code = true;

@ -16,21 +16,26 @@
*/ */
class Smarty_Internal_Compile_Nocache extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Nocache extends Smarty_Internal_CompileBase
{ {
/**
* Array of names of valid option flags
*
* @var array
*/
public $option_flags = array();
/** /**
* Compiles code for the {nocache} tag * Compiles code for the {nocache} tag
* This tag does not generate compiled output. It only sets a compiler flag. * This tag does not generate compiled output. It only sets a compiler flag.
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return bool * @return bool
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { $this->openTag($compiler, 'nocache', array($compiler->nocache));
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno);
}
// enter nocache mode // enter nocache mode
$compiler->nocache = true; $compiler->nocache = true;
// this tag does not return compiled code // this tag does not return compiled code
@ -53,15 +58,15 @@ class Smarty_Internal_Compile_Nocacheclose extends Smarty_Internal_CompileBase
* This tag does not generate compiled output. It only sets a compiler flag. * This tag does not generate compiled output. It only sets a compiler flag.
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return bool * @return bool
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
// leave nocache mode // leave nocache mode
$compiler->nocache = false; list($compiler->nocache) = $this->closeTag($compiler, array('nocache'));
// this tag does not return compiled code // this tag does not return compiled code
$compiler->has_code = false; $compiler->has_code = false;

@ -28,14 +28,14 @@ class Smarty_Internal_Compile_Private_Block_Plugin extends Smarty_Internal_Compi
* Compiles code for the execution of block plugin * Compiles code for the execution of block plugin
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of block plugin * @param string $tag name of block plugin
* @param string $function PHP function name * @param string $function PHP function name
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter, $tag, $function) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter, $tag, $function)
{ {
if (!isset($tag[5]) || substr($tag, - 5) != 'close') { if (!isset($tag[5]) || substr($tag, - 5) != 'close') {
// opening tag of block plugin // opening tag of block plugin
@ -60,7 +60,7 @@ class Smarty_Internal_Compile_Private_Block_Plugin extends Smarty_Internal_Compi
// maybe nocache because of nocache variables or nocache plugin // maybe nocache because of nocache variables or nocache plugin
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
// compile code // compile code
$output = "<?php \$_smarty_tpl->smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; echo {$function}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; $output = "<?php \$_smarty_tpl->smarty->_cache['tag_stack'][] = array('{$tag}', {$_params}); \$_block_repeat=true; echo {$function}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>";
} else { } else {
// must endblock be nocache? // must endblock be nocache?
if ($compiler->nocache) { if ($compiler->nocache) {
@ -75,9 +75,13 @@ class Smarty_Internal_Compile_Private_Block_Plugin extends Smarty_Internal_Compi
$mod_pre = $mod_post = ''; $mod_pre = $mod_post = '';
} else { } else {
$mod_pre = ' ob_start(); '; $mod_pre = ' ob_start(); ';
$mod_post = 'echo ' . $compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifier_list'], 'value' => 'ob_get_clean()')) . ';'; $mod_post = 'echo ' .
$compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifier_list'],
'value' => 'ob_get_clean()')) . ';';
} }
$output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre . " echo {$function}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " . $mod_post . " } array_pop(\$_smarty_tpl->smarty->_tag_stack);?>"; $output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre .
" echo {$function}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " . $mod_post .
" } array_pop(\$_smarty_tpl->smarty->_cache['tag_stack']);?>";
} }
return $output . "\n"; return $output . "\n";

@ -0,0 +1,220 @@
<?php
/**
* Smarty Internal Plugin Compile ForeachSection
* Shared methods for {foreach} {section} tags
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile ForeachSection Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_CompileBase
{
/**
* Preg search pattern
*
* @var string
*/
private $propertyPreg = '';
/**
* Offsets in preg match result
*
* @var array
*/
private $resultOffsets = array();
/**
* Start offset
*
* @var int
*/
private $startOffset = 0;
/**
* Name of this tag
*
* @var string
*/
public $tagName = '';
/**
* Valid properties of $smarty.xxx variable
*
* @var array
*/
public $nameProperties = array();
/**
* {section} tag has no item properties
*
* @var array
*/
public $itemProperties = null;
/**
* {section} tag has always name attribute
*
* @var bool
*/
public $isNamed = true;
/**
* @var array
*/
public $matchResults = array();
/**
* Scan sources for used tag attributes
*
* @param array $attributes
* @param \Smarty_Internal_TemplateCompilerBase $compiler
*/
public function scanForProperties($attributes, Smarty_Internal_TemplateCompilerBase $compiler)
{
$this->propertyPreg = '~(';
$this->startOffset = 0;
$this->resultOffsets = array();
$this->matchResults = array('named' => array(), 'item' => array());
if ($this->isNamed) {
$this->buildPropertyPreg(true, $attributes);
}
if (isset($this->itemProperties)) {
if ($this->isNamed) {
$this->propertyPreg .= '|';
}
$this->buildPropertyPreg(false, $attributes);
}
$this->propertyPreg .= ')\W~i';
// Template source
$this->matchTemplateSource($compiler);
// Parent template source
$this->matchParentTemplateSource($compiler);
// {block} source
$this->matchBlockSource($compiler);
}
/**
* Build property preg string
*
* @param bool $named
* @param array $attributes
*/
public function buildPropertyPreg($named, $attributes)
{
if ($named) {
$this->resultOffsets['named'] = $this->startOffset + 3;
$this->propertyPreg .= "([\$]smarty[.]{$this->tagName}[.]{$attributes['name']}[.](";
$properties = $this->nameProperties;
} else {
$this->resultOffsets['item'] = $this->startOffset + 3;
$this->propertyPreg .= "([\$]{$attributes['item']}[@](";
$properties = $this->itemProperties;
}
$this->startOffset += count($properties) + 2;
$propName = reset($properties);
while ($propName) {
$this->propertyPreg .= "({$propName})";
$propName = next($properties);
if ($propName) {
$this->propertyPreg .= '|';
}
}
$this->propertyPreg .= '))';
}
/**
* Find matches in source string
*
* @param string $source
*/
public function matchProperty($source)
{
preg_match_all($this->propertyPreg, $source, $match, PREG_SET_ORDER);
foreach ($this->resultOffsets as $key => $offset) {
foreach ($match as $m) {
if (isset($m[$offset]) && !empty($m[$offset])) {
$this->matchResults[$key][strtolower($m[$offset])] = true;
}
}
}
}
/**
* Find matches in template source
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
*/
public function matchTemplateSource(Smarty_Internal_TemplateCompilerBase $compiler)
{
$this->matchProperty($compiler->parser->lex->data);
}
/**
* Find matches in all parent template source
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
*/
public function matchParentTemplateSource(Smarty_Internal_TemplateCompilerBase $compiler)
{
// search parent compiler template source
$nextCompiler = $compiler;
while ($nextCompiler !== $nextCompiler->parent_compiler) {
$nextCompiler = $nextCompiler->parent_compiler;
if ($compiler !== $nextCompiler) {
// get template source
$_content = $nextCompiler->template->source->getContent();
if ($_content != '') {
// run pre filter if required
if ((isset($nextCompiler->smarty->autoload_filters['pre']) ||
isset($nextCompiler->smarty->registered_filters['pre']))) {
$_content = $nextCompiler->smarty->ext->_filter_Handler->runFilter('pre', $_content, $nextCompiler->template);
}
$this->matchProperty($_content);
}
}
}
}
/**
* Find matches in {block} tag source
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
*/
public function matchBlockSource(Smarty_Internal_TemplateCompilerBase $compiler)
{
}
/**
* Compiles code for the {$smarty.foreach.xxx} or {$smarty.section.xxx}tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string compiled code
* @throws \SmartyCompilerException
*/
public function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
$tag = strtolower(trim($parameter[ 0 ], '"\''));
$name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : false;
if (!$name) {
$compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true);
}
$property = isset($parameter[ 2 ]) ? strtolower($compiler->getId($parameter[ 2 ])) : false;
if (!$property || !in_array($property, $this->nameProperties)) {
$compiler->trigger_template_error("missing or illegal \$smarty.{$tag} property attribute", null, true);
}
$tagVar = "'__smarty_{$tag}_{$name}'";
return "(isset(\$_smarty_tpl->tpl_vars[{$tagVar}]->value['{$property}']) ? \$_smarty_tpl->tpl_vars[{$tagVar}]->value['{$property}'] : null)";
}
}

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Private_Function_Plugin extends Smarty_Internal_Co
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array(); public $required_attributes = array();
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -35,14 +36,14 @@ class Smarty_Internal_Compile_Private_Function_Plugin extends Smarty_Internal_Co
* Compiles code for the execution of function plugin * Compiles code for the execution of function plugin
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of function plugin * @param string $tag name of function plugin
* @param string $function PHP function name * @param string $function PHP function name
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter, $tag, $function) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter, $tag, $function)
{ {
// This tag does create output // This tag does create output
$compiler->has_output = true; $compiler->has_output = true;

@ -21,12 +21,13 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
* Compiles code for modifier execution * Compiles code for modifier execution
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@ -52,7 +53,8 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
$output = "{$function}({$params})"; $output = "{$function}({$params})";
} else { } else {
if (is_object($function[0])) { if (is_object($function[0])) {
$output = '$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][\'' . $modifier . '\'][0][0]->' . $function[1] . '(' . $params . ')'; $output = '$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][\'' .
$modifier . '\'][0][0]->' . $function[1] . '(' . $params . ')';
} else { } else {
$output = $function[0] . '::' . $function[1] . '(' . $params . ')'; $output = $function[0] . '::' . $function[1] . '(' . $params . ')';
} }
@ -73,7 +75,9 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
// modifiercompiler plugin // modifiercompiler plugin
if ($compiler->smarty->loadPlugin('smarty_modifiercompiler_' . $modifier)) { if ($compiler->smarty->loadPlugin('smarty_modifiercompiler_' . $modifier)) {
// check if modifier allowed // check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) { if (!is_object($compiler->smarty->security_policy) ||
$compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)
) {
$plugin = 'smarty_modifiercompiler_' . $modifier; $plugin = 'smarty_modifiercompiler_' . $modifier;
$output = $plugin($single_modifier, $compiler); $output = $plugin($single_modifier, $compiler);
} }
@ -85,7 +89,9 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
// modifier plugin // modifier plugin
if ($function = $compiler->getPlugin($modifier, Smarty::PLUGIN_MODIFIER)) { if ($function = $compiler->getPlugin($modifier, Smarty::PLUGIN_MODIFIER)) {
// check if modifier allowed // check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) { if (!is_object($compiler->smarty->security_policy) ||
$compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)
) {
$output = "{$function}({$params})"; $output = "{$function}({$params})";
} }
$compiler->known_modifier_type[$modifier] = $type; $compiler->known_modifier_type[$modifier] = $type;
@ -96,7 +102,9 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
// PHP function // PHP function
if (is_callable($modifier)) { if (is_callable($modifier)) {
// check if modifier allowed // check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)) { if (!is_object($compiler->smarty->security_policy) ||
$compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)
) {
$output = "{$modifier}({$params})"; $output = "{$modifier}({$params})";
} }
$compiler->known_modifier_type[$modifier] = $type; $compiler->known_modifier_type[$modifier] = $type;
@ -105,21 +113,29 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
break; break;
case 6: case 6:
// default plugin handler // default plugin handler
if (isset($compiler->default_handler_plugins[Smarty::PLUGIN_MODIFIER][$modifier]) || (is_callable($compiler->smarty->default_plugin_handler_func) && $compiler->getPluginFromDefaultHandler($modifier, Smarty::PLUGIN_MODIFIER))) { if (isset($compiler->default_handler_plugins[Smarty::PLUGIN_MODIFIER][$modifier]) ||
(is_callable($compiler->smarty->default_plugin_handler_func) &&
$compiler->getPluginFromDefaultHandler($modifier, Smarty::PLUGIN_MODIFIER))
) {
$function = $compiler->default_handler_plugins[Smarty::PLUGIN_MODIFIER][$modifier][0]; $function = $compiler->default_handler_plugins[Smarty::PLUGIN_MODIFIER][$modifier][0];
// check if modifier allowed // check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) { if (!is_object($compiler->smarty->security_policy) ||
$compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)
) {
if (!is_array($function)) { if (!is_array($function)) {
$output = "{$function}({$params})"; $output = "{$function}({$params})";
} else { } else {
if (is_object($function[0])) { if (is_object($function[0])) {
$output = '$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][\'' . $modifier . '\'][0][0]->' . $function[1] . '(' . $params . ')'; $output = '$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][\'' .
$modifier . '\'][0][0]->' . $function[1] . '(' . $params . ')';
} else { } else {
$output = $function[0] . '::' . $function[1] . '(' . $params . ')'; $output = $function[0] . '::' . $function[1] . '(' . $params . ')';
} }
} }
} }
if (isset($compiler->template->required_plugins['nocache'][$modifier][Smarty::PLUGIN_MODIFIER]['file']) || isset($compiler->template->required_plugins['compiled'][$modifier][Smarty::PLUGIN_MODIFIER]['file'])) { if (isset($compiler->parent_compiler->template->compiled->required_plugins['nocache'][$modifier][Smarty::PLUGIN_MODIFIER]['file']) ||
isset($compiler->parent_compiler->template->compiled->required_plugins['compiled'][$modifier][Smarty::PLUGIN_MODIFIER]['file'])
) {
// was a plugin // was a plugin
$compiler->known_modifier_type[$modifier] = 4; $compiler->known_modifier_type[$modifier] = 4;
} else { } else {
@ -130,7 +146,7 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
} }
} }
if (!isset($compiler->known_modifier_type[$modifier])) { if (!isset($compiler->known_modifier_type[$modifier])) {
$compiler->trigger_template_error("unknown modifier \"" . $modifier . "\"", $compiler->lex->taglineno); $compiler->trigger_template_error("unknown modifier \"" . $modifier . "\"", null, true);
} }
} }

@ -28,14 +28,14 @@ class Smarty_Internal_Compile_Private_Object_Block_Function extends Smarty_Inter
* Compiles code for the execution of block plugin * Compiles code for the execution of block plugin
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of block object * @param string $tag name of block object
* @param string $method name of method to call * @param string $method name of method to call
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter, $tag, $method) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter, $tag, $method)
{ {
if (!isset($tag[5]) || substr($tag, - 5) != 'close') { if (!isset($tag[5]) || substr($tag, - 5) != 'close') {
// opening tag of block plugin // opening tag of block plugin
@ -60,7 +60,8 @@ class Smarty_Internal_Compile_Private_Object_Block_Function extends Smarty_Inter
// maybe nocache because of nocache variables or nocache plugin // maybe nocache because of nocache variables or nocache plugin
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
// compile code // compile code
$output = "<?php \$_smarty_tpl->smarty->_tag_stack[] = array('{$tag}->{$method}', {$_params}); \$_block_repeat=true; echo \$_smarty_tpl->smarty->registered_objects['{$tag}'][0]->{$method}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; $output =
"<?php \$_smarty_tpl->smarty->_cache['tag_stack'][] = array('{$tag}->{$method}', {$_params}); \$_block_repeat=true; echo \$_smarty_tpl->smarty->registered_objects['{$tag}'][0]->{$method}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>";
} else { } else {
$base_tag = substr($tag, 0, - 5); $base_tag = substr($tag, 0, - 5);
// must endblock be nocache? // must endblock be nocache?
@ -76,9 +77,13 @@ class Smarty_Internal_Compile_Private_Object_Block_Function extends Smarty_Inter
$mod_pre = $mod_post = ''; $mod_pre = $mod_post = '';
} else { } else {
$mod_pre = ' ob_start(); '; $mod_pre = ' ob_start(); ';
$mod_post = 'echo ' . $compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifier_list'], 'value' => 'ob_get_clean()')) . ';'; $mod_post = 'echo ' . $compiler->compileTag('private_modifier', array(),
array('modifierlist' => $parameter['modifier_list'],
'value' => 'ob_get_clean()')) . ';';
} }
$output = "<?php \$_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;" . $mod_pre . " echo \$_smarty_tpl->smarty->registered_objects['{$base_tag}'][0]->{$method}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " . $mod_post . " } array_pop(\$_smarty_tpl->smarty->_tag_stack);?>"; $output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre .
" echo \$_smarty_tpl->smarty->registered_objects['{$base_tag}'][0]->{$method}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " .
$mod_post . " } array_pop(\$_smarty_tpl->smarty->_cache['tag_stack']);?>";
} }
return $output . "\n"; return $output . "\n";

@ -28,14 +28,14 @@ class Smarty_Internal_Compile_Private_Object_Function extends Smarty_Internal_Co
* Compiles code for the execution of function plugin * Compiles code for the execution of function plugin
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of function * @param string $tag name of function
* @param string $method name of method to call * @param string $method name of method to call
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter, $tag, $method) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter, $tag, $method)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);

@ -0,0 +1,209 @@
<?php
/**
* Smarty Internal Plugin Compile PHP Expression
* Compiles any tag which will output an expression or variable
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile PHP Expression Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Private_Php extends Smarty_Internal_CompileBase
{
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $required_attributes = array('code', 'type');
/**
* Compiles code for generating output from any expression
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string
* @throws \SmartyException
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$compiler->has_code = false;
if ($_attr['type'] == 'xml') {
$compiler->tag_nocache = true;
$save = $compiler->template->compiled->has_nocache_code;
$output = addcslashes($_attr['code'], "'\\");
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" .
$output .
"';?>", $compiler, true)));
$compiler->template->compiled->has_nocache_code = $save;
return '';
}
if ($_attr['type'] != 'tag') {
if ($compiler->php_handling == Smarty::PHP_REMOVE) {
return '';
} elseif ($compiler->php_handling == Smarty::PHP_QUOTE) {
$output = preg_replace_callback('#(<\?(?:php|=)?)|(<%)|(<script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*>)|(\?>)|(%>)|(<\/script>)#i', array($this,
'quote'), $_attr['code']);
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Text($output));
return '';
} elseif ($compiler->php_handling == Smarty::PHP_PASSTHRU || $_attr['type'] == 'unmatched') {
$compiler->tag_nocache = true;
$save = $compiler->template->compiled->has_nocache_code;
$output = addcslashes($_attr['code'], "'\\");
$compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" .
$output .
"';?>", $compiler, true)));
$compiler->template->compiled->has_nocache_code = $save;
return '';
} elseif ($compiler->php_handling == Smarty::PHP_ALLOW) {
if (!($compiler->smarty instanceof SmartyBC)) {
$compiler->trigger_template_error('$smarty->php_handling PHP_ALLOW not allowed. Use SmartyBC to enable it', null, true);
}
$compiler->has_code = true;
return $_attr['code'];
} else {
$compiler->trigger_template_error('Illegal $smarty->php_handling value', null, true);
}
} else {
$compiler->has_code = true;
if (!($compiler->smarty instanceof SmartyBC)) {
$compiler->trigger_template_error('{php}{/php} tags not allowed. Use SmartyBC to enable them', null, true);
}
$ldel = preg_quote($compiler->smarty->left_delimiter, '#');
$rdel = preg_quote($compiler->smarty->right_delimiter, '#');
preg_match("#^({$ldel}php\\s*)((.)*?)({$rdel})#", $_attr['code'], $match);
if (!empty($match[2])) {
if ('nocache' == trim($match[2])) {
$compiler->tag_nocache = true;
} else {
$compiler->trigger_template_error("illegal value of option flag \"{$match[2]}\"", null, true);
}
}
return preg_replace(array("#^{$ldel}\\s*php\\s*(.)*?{$rdel}#",
"#{$ldel}\\s*/\\s*php\\s*{$rdel}$#"), array('<?php ', '?>'), $_attr['code']);
}
}
/**
* Lexer code for PHP tags
*
* This code has been moved from lexer here fo easier debugging and maintenance
*
* @param $lex
*/
public function parsePhp($lex)
{
$lex->token = Smarty_Internal_Templateparser::TP_PHP;
$close = 0;
$lex->taglineno = $lex->line;
$closeTag = '?>';
if (strpos($lex->value, '<?xml') === 0) {
$lex->is_xml = true;
$lex->token = Smarty_Internal_Templateparser::TP_NOCACHE;
return;
} elseif (strpos($lex->value, '<?') === 0) {
$lex->phpType = 'php';
} elseif (strpos($lex->value, '<%') === 0) {
$lex->phpType = 'asp';
$closeTag = '%>';
} elseif (strpos($lex->value, '%>') === 0) {
$lex->phpType = 'unmatched';
} elseif (strpos($lex->value, '?>') === 0) {
if ($lex->is_xml) {
$lex->is_xml = false;
$lex->token = Smarty_Internal_Templateparser::TP_NOCACHE;
return;
}
$lex->phpType = 'unmatched';
} elseif (strpos($lex->value, '<s') === 0) {
$lex->phpType = 'script';
$closeTag = '</script>';
} elseif (strpos($lex->value, $lex->smarty->left_delimiter) === 0) {
if ($lex->isAutoLiteral()) {
$lex->token = Smarty_Internal_Templateparser::TP_TEXT;
return;
}
$closeTag = "{$lex->smarty->left_delimiter}/php{$lex->smarty->right_delimiter}";
if ($lex->value == $closeTag) {
$lex->compiler->trigger_template_error("unexpected closing tag '{$closeTag}'");
}
$lex->phpType = 'tag';
}
if ($lex->phpType == 'unmatched') {
return;
}
if (($lex->phpType == 'php' || $lex->phpType == 'asp') &&
($lex->compiler->php_handling == Smarty::PHP_PASSTHRU || $lex->compiler->php_handling == Smarty::PHP_QUOTE)
) {
return;
}
$start = $lex->counter + strlen($lex->value);
$body = true;
if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
$close = $match[0][1];
} else {
$lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
}
while ($body) {
if (preg_match('~([/][*])|([/][/][^\n]*)|(\'[^\'\\\\]*(?:\\.[^\'\\\\]*)*\')|("[^"\\\\]*(?:\\.[^"\\\\]*)*")~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
$value = $match[0][0];
$from = $pos = $match[0][1];
if ($pos > $close) {
$body = false;
} else {
$start = $pos + strlen($value);
$phpCommentStart = $value == '/*';
if ($phpCommentStart) {
$phpCommentEnd = preg_match('~([*][/])~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start);
if ($phpCommentEnd) {
$pos2 = $match[0][1];
$start = $pos2 + strlen($match[0][0]);
}
}
while ($close > $pos && $close < $start) {
if (preg_match('~' . preg_quote($closeTag, '~') .
'~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $from)) {
$close = $match[0][1];
$from = $close + strlen($match[0][0]);
} else {
$lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
}
}
if ($phpCommentStart && (!$phpCommentEnd || $pos2 > $close)) {
$lex->taglineno = $lex->line + substr_count(substr($lex->data, $lex->counter, $start), "\n");
$lex->compiler->trigger_template_error("missing PHP comment closing tag '*/'");
}
}
} else {
$body = false;
}
}
$lex->value = substr($lex->data, $lex->counter, $close + strlen($closeTag) - $lex->counter);
}
/*
* Call back function for $php_handling = PHP_QUOTE
*
*/
/**
* @param $match
*
* @return string
*/
private function quote($match)
{
return htmlspecialchars($match[0], ENT_QUOTES);
}
}

@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('assign'); public $optional_attributes = array('assign');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -35,13 +36,13 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
* Compiles code for generating output from any expression * Compiles code for generating output from any expression
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @throws SmartyException * @return string
* @return string compiled code * @throws \SmartyException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@ -57,7 +58,8 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
$output = $parameter['value']; $output = $parameter['value'];
// tag modifier // tag modifier
if (!empty($parameter['modifierlist'])) { if (!empty($parameter['modifierlist'])) {
$output = $compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifierlist'], 'value' => $output)); $output = $compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifierlist'],
'value' => $output));
} }
if (!$_attr['nofilter']) { if (!$_attr['nofilter']) {
// default modifier // default modifier
@ -74,7 +76,8 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
} }
$compiler->default_modifier_list = $modifierlist; $compiler->default_modifier_list = $modifierlist;
} }
$output = $compiler->compileTag('private_modifier', array(), array('modifierlist' => $compiler->default_modifier_list, 'value' => $output)); $output = $compiler->compileTag('private_modifier', array(), array('modifierlist' => $compiler->default_modifier_list,
'value' => $output));
} }
// autoescape html // autoescape html
if ($compiler->template->smarty->escape_html) { if ($compiler->template->smarty->escape_html) {
@ -82,7 +85,8 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
} }
// loop over registered filters // loop over registered filters
if (!empty($compiler->template->smarty->registered_filters[Smarty::FILTER_VARIABLE])) { if (!empty($compiler->template->smarty->registered_filters[Smarty::FILTER_VARIABLE])) {
foreach ($compiler->template->smarty->registered_filters[Smarty::FILTER_VARIABLE] as $key => $function) { foreach ($compiler->template->smarty->registered_filters[Smarty::FILTER_VARIABLE] as $key =>
$function) {
if (!is_array($function)) { if (!is_array($function)) {
$output = "{$function}({$output},\$_smarty_tpl)"; $output = "{$function}({$output},\$_smarty_tpl)";
} elseif (is_object($function[0])) { } elseif (is_object($function[0])) {
@ -104,13 +108,14 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
} }
} }
} }
if (isset($compiler->template->variable_filters)) { foreach ($compiler->variable_filters as $filter) {
foreach ($compiler->template->variable_filters as $filter) { if (count($filter) == 1 &&
if (count($filter) == 1 && ($result = $this->compile_output_filter($compiler, $filter[0], $output)) !== false) { ($result = $this->compile_output_filter($compiler, $filter[0], $output)) !== false
) {
$output = $result; $output = $result;
} else { } else {
$output = $compiler->compileTag('private_modifier', array(), array('modifierlist' => array($filter), 'value' => $output)); $output = $compiler->compileTag('private_modifier', array(), array('modifierlist' => array($filter),
} 'value' => $output));
} }
} }
} }
@ -123,23 +128,23 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
} }
/** /**
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param string $name name of variable filter * @param string $name name of variable filter
* @param string $output embedded output * @param string $output embedded output
* *
* @return string * @return string
*/ */
private function compile_output_filter($compiler, $name, $output) private function compile_output_filter(Smarty_Internal_TemplateCompilerBase $compiler, $name, $output)
{ {
$plugin_name = "smarty_variablefilter_{$name}"; $plugin_name = "smarty_variablefilter_{$name}";
$path = $compiler->smarty->loadPlugin($plugin_name, false); $path = $compiler->smarty->loadPlugin($plugin_name, false);
if ($path) { if ($path) {
if ($compiler->template->caching) { if ($compiler->template->caching) {
$compiler->template->required_plugins['nocache'][$name][Smarty::FILTER_VARIABLE]['file'] = $path; $compiler->parent_compiler->template->compiled->required_plugins['nocache'][$name][Smarty::FILTER_VARIABLE]['file'] = $path;
$compiler->template->required_plugins['nocache'][$name][Smarty::FILTER_VARIABLE]['function'] = $plugin_name; $compiler->parent_compiler->template->compiled->required_plugins['nocache'][$name][Smarty::FILTER_VARIABLE]['function'] = $plugin_name;
} else { } else {
$compiler->template->required_plugins['compiled'][$name][Smarty::FILTER_VARIABLE]['file'] = $path; $compiler->parent_compiler->template->compiled->required_plugins['compiled'][$name][Smarty::FILTER_VARIABLE]['file'] = $path;
$compiler->template->required_plugins['compiled'][$name][Smarty::FILTER_VARIABLE]['function'] = $plugin_name; $compiler->parent_compiler->template->compiled->required_plugins['compiled'][$name][Smarty::FILTER_VARIABLE]['function'] = $plugin_name;
} }
} else { } else {
// not found // not found

@ -28,13 +28,13 @@ class Smarty_Internal_Compile_Private_Registered_Block extends Smarty_Internal_C
* Compiles code for the execution of a block function * Compiles code for the execution of a block function
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of block function * @param string $tag name of block function
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter, $tag) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter, $tag)
{ {
if (!isset($tag[5]) || substr($tag, - 5) != 'close') { if (!isset($tag[5]) || substr($tag, - 5) != 'close') {
// opening tag of block plugin // opening tag of block plugin
@ -69,11 +69,11 @@ class Smarty_Internal_Compile_Private_Registered_Block extends Smarty_Internal_C
$function = $tag_info[0]; $function = $tag_info[0];
// compile code // compile code
if (!is_array($function)) { if (!is_array($function)) {
$output = "<?php \$_smarty_tpl->smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; echo {$function}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; $output = "<?php \$_smarty_tpl->smarty->_cache['tag_stack'][] = array('{$tag}', {$_params}); \$_block_repeat=true; echo {$function}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>";
} elseif (is_object($function[0])) { } elseif (is_object($function[0])) {
$output = "<?php \$_smarty_tpl->smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; echo \$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]->{$function[1]}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; $output = "<?php \$_smarty_tpl->smarty->_cache['tag_stack'][] = array('{$tag}', {$_params}); \$_block_repeat=true; echo \$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]->{$function[1]}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>";
} else { } else {
$output = "<?php \$_smarty_tpl->smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; echo {$function[0]}::{$function[1]}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; $output = "<?php \$_smarty_tpl->smarty->_cache['tag_stack'][] = array('{$tag}', {$_params}); \$_block_repeat=true; echo {$function[0]}::{$function[1]}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>";
} }
} else { } else {
// must endblock be nocache? // must endblock be nocache?
@ -95,14 +95,22 @@ class Smarty_Internal_Compile_Private_Registered_Block extends Smarty_Internal_C
$mod_pre = $mod_post = ''; $mod_pre = $mod_post = '';
} else { } else {
$mod_pre = ' ob_start(); '; $mod_pre = ' ob_start(); ';
$mod_post = 'echo ' . $compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifier_list'], 'value' => 'ob_get_clean()')) . ';'; $mod_post = 'echo ' .
$compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifier_list'],
'value' => 'ob_get_clean()')) . ';';
} }
if (!is_array($function)) { if (!is_array($function)) {
$output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre . " echo {$function}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat);" . $mod_post . " } array_pop(\$_smarty_tpl->smarty->_tag_stack);?>"; $output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre .
" echo {$function}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat);" . $mod_post .
" } array_pop(\$_smarty_tpl->smarty->_cache['tag_stack']);?>";
} elseif (is_object($function[0])) { } elseif (is_object($function[0])) {
$output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre . " echo \$_smarty_tpl->smarty->registered_plugins['block']['{$base_tag}'][0][0]->{$function[1]}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " . $mod_post . "} array_pop(\$_smarty_tpl->smarty->_tag_stack);?>"; $output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre .
" echo \$_smarty_tpl->smarty->registered_plugins['block']['{$base_tag}'][0][0]->{$function[1]}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " .
$mod_post . "} array_pop(\$_smarty_tpl->smarty->_cache['tag_stack']);?>";
} else { } else {
$output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre . " echo {$function[0]}::{$function[1]}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " . $mod_post . "} array_pop(\$_smarty_tpl->smarty->_tag_stack);?>"; $output = "<?php \$_block_content = ob_get_clean(); \$_block_repeat=false;" . $mod_pre .
" echo {$function[0]}::{$function[1]}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); " .
$mod_post . "} array_pop(\$_smarty_tpl->smarty->_cache['tag_stack']);?>";
} }
} }

@ -28,13 +28,13 @@ class Smarty_Internal_Compile_Private_Registered_Function extends Smarty_Interna
* Compiles code for the execution of a registered function * Compiles code for the execution of a registered function
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of function * @param string $tag name of function
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter, $tag) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter, $tag)
{ {
// This tag does create output // This tag does create output
$compiler->has_output = true; $compiler->has_output = true;

@ -20,40 +20,55 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C
* Compiles code for the special $smarty variables * Compiles code for the special $smarty variables
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param $parameter * @param $parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2)); $_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2));
$compiled_ref = ' '; $variable = strtolower($compiler->getId($_index[ 0 ]));
$variable = trim($_index[0], "'"); if ($variable === false) {
$compiler->trigger_template_error("special \$Smarty variable name index can not be variable", null, true);
}
if (!isset($compiler->smarty->security_policy) ||
$compiler->smarty->security_policy->isTrustedSpecialSmartyVar($variable, $compiler)
) {
switch ($variable) { switch ($variable) {
case 'foreach': case 'foreach':
return "\$_smarty_tpl->getVariable('smarty')->value$parameter";
case 'section': case 'section':
return "\$_smarty_tpl->getVariable('smarty')->value$parameter"; if (!isset($compiler->_tag_objects[ $variable ])) {
$class = 'Smarty_Internal_Compile_' . ucfirst($variable);
$compiler->_tag_objects[ $variable ] = new $class;
}
return $compiler->_tag_objects[ $variable ]->compileSpecialVariable(array(), $compiler, $_index);
case 'capture': case 'capture':
return "Smarty::\$_smarty_vars$parameter"; if (class_exists('Smarty_Internal_Compile_Capture')) {
return Smarty_Internal_Compile_Capture::compileSpecialVariable(array(), $compiler, $_index);
}
return '';
case 'now': case 'now':
return 'time()'; return 'time()';
case 'cookies': case 'cookies':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { if (isset($compiler->smarty->security_policy) &&
!$compiler->smarty->security_policy->allow_super_globals
) {
$compiler->trigger_template_error("(secure mode) super globals not permitted"); $compiler->trigger_template_error("(secure mode) super globals not permitted");
break; break;
} }
$compiled_ref = '$_COOKIE'; $compiled_ref = '$_COOKIE';
break; break;
case 'get': case 'get':
case 'post': case 'post':
case 'env': case 'env':
case 'server': case 'server':
case 'session': case 'session':
case 'request': case 'request':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { if (isset($compiler->smarty->security_policy) &&
!$compiler->smarty->security_policy->allow_super_globals
) {
$compiler->trigger_template_error("(secure mode) super globals not permitted"); $compiler->trigger_template_error("(secure mode) super globals not permitted");
break; break;
} }
@ -70,36 +85,33 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C
return 'dirname($_smarty_tpl->source->filepath)'; return 'dirname($_smarty_tpl->source->filepath)';
case 'version': case 'version':
$_version = Smarty::SMARTY_VERSION; return "Smarty::SMARTY_VERSION";
return "'$_version'";
case 'const': case 'const':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_constants) { if (isset($compiler->smarty->security_policy) &&
!$compiler->smarty->security_policy->allow_constants
) {
$compiler->trigger_template_error("(secure mode) constants not permitted"); $compiler->trigger_template_error("(secure mode) constants not permitted");
break; break;
} }
if (strpos($_index[ 1 ], '$') === false && strpos($_index[ 1 ], '\'') === false) {
return "@constant('{$_index[1]}')";
} else {
return "@constant({$_index[1]})"; return "@constant({$_index[1]})";
}
case 'config': case 'config':
if (isset($_index[ 2 ])) { if (isset($_index[ 2 ])) {
return "(is_array(\$tmp = \$_smarty_tpl->getConfigVariable($_index[1])) ? \$tmp[$_index[2]] : null)"; return "(is_array(\$tmp = \$_smarty_tpl->smarty->ext->configload->_getConfigVariable(\$_smarty_tpl, $_index[1])) ? \$tmp[$_index[2]] : null)";
} else { } else {
return "\$_smarty_tpl->getConfigVariable($_index[1])"; return "\$_smarty_tpl->smarty->ext->configload->_getConfigVariable(\$_smarty_tpl, $_index[1])";
} }
case 'ldelim': case 'ldelim':
$_ldelim = $compiler->smarty->left_delimiter; return "\$_smarty_tpl->smarty->left_delimiter";
return "'$_ldelim'";
case 'rdelim': case 'rdelim':
$_rdelim = $compiler->smarty->right_delimiter; return "\$_smarty_tpl->smarty->right_delimiter";
return "'$_rdelim'";
default: default:
$compiler->trigger_template_error('$smarty.' . trim($_index[0], "'") . ' is invalid'); $compiler->trigger_template_error('$smarty.' . trim($_index[ 0 ], "'") . ' is not defined');
break; break;
} }
if (isset($_index[ 1 ])) { if (isset($_index[ 1 ])) {
@ -108,7 +120,7 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C
$compiled_ref = $compiled_ref . "[$_ind]"; $compiled_ref = $compiled_ref . "[$_ind]";
} }
} }
return $compiled_ref; return $compiled_ref;
} }
} }
}

@ -25,11 +25,11 @@ class Smarty_Internal_Compile_Rdelim extends Smarty_Internal_CompileBase
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) { if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); $compiler->trigger_template_error('nocache option not allowed', null, true);
} }
// this tag does not return compiled code // this tag does not return compiled code
$compiler->has_code = true; $compiler->has_code = true;

@ -14,7 +14,7 @@
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class Smarty_Internal_Compile_Section extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Section extends Smarty_Internal_Compile_Private_ForeachSection
{ {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Section extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $required_attributes = array('name', 'loop'); public $required_attributes = array('name', 'loop');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -30,6 +31,7 @@ class Smarty_Internal_Compile_Section extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('name', 'loop'); public $shorttag_order = array('name', 'loop');
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
@ -38,103 +40,343 @@ class Smarty_Internal_Compile_Section extends Smarty_Internal_CompileBase
*/ */
public $optional_attributes = array('start', 'step', 'max', 'show'); public $optional_attributes = array('start', 'step', 'max', 'show');
/**
* counter
*
* @var int
*/
public $counter = 0;
/**
* Name of this tag
*
* @var string
*/
public $tagName = 'section';
/**
* Valid properties of $smarty.section.name.xxx variable
*
* @var array
*/
public $nameProperties = array('first', 'last', 'index', 'iteration', 'show', 'total', 'rownum',
'index_prev', 'index_next');
/**
* {section} tag has no item properties
*
* @var array
*/
public $itemProperties = null;
/**
* {section} tag has always name attribute
*
* @var bool
*/
public $isNamed = true;
/** /**
* Compiles code for the {section} tag * Compiles code for the {section} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$compiler->loopNesting++;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
$attributes = array('name' => $compiler->getId($_attr['name']));
$this->openTag($compiler, 'section', array('section', $compiler->nocache)); unset($_attr['name']);
foreach ($attributes as $a => $v) {
if ($v === false) {
$compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true);
}
}
$local = "\$__section_{$attributes['name']}_" . $this->counter ++ . '_';
$sectionVar = "\$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}']";
$this->openTag($compiler, 'section', array('section', $compiler->nocache, $local, $sectionVar));
// maybe nocache because of nocache variables // maybe nocache because of nocache variables
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$output = "<?php "; $initLocal = array('saved' => "isset(\$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}']) ? \$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}'] : false",);
$initNamedProperty = array();
$section_name = $_attr['name']; $initFor = array();
$incFor = array();
$output .= "if (isset(\$_smarty_tpl->tpl_vars['smarty']->value['section'][$section_name])) unset(\$_smarty_tpl->tpl_vars['smarty']->value['section'][$section_name]);\n"; $cmpFor = array();
$section_props = "\$_smarty_tpl->tpl_vars['smarty']->value['section'][$section_name]"; $propValue = array('index' => "{$sectionVar}->value['index']", 'show' => 'true', 'step' => 1,
'iteration' => "{$local}iteration",
);
$propType = array('index' => 2, 'iteration' => 2, 'show' => 0, 'step' => 0,);
// search for used tag attributes
$this->scanForProperties($attributes, $compiler);
if (!empty($this->matchResults['named'])) {
$namedAttr = $this->matchResults['named'];
}
$namedAttr['index'] = true;
$output = "<?php\n";
foreach ($_attr as $attr_name => $attr_value) { foreach ($_attr as $attr_name => $attr_value) {
switch ($attr_name) { switch ($attr_name) {
case 'loop': case 'loop':
$output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int) \$_loop); unset(\$_loop);\n"; if (is_numeric($attr_value)) {
$v = (int) $attr_value;
$t = 0;
} else {
$v = "(is_array(@\$_loop=$attr_value) ? count(\$_loop) : max(0, (int) \$_loop))";
$t = 1;
}
if (isset($namedAttr['loop'])) {
$initNamedProperty['loop'] = "'loop' => {$v}";
if ($t == 1) {
$v = "{$sectionVar}->value['loop']";
}
} elseif ($t == 1) {
$initLocal['loop'] = $v;
$v = "{$local}loop";
}
break; break;
case 'show': case 'show':
if (is_bool($attr_value)) { if (is_bool($attr_value)) {
$show_attr_value = $attr_value ? 'true' : 'false'; $v = $attr_value ? 'true' : 'false';
$t = 0;
} else { } else {
$show_attr_value = "(bool) $attr_value"; $v = "(bool) $attr_value";
$t = 3;
} }
$output .= "{$section_props}['show'] = $show_attr_value;\n";
break; break;
case 'step':
case 'name': if (is_numeric($attr_value)) {
$output .= "{$section_props}['$attr_name'] = $attr_value;\n"; $v = (int) $attr_value;
$v = ($v == 0) ? 1 : $v;
$t = 0;
break;
}
$initLocal['step'] = "((int)@$attr_value) == 0 ? 1 : (int)@$attr_value";
$v = "{$local}step";
$t = 2;
break; break;
case 'max': case 'max':
case 'start': case 'start':
$output .= "{$section_props}['$attr_name'] = (int) $attr_value;\n"; if (is_numeric($attr_value)) {
$v = (int) $attr_value;
$t = 0;
break; break;
}
case 'step': $v = "(int)@$attr_value";
$output .= "{$section_props}['$attr_name'] = ((int) $attr_value) == 0 ? 1 : (int) $attr_value;\n"; $t = 3;
break; break;
} }
if ($t == 3 && $compiler->getId($attr_value)) {
$t = 1;
} }
$propValue[$attr_name] = $v;
if (!isset($_attr['show'])) { $propType[$attr_name] = $t;
$output .= "{$section_props}['show'] = true;\n";
} }
if (!isset($_attr['loop'])) { if (isset($namedAttr['step'])) {
$output .= "{$section_props}['loop'] = 1;\n"; $initNamedProperty['step'] = $propValue['step'];
}
if (isset($namedAttr['iteration'])) {
$propValue['iteration'] = "{$sectionVar}->value['iteration']";
} }
$incFor['iteration'] = "{$propValue['iteration']}++";
$initFor['iteration'] = "{$propValue['iteration']} = 1";
if (!isset($_attr['max'])) { if ($propType['step'] == 0) {
$output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; if ($propValue['step'] == 1) {
$incFor['index'] = "{$sectionVar}->value['index']++";
} elseif ($propValue['step'] > 1) {
$incFor['index'] = "{$sectionVar}->value['index'] += {$propValue['step']}";
} else {
$incFor['index'] = "{$sectionVar}->value['index'] -= " . - $propValue['step'];
}
} else { } else {
$output .= "if ({$section_props}['max'] < 0)\n" . " {$section_props}['max'] = {$section_props}['loop'];\n"; $incFor['index'] = "{$sectionVar}->value['index'] += {$propValue['step']}";
} }
if (!isset($_attr['step'])) { if (!isset($propValue['max'])) {
$output .= "{$section_props}['step'] = 1;\n"; $propValue['max'] = $propValue['loop'];
$propType['max'] = $propType['loop'];
} elseif ($propType['max'] != 0) {
$propValue['max'] = "{$propValue['max']} < 0 ? {$propValue['loop']} : {$propValue['max']}";
$propType['max'] = 1;
} else {
if ($propValue['max'] < 0) {
$propValue['max'] = $propValue['loop'];
$propType['max'] = $propType['loop'];
}
} }
if (!isset($_attr['start'])) { if (!isset($propValue['start'])) {
$output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n"; $start_code = array(1 => "{$propValue['step']} > 0 ? ", 2 => '0', 3 => ' : ', 4 => $propValue['loop'],
5 => ' - 1');
if ($propType['loop'] == 0) {
$start_code[5] = '';
$start_code[4] = $propValue['loop'] - 1;
}
if ($propType['step'] == 0) {
if ($propValue['step'] > 0) {
$start_code = array(1 => '0');
$propType['start'] = 0;
} else {
$start_code[1] = $start_code[2] = $start_code[3] = '';
$propType['start'] = $propType['loop'];
}
} else {
$propType['start'] = 1;
}
$propValue['start'] = join('', $start_code);
} else {
$start_code = array(1 => "{$propValue['start']} < 0 ? ", 2 => 'max(', 3 => "{$propValue['step']} > 0 ? ",
4 => '0', 5 => ' : ', 6 => '-1', 7 => ', ',
8 => "{$propValue['start']} + {$propValue['loop']}", 10 => ')', 11 => ' : ',
12 => 'min(', 13 => $propValue['start'], 14 => ', ',
15 => "{$propValue['step']} > 0 ? ", 16 => $propValue['loop'], 17 => ' : ',
18 => $propType['loop'] == 0 ? $propValue['loop'] - 1 : "{$propValue['loop']} - 1",
19 => ')');
if ($propType['step'] == 0) {
$start_code[3] = $start_code[5] = $start_code[15] = $start_code[17] = '';
if ($propValue['step'] > 0) {
$start_code[6] = $start_code[18] = '';
} else {
$start_code[4] = $start_code[16] = '';
}
}
if ($propType['start'] == 0) {
if ($propType['loop'] == 0) {
$start_code[8] = $propValue['start'] + $propValue['loop'];
}
$propType['start'] = $propType['step'] + $propType['loop'];
$start_code[1] = '';
if ($propValue['start'] < 0) {
for ($i = 11; $i <= 19; $i ++) {
$start_code[$i] = '';
}
if ($propType['start'] == 0) {
$start_code = array(max($propValue['step'] > 0 ? 0 : - 1, $propValue['start'] +
$propValue['loop']));
}
} else { } else {
$output .= "if ({$section_props}['start'] < 0)\n" . " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" . "else\n" . " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n"; for ($i = 1; $i <= 11; $i ++) {
$start_code[$i] = '';
} }
if ($propType['start'] == 0) {
$start_code = array(min($propValue['step'] > 0 ? $propValue['loop'] : $propValue['loop'] -
1, $propValue['start']));
}
}
}
$propValue['start'] = join('', $start_code);
}
if ($propType['start'] != 0) {
$initLocal['start'] = $propValue['start'];
$propValue['start'] = "{$local}start";
}
$initFor['index'] = "{$sectionVar}->value['index'] = {$propValue['start']}";
$output .= "if ({$section_props}['show']) {\n";
if (!isset($_attr['start']) && !isset($_attr['step']) && !isset($_attr['max'])) { if (!isset($_attr['start']) && !isset($_attr['step']) && !isset($_attr['max'])) {
$output .= " {$section_props}['total'] = {$section_props}['loop'];\n"; $propValue['total'] = $propValue['loop'];
$propType['total'] = $propType['loop'];
} else {
$propType['total'] = $propType['start'] + $propType['loop'] + $propType['step'] + $propType['max'];
if ($propType['total'] == 0) {
$propValue['total'] = min(ceil(($propValue['step'] > 0 ? $propValue['loop'] -
$propValue['start'] : (int) $propValue['start'] + 1) /
abs($propValue['step'])), $propValue['max']);
} else {
$total_code = array(1 => 'min(', 2 => 'ceil(', 3 => '(', 4 => "{$propValue['step']} > 0 ? ",
5 => $propValue['loop'], 6 => ' - ', 7 => $propValue['start'], 8 => ' : ',
9 => $propValue['start'], 10 => '+ 1', 11 => ')', 12 => '/ ', 13 => 'abs(',
14 => $propValue['step'], 15 => ')', 16 => ')', 17 => ", {$propValue['max']})",);
if (!isset($propValue['max'])) {
$total_code[1] = $total_code[17] = '';
}
if ($propType['loop'] + $propType['start'] == 0) {
$total_code[5] = $propValue['loop'] - $propValue['start'];
$total_code[6] = $total_code[7] = '';
}
if ($propType['start'] == 0) {
$total_code[9] = (int) $propValue['start'] + 1;
$total_code[10] = '';
}
if ($propType['step'] == 0) {
$total_code[13] = $total_code[15] = '';
if ($propValue['step'] == 1 || $propValue['step'] == - 1) {
$total_code[2] = $total_code[12] = $total_code[14] = $total_code[16] = '';
} elseif ($propValue['step'] < 0) {
$total_code[14] = - $propValue['step'];
}
$total_code[4] = '';
if ($propValue['step'] > 0) {
$total_code[8] = $total_code[9] = $total_code[10] = '';
} else { } else {
$output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n"; $total_code[5] = $total_code[6] = $total_code[7] = $total_code[8] = '';
}
}
$propValue['total'] = join('', $total_code);
}
}
if (isset($namedAttr['total'])) {
$initNamedProperty['total'] = "'total' => {$propValue['total']}";
if ($propType['total'] > 0) {
$propValue['total'] = "{$sectionVar}->value['total']";
}
} elseif ($propType['total'] > 0) {
$initLocal['total'] = $propValue['total'];
$propValue['total'] = "{$local}total";
} }
$output .= " if ({$section_props}['total'] == 0)\n" . " {$section_props}['show'] = false;\n" . "} else\n" . " {$section_props}['total'] = 0;\n";
$output .= "if ({$section_props}['show']):\n"; $cmpFor['iteration'] = "{$propValue['iteration']} <= {$propValue['total']}";
$output .= "
for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
{$section_props}['iteration'] <= {$section_props}['total'];
{$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
$output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
$output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
$output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
$output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n";
$output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n";
foreach ($initLocal as $key => $code) {
$output .= "{$local}{$key} = {$code};\n";
}
$_vars = 'array(' . join(', ', $initNamedProperty) . ')';
$output .= "{$sectionVar} = new Smarty_Variable({$_vars});\n";
$cond_code = "{$propValue['total']} != 0";
if ($propType['total'] == 0) {
if ($propValue['total'] == 0) {
$cond_code = 'false';
} else {
$cond_code = 'true';
}
}
if ($propType['show'] > 0) {
$output .= "{$local}show = {$propValue['show']} ? {$cond_code} : false;\n";
$output .= "if ({$local}show) {\n";
} elseif ($propValue['show'] == 'true') {
$output .= "if ({$cond_code}) {\n";
} else {
$output .= "if (false) {\n";
}
$jinit = join(', ', $initFor);
$jcmp = join(', ', $cmpFor);
$jinc = join(', ', $incFor);
$output .= "for ({$jinit}; {$jcmp}; {$jinc}){\n";
if (isset($namedAttr['rownum'])) {
$output .= "{$sectionVar}->value['rownum'] = {$propValue['iteration']};\n";
}
if (isset($namedAttr['index_prev'])) {
$output .= "{$sectionVar}->value['index_prev'] = {$propValue['index']} - {$propValue['step']};\n";
}
if (isset($namedAttr['index_next'])) {
$output .= "{$sectionVar}->value['index_next'] = {$propValue['index']} + {$propValue['step']};\n";
}
if (isset($namedAttr['first'])) {
$output .= "{$sectionVar}->value['first'] = ({$propValue['iteration']} == 1);\n";
}
if (isset($namedAttr['last'])) {
$output .= "{$sectionVar}->value['last'] = ({$propValue['iteration']} == {$propValue['total']});\n";
}
$output .= "?>"; $output .= "?>";
return $output; return $output;
@ -153,19 +395,19 @@ class Smarty_Internal_Compile_Sectionelse extends Smarty_Internal_CompileBase
* Compiles code for the {sectionelse} tag * Compiles code for the {sectionelse} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
list($openTag, $nocache) = $this->closeTag($compiler, array('section')); list($openTag, $nocache, $local, $sectionVar) = $this->closeTag($compiler, array('section'));
$this->openTag($compiler, 'sectionelse', array('sectionelse', $nocache)); $this->openTag($compiler, 'sectionelse', array('sectionelse', $nocache, $local, $sectionVar));
return "<?php endfor; else: ?>"; return "<?php }} else {\n ?>";
} }
} }
@ -181,26 +423,32 @@ class Smarty_Internal_Compile_Sectionclose extends Smarty_Internal_CompileBase
* Compiles code for the {/section} tag * Compiles code for the {/section} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
// check and get attributes $compiler->loopNesting--;
$_attr = $this->getAttributes($compiler, $args);
// must endblock be nocache? // must endblock be nocache?
if ($compiler->nocache) { if ($compiler->nocache) {
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
} }
list($openTag, $compiler->nocache) = $this->closeTag($compiler, array('section', 'sectionelse')); list($openTag, $compiler->nocache, $local, $sectionVar) = $this->closeTag($compiler, array('section',
'sectionelse'));
$output = "<?php\n";
if ($openTag == 'sectionelse') { if ($openTag == 'sectionelse') {
return "<?php endif; ?>"; $output .= "}\n";
} else { } else {
return "<?php endfor; endif; ?>"; $output .= "}\n}\n";
} }
$output .= "if ({$local}saved) {\n";
$output .= "{$sectionVar} = {$local}saved;\n";
$output .= "}\n";
$output .= "?>";
return $output;
} }
} }

@ -25,10 +25,10 @@ class Smarty_Internal_Compile_Setfilter extends Smarty_Internal_CompileBase
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$compiler->variable_filter_stack[] = $compiler->template->variable_filters; $compiler->variable_filter_stack[] = $compiler->variable_filters;
$compiler->template->variable_filters = $parameter['modifier_list']; $compiler->variable_filters = $parameter['modifier_list'];
// this tag does not return compiled code // this tag does not return compiled code
$compiler->has_code = false; $compiler->has_code = false;
@ -53,14 +53,14 @@ class Smarty_Internal_Compile_Setfilterclose extends Smarty_Internal_CompileBase
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
// reset variable filter to previous state // reset variable filter to previous state
if (count($compiler->variable_filter_stack)) { if (count($compiler->variable_filter_stack)) {
$compiler->template->variable_filters = array_pop($compiler->variable_filter_stack); $compiler->variable_filters = array_pop($compiler->variable_filter_stack);
} else { } else {
$compiler->template->variable_filters = array(); $compiler->variable_filters = array();
} }
// this tag does not return compiled code // this tag does not return compiled code
$compiler->has_code = false; $compiler->has_code = false;

@ -0,0 +1,46 @@
<?php
/**
* Smarty Internal Plugin Compile Shared Inheritance
* Shared methods for {extends} and {block} tags
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile Shared Inheritance Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Shared_Inheritance extends Smarty_Internal_CompileBase
{
/**
* Register post compile callback to compile inheritance initialization code
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param bool|false $initChildSequence if true force child template
*/
public function registerInit(Smarty_Internal_TemplateCompilerBase $compiler, $initChildSequence = false)
{
if ($initChildSequence || !isset($compiler->_cache['inheritanceInit'])) {
$compiler->registerPostCompileCallback(array('Smarty_Internal_Compile_Shared_Inheritance', 'postCompile'),
array($initChildSequence), 'inheritanceInit', $initChildSequence);
$compiler->_cache['inheritanceInit'] = true;
}
}
/**
* Compile inheritance initialization code as prefix
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param bool|false $initChildSequence if true force child template
*/
static function postCompile(Smarty_Internal_TemplateCompilerBase $compiler, $initChildSequence = false)
{
$compiler->prefixCompiledCode .= "<?php \$_smarty_tpl->ext->_inheritance->init(\$_smarty_tpl, " .
var_export($initChildSequence, true) . ");\n?>\n";
}
}

@ -20,47 +20,62 @@ class Smarty_Internal_Compile_While extends Smarty_Internal_CompileBase
* Compiles code for the {while} tag * Compiles code for the {while} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return string compiled code
* @throws \SmartyCompilerException
*/ */
public function compile($args, $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
$compiler->loopNesting++;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
$this->openTag($compiler, 'while', $compiler->nocache); $this->openTag($compiler, 'while', $compiler->nocache);
if (!array_key_exists("if condition", $parameter)) { if (!array_key_exists("if condition", $parameter)) {
$compiler->trigger_template_error("missing while condition", $compiler->lex->taglineno); $compiler->trigger_template_error("missing while condition", null, true);
} }
// maybe nocache because of nocache variables // maybe nocache because of nocache variables
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache; $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$_output = "<?php\n";
if (is_array($parameter['if condition'])) { if (is_array($parameter['if condition'])) {
if ($compiler->nocache) { if ($compiler->nocache) {
$_nocache = ',true'; $_nocache = ',true';
// create nocache var to make it know for further compiling // create nocache var to make it know for further compiling
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true); $var = trim($parameter['if condition']['var']['var'], "'");
} else { } else {
$compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true); $var = trim($parameter['if condition']['var'], "'");
}
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
} }
} else { } else {
$_nocache = ''; $_nocache = '';
} }
if (is_array($parameter['if condition']['var'])) { if (is_array($parameter['if condition']['var'])) {
$_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output .= "if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] .
$_output .= "while (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . $parameter['if condition']['value'] . ") {?>"; "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] .
"]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " . $parameter['if condition']['var']['var'] .
"$_nocache);\n";
$_output .= "while (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" .
$parameter['if condition']['var']['smarty_internal_index'] . " = " .
$parameter['if condition']['value'] . ") {?>";
} else { } else {
$_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});"; $_output .= "if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] .
$_output .= "while (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " . $parameter['if condition']['value'] . ") {?>"; "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] .
"] = new Smarty_Variable(null{$_nocache});";
$_output .= "while (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " .
$parameter['if condition']['value'] . ") {?>";
} }
return $_output;
} else { } else {
return "<?php while ({$parameter['if condition']}) {?>"; $_output .= "while ({$parameter['if condition']}) {?>";
} }
return $_output;
} }
} }
@ -76,18 +91,18 @@ class Smarty_Internal_Compile_Whileclose extends Smarty_Internal_CompileBase
* Compiles code for the {/while} tag * Compiles code for the {/while} tag
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param object $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* *
* @return string compiled code * @return string compiled code
*/ */
public function compile($args, $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$compiler->loopNesting--;
// must endblock be nocache? // must endblock be nocache?
if ($compiler->nocache) { if ($compiler->nocache) {
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
} }
$compiler->nocache = $this->closeTag($compiler, array('while')); $compiler->nocache = $this->closeTag($compiler, array('while'));
return "<?php }?>\n";
return "<?php }?>";
} }
} }

@ -21,6 +21,7 @@ abstract class Smarty_Internal_CompileBase
* @var array * @var array
*/ */
public $required_attributes = array(); public $required_attributes = array();
/** /**
* Array of names of optional attribute required by tag * Array of names of optional attribute required by tag
* use array('_any') if there is no restriction of attributes names * use array('_any') if there is no restriction of attributes names
@ -28,12 +29,14 @@ abstract class Smarty_Internal_CompileBase
* @var array * @var array
*/ */
public $optional_attributes = array(); public $optional_attributes = array();
/** /**
* Shorttag attribute order defined by its names * Shorttag attribute order defined by its names
* *
* @var array * @var array
*/ */
public $shorttag_order = array(); public $shorttag_order = array();
/** /**
* Array of names of valid option flags * Array of names of valid option flags
* *
@ -68,7 +71,7 @@ abstract class Smarty_Internal_CompileBase
$_indexed_attr[$this->shorttag_order[$key]] = $mixed; $_indexed_attr[$this->shorttag_order[$key]] = $mixed;
} else { } else {
// too many shorthands // too many shorthands
$compiler->trigger_template_error('too many shorthand attributes', $compiler->lex->taglineno); $compiler->trigger_template_error('too many shorthand attributes', null, true);
} }
// named attribute // named attribute
} else { } else {
@ -90,7 +93,7 @@ abstract class Smarty_Internal_CompileBase
$_indexed_attr[$kv['key']] = false; $_indexed_attr[$kv['key']] = false;
} }
} else { } else {
$compiler->trigger_template_error("illegal value of option flag \"{$kv['key']}\"", $compiler->lex->taglineno); $compiler->trigger_template_error("illegal value of option flag \"{$kv['key']}\"", null, true);
} }
// must be named attribute // must be named attribute
} else { } else {
@ -102,7 +105,7 @@ abstract class Smarty_Internal_CompileBase
// check if all required attributes present // check if all required attributes present
foreach ($this->required_attributes as $attr) { foreach ($this->required_attributes as $attr) {
if (!array_key_exists($attr, $_indexed_attr)) { if (!array_key_exists($attr, $_indexed_attr)) {
$compiler->trigger_template_error("missing \"" . $attr . "\" attribute", $compiler->lex->taglineno); $compiler->trigger_template_error("missing \"" . $attr . "\" attribute", null, true);
} }
} }
// check for not allowed attributes // check for not allowed attributes
@ -110,7 +113,7 @@ abstract class Smarty_Internal_CompileBase
$tmp_array = array_merge($this->required_attributes, $this->optional_attributes, $this->option_flags); $tmp_array = array_merge($this->required_attributes, $this->optional_attributes, $this->option_flags);
foreach ($_indexed_attr as $key => $dummy) { foreach ($_indexed_attr as $key => $dummy) {
if (!in_array($key, $tmp_array) && $key !== 0) { if (!in_array($key, $tmp_array) && $key !== 0) {
$compiler->trigger_template_error("unexpected \"" . $key . "\" attribute", $compiler->lex->taglineno); $compiler->trigger_template_error("unexpected \"" . $key . "\" attribute", null, true);
} }
} }
} }
@ -162,12 +165,13 @@ abstract class Smarty_Internal_CompileBase
} }
} }
// wrong nesting of tags // wrong nesting of tags
$compiler->trigger_template_error("unclosed {$compiler->smarty->left_delimiter}" . $_openTag . "{$compiler->smarty->right_delimiter} tag"); $compiler->trigger_template_error("unclosed {$compiler->smarty->left_delimiter}" . $_openTag .
"{$compiler->smarty->right_delimiter} tag");
return; return;
} }
// wrong nesting of tags // wrong nesting of tags
$compiler->trigger_template_error("unexpected closing tag", $compiler->lex->taglineno); $compiler->trigger_template_error("unexpected closing tag", null, true);
return; return;
} }

@ -1,306 +0,0 @@
<?php
/**
* Smarty Internal Plugin Config
*
* @package Smarty
* @subpackage Config
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Config
* Main class for config variables
*
* @package Smarty
* @subpackage Config
* @ignore
*/
class Smarty_Internal_Config
{
/**
* Smarty instance
*
* @var Smarty object
*/
public $smarty = null;
/**
* Object of config var storage
*
* @var object
*/
public $data = null;
/**
* Config resource
*
* @var string
*/
public $config_resource = null;
/**
* Compiled config file
*
* @var string
*/
public $compiled_config = null;
/**
* filepath of compiled config file
*
* @var string
*/
public $compiled_filepath = null;
/**
* Filemtime of compiled config Filemtime
*
* @var int
*/
public $compiled_timestamp = null;
/**
* flag if compiled config file is invalid and must be (re)compiled
*
* @var bool
*/
public $mustCompile = null;
/**
* Config file compiler object
*
* @var Smarty_Internal_Config_File_Compiler object
*/
public $compiler_object = null;
/**
* Constructor of config file object
*
* @param string $config_resource config file resource name
* @param Smarty $smarty Smarty instance
* @param object $data object for config vars storage
*/
public function __construct($config_resource, $smarty, $data = null)
{
$this->data = $data;
$this->smarty = $smarty;
$this->config_resource = $config_resource;
}
/**
* Returns the compiled filepath
*
* @return string the compiled filepath
*/
public function getCompiledFilepath()
{
return $this->compiled_filepath === null ?
($this->compiled_filepath = $this->buildCompiledFilepath()) :
$this->compiled_filepath;
}
/**
* Get file path.
*
* @return string
*/
public function buildCompiledFilepath()
{
$_compile_id = isset($this->smarty->compile_id) ? preg_replace('![^\w\|]+!', '_', $this->smarty->compile_id) : null;
$_flag = (int) $this->smarty->config_read_hidden + (int) $this->smarty->config_booleanize * 2
+ (int) $this->smarty->config_overwrite * 4;
$_filepath = sha1(realpath($this->source->filepath) . $_flag);
// if use_sub_dirs, break file into directories
if ($this->smarty->use_sub_dirs) {
$_filepath = substr($_filepath, 0, 2) . DS
. substr($_filepath, 2, 2) . DS
. substr($_filepath, 4, 2) . DS
. $_filepath;
}
$_compile_dir_sep = $this->smarty->use_sub_dirs ? DS : '^';
if (isset($_compile_id)) {
$_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
}
$_compile_dir = $this->smarty->getCompileDir();
return $_compile_dir . $_filepath . '.' . basename($this->source->name) . '.config' . '.php';
}
/**
* Returns the timestamp of the compiled file
*
* @return integer the file timestamp
*/
public function getCompiledTimestamp()
{
return $this->compiled_timestamp === null
? ($this->compiled_timestamp = (file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false)
: $this->compiled_timestamp;
}
/**
* Returns if the current config file must be compiled
* It does compare the timestamps of config source and the compiled config and checks the force compile configuration
*
* @return boolean true if the file must be compiled
*/
public function mustCompile()
{
return $this->mustCompile === null ?
$this->mustCompile = ($this->smarty->force_compile || $this->getCompiledTimestamp() === false || $this->smarty->compile_check && $this->getCompiledTimestamp() < $this->source->timestamp) :
$this->mustCompile;
}
/**
* Returns the compiled config file
* It checks if the config file must be compiled or just read the compiled version
*
* @return string the compiled config file
*/
public function getCompiledConfig()
{
if ($this->compiled_config === null) {
// see if template needs compiling.
if ($this->mustCompile()) {
$this->compileConfigSource();
} else {
$this->compiled_config = file_get_contents($this->getCompiledFilepath());
}
}
return $this->compiled_config;
}
/**
* Compiles the config files
*
* @throws Exception
*/
public function compileConfigSource()
{
// compile template
if (!is_object($this->compiler_object)) {
// load compiler
$this->compiler_object = new Smarty_Internal_Config_File_Compiler($this->smarty);
}
// compile locking
if ($this->smarty->compile_locking) {
if ($saved_timestamp = $this->getCompiledTimestamp()) {
touch($this->getCompiledFilepath());
}
}
// call compiler
try {
$this->compiler_object->compileSource($this);
}
catch (Exception $e) {
// restore old timestamp in case of error
if ($this->smarty->compile_locking && $saved_timestamp) {
touch($this->getCompiledFilepath(), $saved_timestamp);
}
throw $e;
}
// compiling succeeded
// write compiled template
Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->getCompiledConfig(), $this->smarty);
}
/**
* load config variables
*
* @param mixed $sections array of section names, single section or null
* @param string $scope global,parent or local
*
* @throws Exception
*/
public function loadConfigVars($sections = null, $scope = 'local')
{
if ($this->data instanceof Smarty_Internal_Template) {
$this->data->properties['file_dependency'][sha1($this->source->filepath)] = array($this->source->filepath, $this->source->timestamp, 'file');
}
if ($this->mustCompile()) {
$this->compileConfigSource();
}
// pointer to scope
if ($scope == 'local') {
$scope_ptr = $this->data;
} elseif ($scope == 'parent') {
if (isset($this->data->parent)) {
$scope_ptr = $this->data->parent;
} else {
$scope_ptr = $this->data;
}
} elseif ($scope == 'root' || $scope == 'global') {
$scope_ptr = $this->data;
while (isset($scope_ptr->parent)) {
$scope_ptr = $scope_ptr->parent;
}
}
$_config_vars = array();
include($this->getCompiledFilepath());
// copy global config vars
foreach ($_config_vars['vars'] as $variable => $value) {
if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
// scan sections
if (!empty($sections)) {
foreach ((array) $sections as $this_section) {
if (isset($_config_vars['sections'][$this_section])) {
foreach ($_config_vars['sections'][$this_section]['vars'] as $variable => $value) {
if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
}
}
}
}
/**
* set Smarty property in template context
*
* @param string $property_name property name
* @param mixed $value value
*
* @throws SmartyException if $property_name is not valid
*/
public function __set($property_name, $value)
{
switch ($property_name) {
case 'source':
case 'compiled':
$this->$property_name = $value;
return;
}
throw new SmartyException("invalid config property '$property_name'.");
}
/**
* get Smarty property in template context
*
* @param string $property_name property name
*
* @return \Smarty_Config_Source|\Smarty_Template_Compiled
* @throws SmartyException if $property_name is not valid
*/
public function __get($property_name)
{
switch ($property_name) {
case 'source':
if (empty($this->config_resource)) {
throw new SmartyException("Unable to parse resource name \"{$this->config_resource}\"");
}
$this->source = Smarty_Resource::config($this);
return $this->source;
case 'compiled':
$this->compiled = $this->source->getCompiled($this);
return $this->compiled;
}
throw new SmartyException("config attribute '$property_name' does not exist.");
}
}

@ -17,6 +17,20 @@
*/ */
class Smarty_Internal_Config_File_Compiler class Smarty_Internal_Config_File_Compiler
{ {
/**
* Lexer class name
*
* @var string
*/
public $lexer_class;
/**
* Parser class name
*
* @var string
*/
public $parser_class;
/** /**
* Lexer object * Lexer object
* *
@ -41,9 +55,9 @@ class Smarty_Internal_Config_File_Compiler
/** /**
* Smarty object * Smarty object
* *
* @var Smarty_Internal_Config object * @var Smarty_Internal_Template object
*/ */
public $config; public $template;
/** /**
* Compiled config data sections and variables * Compiled config data sections and variables
@ -52,40 +66,53 @@ class Smarty_Internal_Config_File_Compiler
*/ */
public $config_data = array(); public $config_data = array();
/**
* compiled config data must always be written
*
* @var bool
*/
public $write_compiled_code = true;
/** /**
* Initialize compiler * Initialize compiler
* *
* @param Smarty $smarty base instance * @param string $lexer_class class name
* @param string $parser_class class name
* @param Smarty $smarty global instance
*/ */
public function __construct($smarty) public function __construct($lexer_class, $parser_class, Smarty $smarty)
{ {
$this->smarty = $smarty;
// get required plugins
$this->lexer_class = $lexer_class;
$this->parser_class = $parser_class;
$this->smarty = $smarty; $this->smarty = $smarty;
$this->config_data['sections'] = array(); $this->config_data['sections'] = array();
$this->config_data['vars'] = array(); $this->config_data['vars'] = array();
} }
/** /**
* Method to compile a Smarty template. * Method to compile Smarty config source.
* *
* @param Smarty_Internal_Config $config config object * @param Smarty_Internal_Template $template
* *
* @return bool true if compiling succeeded, false if it failed * @return bool true if compiling succeeded, false if it failed
*/ */
public function compileSource(Smarty_Internal_Config $config) public function compileTemplate(Smarty_Internal_Template $template)
{ {
/* here is where the compiling takes place. Smarty $this->template = $template;
tags in the templates are replaces with PHP code, $this->template->compiled->file_dependency[$this->template->source->uid] = array($this->template->source->filepath,
then written to compiled files. */ $this->template->source->getTimeStamp(),
$this->config = $config; $this->template->source->type);
// get config file source if ($this->smarty->debugging) {
$_content = $config->source->content . "\n"; $this->smarty->_debug->start_compile($this->template);
// on empty template just return
if ($_content == '') {
return true;
} }
// init the lexer/parser to compile the config file // init the lexer/parser to compile the config file
$lex = new Smarty_Internal_Configfilelexer($_content, $this); /* @var Smarty_Internal_ConfigFileLexer $lex */
$parser = new Smarty_Internal_Configfileparser($lex, $this); $lex = new $this->lexer_class(str_replace(array("\r\n", "\r"), "\n", $template->source->getContent()) .
"\n", $this);
/* @var Smarty_Internal_ConfigFileParser $parser */
$parser = new $this->parser_class($lex, $this);
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
$mbEncoding = mb_internal_encoding(); $mbEncoding = mb_internal_encoding();
@ -94,7 +121,6 @@ class Smarty_Internal_Config_File_Compiler
$mbEncoding = null; $mbEncoding = null;
} }
if ($this->smarty->_parserdebug) { if ($this->smarty->_parserdebug) {
$parser->PrintTrace(); $parser->PrintTrace();
} }
@ -111,8 +137,17 @@ class Smarty_Internal_Config_File_Compiler
if ($mbEncoding) { if ($mbEncoding) {
mb_internal_encoding($mbEncoding); mb_internal_encoding($mbEncoding);
} }
if ($this->smarty->debugging) {
$this->smarty->_debug->end_compile($this->template);
}
// template header code
$template_header = "<?php /* Smarty version " . Smarty::SMARTY_VERSION . ", created on " .
strftime("%Y-%m-%d %H:%M:%S") . "\n";
$template_header .= " compiled from \"" . $this->template->source->filepath . "\" */ ?>\n";
$config->compiled_config = '<?php $_config_vars = ' . var_export($this->config_data, true) . '; ?>'; $code = '<?php $_smarty_tpl->smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' .
var_export($this->config_data, true) . '); ?>';
return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code);
} }
/** /**
@ -129,13 +164,13 @@ class Smarty_Internal_Config_File_Compiler
{ {
$this->lex = Smarty_Internal_Configfilelexer::instance(); $this->lex = Smarty_Internal_Configfilelexer::instance();
$this->parser = Smarty_Internal_Configfileparser::instance(); $this->parser = Smarty_Internal_Configfileparser::instance();
// get template source line which has error // get config source line which has error
$line = $this->lex->line; $line = $this->lex->line;
if (isset($args)) { if (isset($args)) {
// $line--; // $line--;
} }
$match = preg_split("/\n/", $this->lex->data); $match = preg_split("/\n/", $this->lex->data);
$error_text = "Syntax error in config file '{$this->config->source->filepath}' on line {$line} '{$match[$line - 1]}' "; $error_text = "Syntax error in config file '{$this->template->source->filepath}' on line {$line} '{$match[$line - 1]}' ";
if (isset($args)) { if (isset($args)) {
// individual error message // individual error message
$error_text .= $args; $error_text .= $args;

@ -1,6 +1,7 @@
<?php <?php
/** /**
* Smarty Internal Plugin Configfilelexer * Smarty Internal Plugin Configfilelexer
*
* This is the lexer to break the config file source into tokens * This is the lexer to break the config file source into tokens
* *
* @package Smarty * @package Smarty
@ -9,25 +10,134 @@
*/ */
/** /**
* Smarty Internal Plugin Configfilelexer * Smarty_Internal_Configfilelexer
*
* This is the config file lexer.
* It is generated from the smarty_internal_configfilelexer.plex file
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/ */
class Smarty_Internal_Configfilelexer class Smarty_Internal_Configfilelexer
{ {
/**
* Source
*
* @var string
*/
public $data; public $data;
/**
* byte counter
*
* @var int
*/
public $counter; public $counter;
/**
* token number
*
* @var int
*/
public $token; public $token;
/**
* token value
*
* @var string
*/
public $value; public $value;
public $node;
/**
* current line
*
* @var int
*/
public $line; public $line;
private $state = 1;
/**
* state number
*
* @var int
*/
public $state = 1;
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* compiler object
*
* @var Smarty_Internal_Config_File_Compiler
*/
private $compiler = null;
/**
* copy of config_booleanize
*
* @var bool
*/
private $configBooleanize = false;
/**
* trace file
*
* @var resource
*/
public $yyTraceFILE; public $yyTraceFILE;
/**
* trace prompt
*
* @var string
*/
public $yyTracePrompt; public $yyTracePrompt;
public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE');
/**
* state names
*
* @var array
*/
public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION',
6 => 'TRIPPLE');
/**
* storage for assembled token patterns
*
* @var sring
*/
private $yy_global_pattern1 = null;
private $yy_global_pattern2 = null;
private $yy_global_pattern3 = null;
private $yy_global_pattern4 = null;
private $yy_global_pattern5 = null;
private $yy_global_pattern6 = null;
/**
* token names
*
* @var array
*/
public $smarty_token_names = array( // Text for parser error messages public $smarty_token_names = array( // Text for parser error messages
); );
function __construct($data, $compiler) /**
* constructor
*
* @param string $data template source
* @param Smarty_Internal_Config_File_Compiler $compiler
*/
function __construct($data, Smarty_Internal_Config_File_Compiler $compiler)
{ {
// set instance object // set instance object
self::instance($this); self::instance($this);
@ -39,6 +149,7 @@ class Smarty_Internal_Configfilelexer
$this->line = 1; $this->line = 1;
$this->compiler = $compiler; $this->compiler = $compiler;
$this->smarty = $compiler->smarty; $this->smarty = $compiler->smarty;
$this->configBooleanize = $this->smarty->config_booleanize;
} }
public static function &instance($new_instance = null) public static function &instance($new_instance = null)
@ -57,6 +168,7 @@ class Smarty_Internal_Configfilelexer
} }
private $_yy_state = 1; private $_yy_state = 1;
private $_yy_stack = array(); private $_yy_stack = array();
public function yylex() public function yylex()
@ -97,41 +209,28 @@ class Smarty_Internal_Configfilelexer
public function yylex1() public function yylex1()
{ {
$tokenMap = array( if (!isset($this->yy_global_pattern1)) {
1 => 0, $this->yy_global_pattern1 = "/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/isS";
2 => 0, }
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
);
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/iS";
do { do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) { if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches; $yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns if (strlen($yysubmatches[0]) < 200) {
if (!count($yymatches)) { $yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
throw new Exception('Error: lexing failed because a rule matched' . } else {
' an empty string. Input "' . substr($this->data, $yymatches = array_filter($yymatches, 'strlen');
$this->counter, 5) . '... state START'); }
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state START');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value $this->value = current($yymatches); // token value
$r = $this->{'yy_r1_' . $this->token}($yysubmatches); $r = $this->{'yy_r1_' . $this->token}();
if ($r === null) { if ($r === null) {
$this->counter += strlen($this->value); $this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n"); $this->line += substr_count($this->value, "\n");
@ -151,8 +250,7 @@ class Smarty_Internal_Configfilelexer
continue; continue;
} }
} else { } else {
throw new Exception('Unexpected input at line' . $this->line . throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
': ' . $this->data[$this->counter]);
} }
break; break;
} while (true); } while (true);
@ -160,52 +258,52 @@ class Smarty_Internal_Configfilelexer
const START = 1; const START = 1;
function yy_r1_1($yy_subpatterns) function yy_r1_1()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART; $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART;
$this->yypushstate(self::COMMENT); $this->yypushstate(self::COMMENT);
} }
function yy_r1_2($yy_subpatterns) function yy_r1_2()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_OPENB; $this->token = Smarty_Internal_Configfileparser::TPC_OPENB;
$this->yypushstate(self::SECTION); $this->yypushstate(self::SECTION);
} }
function yy_r1_3($yy_subpatterns) function yy_r1_3()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB; $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB;
} }
function yy_r1_4($yy_subpatterns) function yy_r1_4()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_EQUAL; $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL;
$this->yypushstate(self::VALUE); $this->yypushstate(self::VALUE);
} }
function yy_r1_5($yy_subpatterns) function yy_r1_5()
{ {
return false; return false;
} }
function yy_r1_6($yy_subpatterns) function yy_r1_6()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
} }
function yy_r1_7($yy_subpatterns) function yy_r1_7()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_ID; $this->token = Smarty_Internal_Configfileparser::TPC_ID;
} }
function yy_r1_8($yy_subpatterns) function yy_r1_8()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_OTHER; $this->token = Smarty_Internal_Configfileparser::TPC_OTHER;
@ -213,42 +311,28 @@ class Smarty_Internal_Configfilelexer
public function yylex2() public function yylex2()
{ {
$tokenMap = array( if (!isset($this->yy_global_pattern2)) {
1 => 0, $this->yy_global_pattern2 = "/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS";
2 => 0, }
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
);
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
do { do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) { if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches; $yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns if (strlen($yysubmatches[0]) < 200) {
if (!count($yymatches)) { $yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
throw new Exception('Error: lexing failed because a rule matched' . } else {
' an empty string. Input "' . substr($this->data, $yymatches = array_filter($yymatches, 'strlen');
$this->counter, 5) . '... state VALUE'); }
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state VALUE');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value $this->value = current($yymatches); // token value
$r = $this->{'yy_r2_' . $this->token}($yysubmatches); $r = $this->{'yy_r2_' . $this->token}();
if ($r === null) { if ($r === null) {
$this->counter += strlen($this->value); $this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n"); $this->line += substr_count($this->value, "\n");
@ -268,8 +352,7 @@ class Smarty_Internal_Configfilelexer
continue; continue;
} }
} else { } else {
throw new Exception('Unexpected input at line' . $this->line . throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
': ' . $this->data[$this->counter]);
} }
break; break;
} while (true); } while (true);
@ -277,51 +360,53 @@ class Smarty_Internal_Configfilelexer
const VALUE = 2; const VALUE = 2;
function yy_r2_1($yy_subpatterns) function yy_r2_1()
{ {
return false; return false;
} }
function yy_r2_2($yy_subpatterns) function yy_r2_2()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_FLOAT; $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT;
$this->yypopstate(); $this->yypopstate();
} }
function yy_r2_3($yy_subpatterns) function yy_r2_3()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_INT; $this->token = Smarty_Internal_Configfileparser::TPC_INT;
$this->yypopstate(); $this->yypopstate();
} }
function yy_r2_4($yy_subpatterns) function yy_r2_4()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES; $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES;
$this->yypushstate(self::TRIPPLE); $this->yypushstate(self::TRIPPLE);
} }
function yy_r2_5($yy_subpatterns) function yy_r2_5()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING; $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING;
$this->yypopstate(); $this->yypopstate();
} }
function yy_r2_6($yy_subpatterns) function yy_r2_6()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING; $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING;
$this->yypopstate(); $this->yypopstate();
} }
function yy_r2_7($yy_subpatterns) function yy_r2_7()
{ {
if (!$this->smarty->config_booleanize || !in_array(strtolower($this->value), Array("true", "false", "on", "off", "yes", "no"))) { if (!$this->configBooleanize || !in_array(strtolower($this->value), Array("true", "false", "on", "off", "yes",
"no"))
) {
$this->yypopstate(); $this->yypopstate();
$this->yypushstate(self::NAKED_STRING_VALUE); $this->yypushstate(self::NAKED_STRING_VALUE);
return true; //reprocess in new state return true; //reprocess in new state
@ -331,14 +416,14 @@ class Smarty_Internal_Configfilelexer
} }
} }
function yy_r2_8($yy_subpatterns) function yy_r2_8()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
$this->yypopstate(); $this->yypopstate();
} }
function yy_r2_9($yy_subpatterns) function yy_r2_9()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
@ -348,34 +433,28 @@ class Smarty_Internal_Configfilelexer
public function yylex3() public function yylex3()
{ {
$tokenMap = array( if (!isset($this->yy_global_pattern3)) {
1 => 0, $this->yy_global_pattern3 = "/\G([^\n]+?(?=[ \t\r]*\n))/isS";
); }
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G([^\n]+?(?=[ \t\r]*\n))/iS";
do { do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) { if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches; $yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns if (strlen($yysubmatches[0]) < 200) {
if (!count($yymatches)) { $yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
throw new Exception('Error: lexing failed because a rule matched' . } else {
' an empty string. Input "' . substr($this->data, $yymatches = array_filter($yymatches, 'strlen');
$this->counter, 5) . '... state NAKED_STRING_VALUE'); }
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state NAKED_STRING_VALUE');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value $this->value = current($yymatches); // token value
$r = $this->{'yy_r3_' . $this->token}($yysubmatches); $r = $this->{'yy_r3_' . $this->token}();
if ($r === null) { if ($r === null) {
$this->counter += strlen($this->value); $this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n"); $this->line += substr_count($this->value, "\n");
@ -395,8 +474,7 @@ class Smarty_Internal_Configfilelexer
continue; continue;
} }
} else { } else {
throw new Exception('Unexpected input at line' . $this->line . throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
': ' . $this->data[$this->counter]);
} }
break; break;
} while (true); } while (true);
@ -404,7 +482,7 @@ class Smarty_Internal_Configfilelexer
const NAKED_STRING_VALUE = 3; const NAKED_STRING_VALUE = 3;
function yy_r3_1($yy_subpatterns) function yy_r3_1()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
@ -413,36 +491,28 @@ class Smarty_Internal_Configfilelexer
public function yylex4() public function yylex4()
{ {
$tokenMap = array( if (!isset($this->yy_global_pattern4)) {
1 => 0, $this->yy_global_pattern4 = "/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS";
2 => 0, }
3 => 0,
);
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
do { do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) { if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches; $yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns if (strlen($yysubmatches[0]) < 200) {
if (!count($yymatches)) { $yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
throw new Exception('Error: lexing failed because a rule matched' . } else {
' an empty string. Input "' . substr($this->data, $yymatches = array_filter($yymatches, 'strlen');
$this->counter, 5) . '... state COMMENT'); }
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state COMMENT');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value $this->value = current($yymatches); // token value
$r = $this->{'yy_r4_' . $this->token}($yysubmatches); $r = $this->{'yy_r4_' . $this->token}();
if ($r === null) { if ($r === null) {
$this->counter += strlen($this->value); $this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n"); $this->line += substr_count($this->value, "\n");
@ -462,8 +532,7 @@ class Smarty_Internal_Configfilelexer
continue; continue;
} }
} else { } else {
throw new Exception('Unexpected input at line' . $this->line . throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
': ' . $this->data[$this->counter]);
} }
break; break;
} while (true); } while (true);
@ -471,19 +540,19 @@ class Smarty_Internal_Configfilelexer
const COMMENT = 4; const COMMENT = 4;
function yy_r4_1($yy_subpatterns) function yy_r4_1()
{ {
return false; return false;
} }
function yy_r4_2($yy_subpatterns) function yy_r4_2()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
} }
function yy_r4_3($yy_subpatterns) function yy_r4_3()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
@ -492,35 +561,28 @@ class Smarty_Internal_Configfilelexer
public function yylex5() public function yylex5()
{ {
$tokenMap = array( if (!isset($this->yy_global_pattern5)) {
1 => 0, $this->yy_global_pattern5 = "/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/isS";
2 => 0, }
);
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/iS";
do { do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) { if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches; $yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns if (strlen($yysubmatches[0]) < 200) {
if (!count($yymatches)) { $yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
throw new Exception('Error: lexing failed because a rule matched' . } else {
' an empty string. Input "' . substr($this->data, $yymatches = array_filter($yymatches, 'strlen');
$this->counter, 5) . '... state SECTION'); }
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state SECTION');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value $this->value = current($yymatches); // token value
$r = $this->{'yy_r5_' . $this->token}($yysubmatches); $r = $this->{'yy_r5_' . $this->token}();
if ($r === null) { if ($r === null) {
$this->counter += strlen($this->value); $this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n"); $this->line += substr_count($this->value, "\n");
@ -540,8 +602,7 @@ class Smarty_Internal_Configfilelexer
continue; continue;
} }
} else { } else {
throw new Exception('Unexpected input at line' . $this->line . throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
': ' . $this->data[$this->counter]);
} }
break; break;
} while (true); } while (true);
@ -549,13 +610,13 @@ class Smarty_Internal_Configfilelexer
const SECTION = 5; const SECTION = 5;
function yy_r5_1($yy_subpatterns) function yy_r5_1()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_DOT; $this->token = Smarty_Internal_Configfileparser::TPC_DOT;
} }
function yy_r5_2($yy_subpatterns) function yy_r5_2()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_SECTION; $this->token = Smarty_Internal_Configfileparser::TPC_SECTION;
@ -564,35 +625,28 @@ class Smarty_Internal_Configfilelexer
public function yylex6() public function yylex6()
{ {
$tokenMap = array( if (!isset($this->yy_global_pattern6)) {
1 => 0, $this->yy_global_pattern6 = "/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/isS";
2 => 0, }
);
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/iS";
do { do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) { if (preg_match($this->yy_global_pattern6, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches; $yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns if (strlen($yysubmatches[0]) < 200) {
if (!count($yymatches)) { $yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
throw new Exception('Error: lexing failed because a rule matched' . } else {
' an empty string. Input "' . substr($this->data, $yymatches = array_filter($yymatches, 'strlen');
$this->counter, 5) . '... state TRIPPLE'); }
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state TRIPPLE');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value $this->value = current($yymatches); // token value
$r = $this->{'yy_r6_' . $this->token}($yysubmatches); $r = $this->{'yy_r6_' . $this->token}();
if ($r === null) { if ($r === null) {
$this->counter += strlen($this->value); $this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n"); $this->line += substr_count($this->value, "\n");
@ -612,8 +666,7 @@ class Smarty_Internal_Configfilelexer
continue; continue;
} }
} else { } else {
throw new Exception('Unexpected input at line' . $this->line . throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
': ' . $this->data[$this->counter]);
} }
break; break;
} while (true); } while (true);
@ -621,7 +674,7 @@ class Smarty_Internal_Configfilelexer
const TRIPPLE = 6; const TRIPPLE = 6;
function yy_r6_1($yy_subpatterns) function yy_r6_1()
{ {
$this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END; $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END;
@ -629,7 +682,7 @@ class Smarty_Internal_Configfilelexer
$this->yypushstate(self::START); $this->yypushstate(self::START);
} }
function yy_r6_2($yy_subpatterns) function yy_r6_2()
{ {
$to = strlen($this->data); $to = strlen($this->data);
@ -642,5 +695,5 @@ class Smarty_Internal_Configfilelexer
$this->value = substr($this->data, $this->counter, $to - $this->counter); $this->value = substr($this->data, $this->counter, $to - $this->counter);
$this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT; $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT;
} }
}
}

File diff suppressed because it is too large Load Diff

@ -13,34 +13,70 @@
* *
* @package Smarty * @package Smarty
* @subpackage Template * @subpackage Template
*
* @method mixed getConfigVars(string $varName = null, bool $searchParents = true)
* @method mixed getStreamVariable(string $variable)
* @method Smarty_Internal_Data clearAssign(mixed $tpl_var)
* @method Smarty_Internal_Data clearAllAssign()
* @method Smarty_Internal_Data clearConfig(string $varName = null)
* @method Smarty_Internal_Data configLoad(string $config_file, mixed $sections = null, string $scope = 'local')
* @property int $scope
*/ */
class Smarty_Internal_Data class Smarty_Internal_Data
{ {
/**
* This object type (Smarty = 1, template = 2, data = 4)
*
* @var int
*/
public $_objType = 4;
/** /**
* name of class used for templates * name of class used for templates
* *
* @var string * @var string
*/ */
public $template_class = 'Smarty_Internal_Template'; public $template_class = 'Smarty_Internal_Template';
/** /**
* template variables * template variables
* *
* @var array * @var Smarty_Variable[]
*/ */
public $tpl_vars = array(); public $tpl_vars = array();
/** /**
* parent template (if any) * parent template (if any)
* *
* @var Smarty_Internal_Template * @var Smarty|Smarty_Internal_Template|Smarty_Internal_Data
*/ */
public $parent = null; public $parent = null;
/** /**
* configuration settings * configuration settings
* *
* @var array * @var string[]
*/ */
public $config_vars = array(); public $config_vars = array();
/**
* extension handler
*
* @var Smarty_Internal_Extension_Handler
*/
public $ext = null;
/**
* Smarty_Internal_Data constructor.
*
* Install extension handler
*/
public function __construct()
{
$this->ext = new Smarty_Internal_Extension_Handler();
$this->ext->objType = $this->_objType;
}
/** /**
* assigns a Smarty variable * assigns a Smarty variable
* *
@ -48,127 +84,62 @@ class Smarty_Internal_Data
* @param mixed $value the value to assign * @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached * @param boolean $nocache if true any output of this variable will be not cached
* *
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for
* chaining
*/ */
public function assign($tpl_var, $value = null, $nocache = false) public function assign($tpl_var, $value = null, $nocache = false)
{ {
if (is_array($tpl_var)) { if (is_array($tpl_var)) {
foreach ($tpl_var as $_key => $_val) { foreach ($tpl_var as $_key => $_val) {
if ($_key != '') { if ($_key != '') {
$this->tpl_vars[$_key] = new Smarty_variable($_val, $nocache); $this->tpl_vars[$_key] = new Smarty_Variable($_val, $nocache);
if ($this->_objType == 2 && $this->scope) {
$this->ext->_updateScope->updateScope($this, $_key);
}
} }
} }
} else { } else {
if ($tpl_var != '') { if ($tpl_var != '') {
$this->tpl_vars[$tpl_var] = new Smarty_variable($value, $nocache); $this->tpl_vars[$tpl_var] = new Smarty_Variable($value, $nocache);
} if ($this->_objType == 2 && $this->scope) {
} $this->ext->_updateScope->updateScope($this, $tpl_var);
return $this;
} }
/**
* assigns a global Smarty variable
*
* @param string $varname the global variable name
* @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached
*
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
*/
public function assignGlobal($varname, $value = null, $nocache = false)
{
if ($varname != '') {
Smarty::$global_tpl_vars[$varname] = new Smarty_variable($value, $nocache);
$ptr = $this;
while ($ptr instanceof Smarty_Internal_Template) {
$ptr->tpl_vars[$varname] = clone Smarty::$global_tpl_vars[$varname];
$ptr = $ptr->parent;
} }
} }
return $this; return $this;
} }
/** /**
* assigns values to template variables by reference * appends values to template variables
* *
* @param string $tpl_var the template variable name * @api Smarty::append()
* @param $value * @link http://www.smarty.net/docs/en/api.append.tpl
* @param boolean $nocache if true any output of this variable will be not cached
* *
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining * @param array|string $tpl_var the template variable name(s)
* @param mixed $value the value to append
* @param bool $merge flag if array elements shall be merged
* @param bool $nocache if true any output of this variable will
* be not cached
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/ */
public function assignByRef($tpl_var, &$value, $nocache = false) public function append($tpl_var, $value = null, $merge = false, $nocache = false)
{ {
if ($tpl_var != '') { return $this->ext->append->append($this, $tpl_var, $value, $merge, $nocache);
$this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache);
$this->tpl_vars[$tpl_var]->value = & $value;
}
return $this;
} }
/** /**
* appends values to template variables * assigns a global Smarty variable
* *
* @param array|string $tpl_var the template variable name(s) * @param string $varName the global variable name
* @param mixed $value the value to append * @param mixed $value the value to assign
* @param boolean $merge flag if array elements shall be merged
* @param boolean $nocache if true any output of this variable will be not cached * @param boolean $nocache if true any output of this variable will be not cached
* *
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/ */
public function append($tpl_var, $value = null, $merge = false, $nocache = false) public function assignGlobal($varName, $value = null, $nocache = false)
{ {
if (is_array($tpl_var)) { return $this->ext->assignGlobal->assignGlobal($this, $varName, $value, $nocache);
// $tpl_var is an array, ignore $value
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
if (!isset($this->tpl_vars[$_key])) {
$tpl_var_inst = $this->getVariable($_key, null, true, false);
if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
$this->tpl_vars[$_key] = new Smarty_variable(null, $nocache);
} else {
$this->tpl_vars[$_key] = clone $tpl_var_inst;
}
}
if (!(is_array($this->tpl_vars[$_key]->value) || $this->tpl_vars[$_key]->value instanceof ArrayAccess)) {
settype($this->tpl_vars[$_key]->value, 'array');
}
if ($merge && is_array($_val)) {
foreach ($_val as $_mkey => $_mval) {
$this->tpl_vars[$_key]->value[$_mkey] = $_mval;
}
} else {
$this->tpl_vars[$_key]->value[] = $_val;
}
}
}
} else {
if ($tpl_var != '' && isset($value)) {
if (!isset($this->tpl_vars[$tpl_var])) {
$tpl_var_inst = $this->getVariable($tpl_var, null, true, false);
if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
$this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache);
} else {
$this->tpl_vars[$tpl_var] = clone $tpl_var_inst;
}
}
if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) {
settype($this->tpl_vars[$tpl_var]->value, 'array');
}
if ($merge && is_array($value)) {
foreach ($value as $_mkey => $_mval) {
$this->tpl_vars[$tpl_var]->value[$_mkey] = $_mval;
}
} else {
$this->tpl_vars[$tpl_var]->value[] = $value;
}
}
}
return $this;
} }
/** /**
@ -178,399 +149,92 @@ class Smarty_Internal_Data
* @param mixed &$value the referenced value to append * @param mixed &$value the referenced value to append
* @param boolean $merge flag if array elements shall be merged * @param boolean $merge flag if array elements shall be merged
* *
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/ */
public function appendByRef($tpl_var, &$value, $merge = false) public function appendByRef($tpl_var, &$value, $merge = false)
{ {
if ($tpl_var != '' && isset($value)) { return $this->ext->appendByRef->appendByRef($this, $tpl_var, $value, $merge);
if (!isset($this->tpl_vars[$tpl_var])) {
$this->tpl_vars[$tpl_var] = new Smarty_variable();
}
if (!is_array($this->tpl_vars[$tpl_var]->value)) {
settype($this->tpl_vars[$tpl_var]->value, 'array');
}
if ($merge && is_array($value)) {
foreach ($value as $_key => $_val) {
$this->tpl_vars[$tpl_var]->value[$_key] = & $value[$_key];
}
} else {
$this->tpl_vars[$tpl_var]->value[] = & $value;
}
}
return $this;
} }
/** /**
* Returns a single or all template variables * assigns values to template variables by reference
* *
* @param string $varname variable name or null * @param string $tpl_var the template variable name
* @param object $_ptr optional pointer to data object * @param $value
* @param boolean $search_parents include parent templates? * @param boolean $nocache if true any output of this variable will be not cached
* *
* @return string variable value or or array of variables * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/ */
public function getTemplateVars($varname = null, $_ptr = null, $search_parents = true) public function assignByRef($tpl_var, &$value, $nocache = false)
{ {
if (isset($varname)) { return $this->ext->assignByRef->assignByRef($this, $tpl_var, $value, $nocache);
$_var = $this->getVariable($varname, $_ptr, $search_parents, false);
if (is_object($_var)) {
return $_var->value;
} else {
return null;
}
} else {
$_result = array();
if ($_ptr === null) {
$_ptr = $this;
}
while ($_ptr !== null) {
foreach ($_ptr->tpl_vars AS $key => $var) {
if (!array_key_exists($key, $_result)) {
$_result[$key] = $var->value;
}
}
// not found, try at parent
if ($search_parents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if ($search_parents && isset(Smarty::$global_tpl_vars)) {
foreach (Smarty::$global_tpl_vars AS $key => $var) {
if (!array_key_exists($key, $_result)) {
$_result[$key] = $var->value;
}
}
}
return $_result;
}
} }
/** /**
* clear the given assigned template variable. * Returns a single or all template variables
* *
* @param string|array $tpl_var the template variable(s) to clear * @api Smarty::getTemplateVars()
* @link http://www.smarty.net/docs/en/api.get.template.vars.tpl
* *
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining * @param string $varName variable name or null
*/ * @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $_ptr optional pointer to data object
public function clearAssign($tpl_var) * @param bool $searchParents include parent templates?
{
if (is_array($tpl_var)) {
foreach ($tpl_var as $curr_var) {
unset($this->tpl_vars[$curr_var]);
}
} else {
unset($this->tpl_vars[$tpl_var]);
}
return $this;
}
/**
* clear all the assigned template variables.
* *
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining * @return mixed variable value or or array of variables
*/ */
public function clearAllAssign() public function getTemplateVars($varName = null, Smarty_Internal_Data $_ptr = null, $searchParents = true)
{ {
$this->tpl_vars = array(); return $this->ext->getTemplateVars->getTemplateVars($this, $varName, $_ptr, $searchParents);
return $this;
}
/**
* load a config file, optionally load just selected sections
*
* @param string $config_file filename
* @param mixed $sections array of section names, single section or null
*
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
*/
public function configLoad($config_file, $sections = null)
{
// load Config class
$config = new Smarty_Internal_Config($config_file, $this->smarty, $this);
$config->loadConfigVars($sections);
return $this;
} }
/** /**
* gets the object of a Smarty variable * gets the object of a Smarty variable
* *
* @param string $variable the name of the Smarty variable * @param string $variable the name of the Smarty variable
* @param object $_ptr optional pointer to data object * @param Smarty_Internal_Data $_ptr optional pointer to data object
* @param boolean $search_parents search also in parent data * @param boolean $searchParents search also in parent data
* @param bool $error_enable * @param bool $error_enable
* *
* @return object the object of the variable * @return Smarty_Variable|Smarty_Undefined_Variable the object of the variable
*/ * @deprecated since 3.1.28 please use Smarty_Internal_Data::getTemplateVars() instead.
public function getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true)
{
if ($_ptr === null) {
$_ptr = $this;
}
while ($_ptr !== null) {
if (isset($_ptr->tpl_vars[$variable])) {
// found it, return it
return $_ptr->tpl_vars[$variable];
}
// not found, try at parent
if ($search_parents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if (isset(Smarty::$global_tpl_vars[$variable])) {
// found it, return it
return Smarty::$global_tpl_vars[$variable];
}
if ($this->smarty->error_unassigned && $error_enable) {
// force a notice
$x = $$variable;
}
return new Undefined_Smarty_Variable;
}
/**
* gets a config variable
*
* @param string $variable the name of the config variable
* @param bool $error_enable
*
* @return mixed the value of the config variable
*/
public function getConfigVariable($variable, $error_enable = true)
{
$_ptr = $this;
while ($_ptr !== null) {
if (isset($_ptr->config_vars[$variable])) {
// found it, return it
return $_ptr->config_vars[$variable];
}
// not found, try at parent
$_ptr = $_ptr->parent;
}
if ($this->smarty->error_unassigned && $error_enable) {
// force a notice
$x = $$variable;
}
return null;
}
/**
* gets a stream variable
*
* @param string $variable the stream of the variable
*
* @throws SmartyException
* @return mixed the value of the stream variable
*/ */
public function getStreamVariable($variable) public function getVariable($variable = null, Smarty_Internal_Data $_ptr = null, $searchParents = true, $error_enable = true){
{ return $this->ext->getTemplateVars->_getVariable($this, $variable, $_ptr, $searchParents, $error_enable);
$_result = '';
$fp = fopen($variable, 'r+');
if ($fp) {
while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
$_result .= $current_line;
}
fclose($fp);
return $_result;
}
if ($this->smarty->error_unassigned) {
throw new SmartyException('Undefined stream variable "' . $variable . '"');
} else {
return null;
}
} }
/** /**
* Returns a single or all config variables * Follow the parent chain an merge template and config variables
* *
* @param string $varname variable name or null * @param \Smarty_Internal_Data|null $data
* @param bool $search_parents
*
* @return string variable value or or array of variables
*/ */
public function getConfigVars($varname = null, $search_parents = true) public function _mergeVars(Smarty_Internal_Data $data = null)
{ {
$_ptr = $this; if (isset($data)) {
$var_array = array(); if (!empty($this->tpl_vars)) {
while ($_ptr !== null) { $data->tpl_vars = array_merge($this->tpl_vars, $data->tpl_vars);
if (isset($varname)) {
if (isset($_ptr->config_vars[$varname])) {
return $_ptr->config_vars[$varname];
} }
} else { if (!empty($this->config_vars)) {
$var_array = array_merge($_ptr->config_vars, $var_array); $data->config_vars = array_merge($this->config_vars, $data->config_vars);
} }
// not found, try at parent
if ($search_parents) {
$_ptr = $_ptr->parent;
} else { } else {
$_ptr = null; $data = $this;
} }
} if (isset($this->parent)) {
if (isset($varname)) { $this->parent->_mergeVars($data);
return '';
} else {
return $var_array;
} }
} }
/** /**
* Deassigns a single or all config variables * Handle unknown class methods
* *
* @param string $varname variable name or null * @param string $name unknown method-name
* * @param array $args argument array
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
*/
public function clearConfig($varname = null)
{
if (isset($varname)) {
unset($this->config_vars[$varname]);
} else {
$this->config_vars = array();
}
return $this;
}
}
/**
* class for the Smarty data object
* The Smarty data object will hold Smarty variables in the current scope
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Data extends Smarty_Internal_Data
{
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* create Smarty data object
*
* @param Smarty|array $_parent parent template
* @param Smarty|Smarty_Internal_Template $smarty global smarty instance
* *
* @return mixed
* @throws SmartyException * @throws SmartyException
*/ */
public function __construct($_parent = null, $smarty = null) public function __call($name, $args)
{
$this->smarty = $smarty;
if (is_object($_parent)) {
// when object set up back pointer
$this->parent = $_parent;
} elseif (is_array($_parent)) {
// set up variable values
foreach ($_parent as $_key => $_val) {
$this->tpl_vars[$_key] = new Smarty_variable($_val);
}
} elseif ($_parent != null) {
throw new SmartyException("Wrong type for template variables");
}
}
}
/**
* class for the Smarty variable object
* This class defines the Smarty variable object
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Variable
{
/**
* template variable
*
* @var mixed
*/
public $value = null;
/**
* if true any output of this variable will be not cached
*
* @var boolean
*/
public $nocache = false;
/**
* the scope the variable will have (local,parent or root)
*
* @var int
*/
public $scope = Smarty::SCOPE_LOCAL;
/**
* create Smarty variable object
*
* @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached
* @param int $scope the scope the variable will have (local,parent or root)
*/
public function __construct($value = null, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
{
$this->value = $value;
$this->nocache = $nocache;
$this->scope = $scope;
}
/**
* <<magic>> String conversion
*
* @return string
*/
public function __toString()
{
return (string) $this->value;
}
}
/**
* class for undefined variable object
* This class defines an object for undefined variable handling
*
* @package Smarty
* @subpackage Template
*/
class Undefined_Smarty_Variable
{
/**
* Returns FALSE for 'nocache' and NULL otherwise.
*
* @param string $name
*
* @return bool
*/
public function __get($name)
{
if ($name == 'nocache') {
return false;
} else {
return null;
}
}
/**
* Always returns an empty string.
*
* @return string
*/
public function __toString()
{ {
return ""; return $this->ext->_callExternalMethod($this, $name, $args);
} }
} }

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Smarty Internal Plugin Debug * Smarty Internal Plugin Debug
* Class to collect data for the Smarty Debugging Consol * Class to collect data for the Smarty Debugging Console
* *
* @package Smarty * @package Smarty
* @subpackage Debug * @subpackage Debug
@ -21,165 +21,245 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
* *
* @var array * @var array
*/ */
public static $template_data = array(); public $template_data = array();
/** /**
* List of uid's which shall be ignored * List of uid's which shall be ignored
* *
* @var array * @var array
*/ */
public static $ignore_uid = array(); public $ignore_uid = array();
/** /**
* Ignore template * Index of display() and fetch() calls
*
* @var int
*/
public $index = 0;
/**
* Counter for window offset
* *
* @param object $template * @var int
*/ */
public static function ignore($template) public $offset = 0;
/**
* Start logging template
*
* @param \Smarty_Internal_Template $template template
* @param null $mode true: display false: fetch null: subtemplate
*/
public function start_template(Smarty_Internal_Template $template, $mode = null)
{ {
// calculate Uid if not already done if (isset($mode)) {
if ($template->source->uid == '') { $this->index ++;
$template->source->filepath; $this->offset ++;
$this->template_data[$this->index] = null;
} }
self::$ignore_uid[$template->source->uid] = true; $key = $this->get_key($template);
$this->template_data[$this->index][$key]['start_template_time'] = microtime(true);
}
/**
* End logging of cache time
*
* @param \Smarty_Internal_Template $template cached template
*/
public function end_template(Smarty_Internal_Template $template)
{
$key = $this->get_key($template);
$this->template_data[$this->index][$key]['total_time'] +=
microtime(true) - $this->template_data[$this->index][$key]['start_template_time'];
//$this->template_data[$this->index][$key]['properties'] = $template->properties;
} }
/** /**
* Start logging of compile time * Start logging of compile time
* *
* @param object $template * @param \Smarty_Internal_Template $template
*/ */
public static function start_compile($template) public function start_compile(Smarty_Internal_Template $template)
{ {
static $_is_stringy = array('string' => true, 'eval' => true); static $_is_stringy = array('string' => true, 'eval' => true);
if (!empty($template->compiler->trace_uid)) { if (!empty($template->compiler->trace_uid)) {
$key = $template->compiler->trace_uid; $key = $template->compiler->trace_uid;
if (!isset(self::$template_data[$key])) { if (!isset($this->template_data[$this->index][$key])) {
if (isset($_is_stringy[$template->source->type])) { if (isset($_is_stringy[$template->source->type])) {
self::$template_data[$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\''; $this->template_data[$this->index][$key]['name'] =
'\'' . substr($template->source->name, 0, 25) . '...\'';
} else { } else {
self::$template_data[$key]['name'] = $template->source->filepath; $this->template_data[$this->index][$key]['name'] = $template->source->filepath;
} }
self::$template_data[$key]['compile_time'] = 0; $this->template_data[$this->index][$key]['compile_time'] = 0;
self::$template_data[$key]['render_time'] = 0; $this->template_data[$this->index][$key]['render_time'] = 0;
self::$template_data[$key]['cache_time'] = 0; $this->template_data[$this->index][$key]['cache_time'] = 0;
} }
} else { } else {
if (isset(self::$ignore_uid[$template->source->uid])) { if (isset($this->ignore_uid[$template->source->uid])) {
return; return;
} }
$key = self::get_key($template); $key = $this->get_key($template);
} }
self::$template_data[$key]['start_time'] = microtime(true); $this->template_data[$this->index][$key]['start_time'] = microtime(true);
} }
/** /**
* End logging of compile time * End logging of compile time
* *
* @param object $template * @param \Smarty_Internal_Template $template
*/ */
public static function end_compile($template) public function end_compile(Smarty_Internal_Template $template)
{ {
if (!empty($template->compiler->trace_uid)) { if (!empty($template->compiler->trace_uid)) {
$key = $template->compiler->trace_uid; $key = $template->compiler->trace_uid;
} else { } else {
if (isset(self::$ignore_uid[$template->source->uid])) { if (isset($this->ignore_uid[$template->source->uid])) {
return; return;
} }
$key = self::get_key($template); $key = $this->get_key($template);
} }
self::$template_data[$key]['compile_time'] += microtime(true) - self::$template_data[$key]['start_time']; $this->template_data[$this->index][$key]['compile_time'] +=
microtime(true) - $this->template_data[$this->index][$key]['start_time'];
} }
/** /**
* Start logging of render time * Start logging of render time
* *
* @param object $template * @param \Smarty_Internal_Template $template
*/ */
public static function start_render($template) public function start_render(Smarty_Internal_Template $template)
{ {
$key = self::get_key($template); $key = $this->get_key($template);
self::$template_data[$key]['start_time'] = microtime(true); $this->template_data[$this->index][$key]['start_time'] = microtime(true);
} }
/** /**
* End logging of compile time * End logging of compile time
* *
* @param object $template * @param \Smarty_Internal_Template $template
*/ */
public static function end_render($template) public function end_render(Smarty_Internal_Template $template)
{ {
$key = self::get_key($template); $key = $this->get_key($template);
self::$template_data[$key]['render_time'] += microtime(true) - self::$template_data[$key]['start_time']; $this->template_data[$this->index][$key]['render_time'] +=
microtime(true) - $this->template_data[$this->index][$key]['start_time'];
} }
/** /**
* Start logging of cache time * Start logging of cache time
* *
* @param object $template cached template * @param \Smarty_Internal_Template $template cached template
*/ */
public static function start_cache($template) public function start_cache(Smarty_Internal_Template $template)
{ {
$key = self::get_key($template); $key = $this->get_key($template);
self::$template_data[$key]['start_time'] = microtime(true); $this->template_data[$this->index][$key]['start_time'] = microtime(true);
} }
/** /**
* End logging of cache time * End logging of cache time
* *
* @param object $template cached template * @param \Smarty_Internal_Template $template cached template
*/ */
public static function end_cache($template) public function end_cache(Smarty_Internal_Template $template)
{ {
$key = self::get_key($template); $key = $this->get_key($template);
self::$template_data[$key]['cache_time'] += microtime(true) - self::$template_data[$key]['start_time']; $this->template_data[$this->index][$key]['cache_time'] +=
microtime(true) - $this->template_data[$this->index][$key]['start_time'];
} }
/** /**
* Opens a window for the Smarty Debugging Consol and display the data * Register template object
*
* @param \Smarty_Internal_Template $template cached template
*/
public function register_template(Smarty_Internal_Template $template)
{
}
/**
* Register data object
*
* @param \Smarty_Data $data data object
*/
public static function register_data(Smarty_Data $data)
{
}
/**
* Opens a window for the Smarty Debugging Console and display the data
* *
* @param Smarty_Internal_Template|Smarty $obj object to debug * @param Smarty_Internal_Template|Smarty $obj object to debug
* @param bool $full
*/ */
public static function display_debug($obj) public function display_debug($obj, $full = false)
{ {
// prepare information of assigned variables if (!$full) {
$ptr = self::get_debug_vars($obj); $this->offset ++;
if ($obj instanceof Smarty) { $savedIndex = $this->index;
$smarty = clone $obj; $this->index = 9999;
}
if ($obj->_objType == 1) {
$smarty = $obj;
} else { } else {
$smarty = clone $obj->smarty; $smarty = $obj->smarty;
} }
// create fresh instance of smarty for displaying the debug console
// to avoid problems if the application did overload the Smarty class
$debObj = new Smarty();
// copy the working dirs from application
$debObj->setCompileDir($smarty->getCompileDir());
// init properties by hand as user may have edited the original Smarty class
$debObj->setPluginsDir(is_dir(__DIR__ . '/../plugins') ? __DIR__ . '/../plugins' : $smarty->getPluginsDir());
$debObj->force_compile = false;
$debObj->compile_check = true;
$debObj->left_delimiter = '{';
$debObj->right_delimiter = '}';
$debObj->security_policy = null;
$debObj->debugging = false;
$debObj->debugging_ctrl = 'NONE';
$debObj->error_reporting = E_ALL & ~E_NOTICE;
$debObj->debug_tpl = isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . __DIR__ . '/../debug.tpl';
$debObj->registered_plugins = array();
$debObj->registered_resources = array();
$debObj->registered_filters = array();
$debObj->autoload_filters = array();
$debObj->default_modifiers = array();
$debObj->escape_html = true;
$debObj->caching = false;
$debObj->compile_id = null;
$debObj->cache_id = null;
// prepare information of assigned variables
$ptr = $this->get_debug_vars($obj);
$_assigned_vars = $ptr->tpl_vars; $_assigned_vars = $ptr->tpl_vars;
ksort($_assigned_vars); ksort($_assigned_vars);
$_config_vars = $ptr->config_vars; $_config_vars = $ptr->config_vars;
ksort($_config_vars); ksort($_config_vars);
$smarty->registered_filters = array(); $debugging = $smarty->debugging;
$smarty->autoload_filters = array();
$smarty->default_modifiers = array(); $_template = new Smarty_Internal_Template($debObj->debug_tpl, $debObj);
$smarty->force_compile = false; if ($obj->_objType == 2) {
$smarty->left_delimiter = '{';
$smarty->right_delimiter = '}';
$smarty->debugging = false;
$smarty->debugging_ctrl = 'NONE';
$smarty->force_compile = false;
$_template = new Smarty_Internal_Template($smarty->debug_tpl, $smarty);
$_template->caching = false;
$_template->disableSecurity();
$_template->cache_id = null;
$_template->compile_id = null;
if ($obj instanceof Smarty_Internal_Template) {
$_template->assign('template_name', $obj->source->type . ':' . $obj->source->name); $_template->assign('template_name', $obj->source->type . ':' . $obj->source->name);
} }
if ($obj instanceof Smarty) { if ($obj->_objType == 1 || $full) {
$_template->assign('template_data', self::$template_data); $_template->assign('template_data', $this->template_data[$this->index]);
} else { } else {
$_template->assign('template_data', null); $_template->assign('template_data', null);
} }
$_template->assign('assigned_vars', $_assigned_vars); $_template->assign('assigned_vars', $_assigned_vars);
$_template->assign('config_vars', $_config_vars); $_template->assign('config_vars', $_config_vars);
$_template->assign('execution_time', microtime(true) - $smarty->start_time); $_template->assign('execution_time', microtime(true) - $smarty->start_time);
$_template->assign('display_mode', $debugging == 2 || !$full);
$_template->assign('offset', $this->offset * 50);
echo $_template->fetch(); echo $_template->fetch();
if (isset($full)) {
$this->index --;
}
if (!$full) {
$this->index = $savedIndex;
}
} }
/** /**
@ -189,31 +269,79 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
* *
* @return StdClass * @return StdClass
*/ */
public static function get_debug_vars($obj) public function get_debug_vars($obj)
{ {
$config_vars = $obj->config_vars; $config_vars = array();
foreach ($obj->config_vars as $key => $var) {
$config_vars[$key]['value'] = $var;
if ($obj->_objType == 2) {
$config_vars[$key]['scope'] = $obj->source->type . ':' . $obj->source->name;
} elseif ($obj->_objType == 4) {
$tpl_vars[$key]['scope'] = $obj->dataObjectName;
} else {
$config_vars[$key]['scope'] = 'Smarty object';
}
}
$tpl_vars = array(); $tpl_vars = array();
foreach ($obj->tpl_vars as $key => $var) { foreach ($obj->tpl_vars as $key => $var) {
$tpl_vars[$key] = clone $var; foreach ($var as $varkey => $varvalue) {
if ($obj instanceof Smarty_Internal_Template) { if ($varkey == 'value') {
$tpl_vars[$key]->scope = $obj->source->type . ':' . $obj->source->name; $tpl_vars[$key][$varkey] = $varvalue;
} elseif ($obj instanceof Smarty_Data) { } else {
$tpl_vars[$key]->scope = 'Data object'; if ($varkey == 'nocache') {
if ($varvalue == true) {
$tpl_vars[$key][$varkey] = $varvalue;
}
} else { } else {
$tpl_vars[$key]->scope = 'Smarty root'; if ($varkey != 'scope' || $varvalue !== 0) {
$tpl_vars[$key]['attributes'][$varkey] = $varvalue;
}
}
}
}
if ($obj->_objType == 2) {
$tpl_vars[$key]['scope'] = $obj->source->type . ':' . $obj->source->name;
} elseif ($obj->_objType == 4) {
$tpl_vars[$key]['scope'] = $obj->dataObjectName;
} else {
$tpl_vars[$key]['scope'] = 'Smarty object';
} }
} }
if (isset($obj->parent)) { if (isset($obj->parent)) {
$parent = self::get_debug_vars($obj->parent); $parent = $this->get_debug_vars($obj->parent);
foreach ($parent->tpl_vars as $name => $pvar) {
if (isset($tpl_vars[$name]) && $tpl_vars[$name]['value'] === $pvar['value']) {
$tpl_vars[$name]['scope'] = $pvar['scope'];
}
}
$tpl_vars = array_merge($parent->tpl_vars, $tpl_vars); $tpl_vars = array_merge($parent->tpl_vars, $tpl_vars);
foreach ($parent->config_vars as $name => $pvar) {
if (isset($config_vars[$name]) && $config_vars[$name]['value'] === $pvar['value']) {
$config_vars[$name]['scope'] = $pvar['scope'];
}
}
$config_vars = array_merge($parent->config_vars, $config_vars); $config_vars = array_merge($parent->config_vars, $config_vars);
} else { } else {
foreach (Smarty::$global_tpl_vars as $name => $var) { foreach (Smarty::$global_tpl_vars as $key => $var) {
if (!array_key_exists($name, $tpl_vars)) { if (!array_key_exists($key, $tpl_vars)) {
$clone = clone $var; foreach ($var as $varkey => $varvalue) {
$clone->scope = 'Global'; if ($varkey == 'value') {
$tpl_vars[$name] = $clone; $tpl_vars[$key][$varkey] = $varvalue;
} else {
if ($varkey == 'nocache') {
if ($varvalue == true) {
$tpl_vars[$key][$varkey] = $varvalue;
}
} else {
if ($varkey != 'scope' || $varvalue !== 0) {
$tpl_vars[$key]['attributes'][$varkey] = $varvalue;
}
}
}
}
$tpl_vars[$key]['scope'] = 'Global';
} }
} }
} }
@ -224,11 +352,11 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/** /**
* Return key into $template_data for template * Return key into $template_data for template
* *
* @param object $template template object * @param \Smarty_Internal_Template $template template object
* *
* @return string key into $template_data * @return string key into $template_data
*/ */
private static function get_key($template) private function get_key(Smarty_Internal_Template $template)
{ {
static $_is_stringy = array('string' => true, 'eval' => true); static $_is_stringy = array('string' => true, 'eval' => true);
// calculate Uid if not already done // calculate Uid if not already done
@ -236,19 +364,67 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
$template->source->filepath; $template->source->filepath;
} }
$key = $template->source->uid; $key = $template->source->uid;
if (isset(self::$template_data[$key])) { if (isset($this->template_data[$this->index][$key])) {
return $key; return $key;
} else { } else {
if (isset($_is_stringy[$template->source->type])) { if (isset($_is_stringy[$template->source->type])) {
self::$template_data[$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\''; $this->template_data[$this->index][$key]['name'] =
'\'' . substr($template->source->name, 0, 25) . '...\'';
} else { } else {
self::$template_data[$key]['name'] = $template->source->filepath; $this->template_data[$this->index][$key]['name'] = $template->source->filepath;
} }
self::$template_data[$key]['compile_time'] = 0; $this->template_data[$this->index][$key]['compile_time'] = 0;
self::$template_data[$key]['render_time'] = 0; $this->template_data[$this->index][$key]['render_time'] = 0;
self::$template_data[$key]['cache_time'] = 0; $this->template_data[$this->index][$key]['cache_time'] = 0;
$this->template_data[$this->index][$key]['total_time'] = 0;
return $key; return $key;
} }
} }
/**
* Ignore template
*
* @param \Smarty_Internal_Template $template
*/
public function ignore(Smarty_Internal_Template $template)
{
// calculate Uid if not already done
if ($template->source->uid == '') {
$template->source->filepath;
}
$this->ignore_uid[$template->source->uid] = true;
}
/**
* handle 'URL' debugging mode
*
* @param Smarty $smarty
*/
public function debugUrl(Smarty $smarty)
{
if (isset($_SERVER['QUERY_STRING'])) {
$_query_string = $_SERVER['QUERY_STRING'];
} else {
$_query_string = '';
}
if (false !== strpos($_query_string, $smarty->smarty_debug_id)) {
if (false !== strpos($_query_string, $smarty->smarty_debug_id . '=on')) {
// enable debugging for this browser session
setcookie('SMARTY_DEBUG', true);
$smarty->debugging = true;
} elseif (false !== strpos($_query_string, $smarty->smarty_debug_id . '=off')) {
// disable debugging for this browser session
setcookie('SMARTY_DEBUG', false);
$smarty->debugging = false;
} else {
// enable debugging for this page
$smarty->debugging = true;
}
} else {
if (isset($_COOKIE['SMARTY_DEBUG'])) {
$smarty->debugging = true;
}
}
}
} }

@ -0,0 +1,126 @@
<?php
/**
* Smarty Extension Clear
*
* $smarty->clear() method file cache file resource
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Extension_Clear
{
/**
* Empty cache for a specific template
*
* @param Smarty $smarty
* @param string $resource_name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param integer $exp_time expiration time (number of seconds, not timestamp)
*
* @return integer number of cache files deleted
*/
public static function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
{
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
$_compile_id = isset($compile_id) ? preg_replace('![^\w]+!', '_', $compile_id) : null;
$_dir_sep = $smarty->use_sub_dirs ? '/' : '^';
$_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0;
$_dir = $smarty->getCacheDir();
if ($_dir == '/') { //We should never want to delete this!
return 0;
}
$_dir_length = strlen($_dir);
if (isset($_cache_id)) {
$_cache_id_parts = explode('|', $_cache_id);
$_cache_id_parts_count = count($_cache_id_parts);
if ($smarty->use_sub_dirs) {
foreach ($_cache_id_parts as $id_part) {
$_dir .= $id_part . DS;
}
}
}
if (isset($resource_name)) {
$_save_stat = $smarty->caching;
$smarty->caching = true;
$tpl = new $smarty->template_class($resource_name, $smarty);
$smarty->caching = $_save_stat;
// remove from template cache
$tpl->source; // have the template registered before unset()
if ($tpl->source->exists) {
$_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath));
} else {
return 0;
}
}
$_count = 0;
$_time = time();
if (file_exists($_dir)) {
$_cacheDirs = new RecursiveDirectoryIterator($_dir);
$_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($_cache as $_file) {
if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) {
continue;
}
// directory ?
if ($_file->isDir()) {
if (!$_cache->isDot()) {
// delete folder if empty
@rmdir($_file->getPathname());
}
} else {
$_parts = explode($_dir_sep, str_replace('\\', '/', substr((string) $_file, $_dir_length)));
$_parts_count = count($_parts);
// check name
if (isset($resource_name)) {
if ($_parts[$_parts_count - 1] != $_resourcename_parts) {
continue;
}
}
// check compile id
if (isset($_compile_id) && (!isset($_parts[$_parts_count - 2 - $_compile_id_offset]) ||
$_parts[$_parts_count - 2 - $_compile_id_offset] != $_compile_id)
) {
continue;
}
// check cache id
if (isset($_cache_id)) {
// count of cache id parts
$_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset :
$_parts_count - 1 - $_compile_id_offset;
if ($_parts_count < $_cache_id_parts_count) {
continue;
}
for ($i = 0; $i < $_cache_id_parts_count; $i ++) {
if ($_parts[$i] != $_cache_id_parts[$i]) {
continue 2;
}
}
}
// expired ?
if (isset($exp_time)) {
if ($exp_time < 0) {
preg_match('#\'cache_lifetime\' =>\s*(\d*)#', file_get_contents($_file), $match);
if ($_time < (@filemtime($_file) + $match[1])) {
continue;
}
} else {
if ($_time - @filemtime($_file) < $exp_time) {
continue;
}
}
}
$_count += @unlink((string) $_file) ? 1 : 0;
if (function_exists('opcache_invalidate')) {
opcache_invalidate((string) $_file);
}
}
}
}
return $_count;
}
}

@ -0,0 +1,157 @@
<?php
/**
* Smarty Extension handler
*
* Load extensions dynamically
*
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*
* @property Smarty_Internal_Runtime_Inheritance $_inheritance
* @property Smarty_Internal_Runtime_SubTemplate $_subTemplate
* @property Smarty_Internal_Runtime_TplFunction $_tplFunction
* @property Smarty_Internal_Runtime_Var $_var
* @property Smarty_Internal_Runtime_Config $_config
* @property Smarty_Internal_Runtime_Foreach $_foreach
* @property Smarty_Internal_Runtime_Hhvm $_hhvm
* @property Smarty_Internal_Runtime_WriteFile $_writeFile
* @property Smarty_Internal_Runtime_ValidateCompiled $_validateCompiled
* @property Smarty_Internal_Runtime_CodeFrame $_codeFrame
* @property Smarty_Internal_Runtime_FilterHandler $_filterHandler
* @property Smarty_Internal_Runtime_GetIncludePath $_getIncludePath
* @property Smarty_Internal_Runtime_UpdateScope $_updateScope
* @property Smarty_Internal_Runtime_IsCached $_isCached
* @property Smarty_Internal_Runtime_CacheModify $_cacheModify
* @property Smarty_Internal_Runtime_UpdateCache $_updateCache
* @property Smarty_Internal_Method_GetTemplateVars $getTemplateVars
* @property Smarty_Internal_Method_Append $append
* @property Smarty_Internal_Method_AppendByRef $appendByRef
* @property Smarty_Internal_Method_AssignGlobal $assignGlobal
* @property Smarty_Internal_Method_AssignByRef $assignByRef
* @property Smarty_Internal_Method_LoadFilter $loadFilter
* @property Smarty_Internal_Method_LoadPlugin $loadPlugin
* @property Smarty_Internal_Method_RegisterFilter $registerFilter
* @property Smarty_Internal_Method_RegisterObject $registerObject
* @property Smarty_Internal_Method_RegisterPlugin $registerPlugin
*/
class Smarty_Internal_Extension_Handler
{
public $objType = null;
/**
* Cache for property information from generic getter/setter
* Preloaded with names which should not use with generic getter/setter
*
* @var array
*/
private $_property_info = array('AutoloadFilters' => 0, 'DefaultModifiers' => 0, 'ConfigVars' => 0,
'DebugTemplate' => 0, 'RegisteredObject' => 0, 'StreamVariable' => 0,
'TemplateVars' => 0,);#
private $resolvedProperties = array();
/**
* Call external Method
*
* @param \Smarty_Internal_Data $data
* @param string $name external method names
* @param array $args argument array
*
* @return mixed
* @throws SmartyException
*/
public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args)
{
/* @var Smarty $data ->smarty */
$smarty = isset($data->smarty) ? $data->smarty : $data;
if (!isset($smarty->ext->$name)) {
$class = 'Smarty_Internal_Method_' . ucfirst($name);
if (preg_match('/^(set|get)([A-Z].*)$/', $name, $match)) {
if (!isset($this->_property_info[$prop = $match[2]])) {
// convert camel case to underscored name
$this->resolvedProperties[$prop] = $pn = strtolower(join('_',
preg_split('/([A-Z][^A-Z]*)/', $prop, - 1,
PREG_SPLIT_NO_EMPTY |
PREG_SPLIT_DELIM_CAPTURE)));
$this->_property_info[$prop] = property_exists($data, $pn) ? 1 :
($data->_objType == 2 && property_exists($smarty, $pn) ? 2 : 0);
}
if ($this->_property_info[$prop]) {
$pn = $this->resolvedProperties[$prop];
if ($match[1] == 'get') {
return $this->_property_info[$prop] == 1 ? $data->$pn : $data->smarty->$pn;
} else {
return $this->_property_info[$prop] == 1 ? $data->$pn = $args[0] :
$data->smarty->$pn = $args[0];
}
} elseif (!class_exists($class)) {
throw new SmartyException("property '$pn' does not exist.");
}
}
if (class_exists($class)) {
$callback = array($smarty->ext->$name = new $class(), $name);
}
} else {
$callback = array($smarty->ext->$name, $name);
}
array_unshift($args, $data);
if (isset($callback) && $callback[0]->objMap | $data->_objType) {
return call_user_func_array($callback, $args);
}
return call_user_func_array(array(new Smarty_Internal_Undefined(), $name), $args);
}
/**
* set extension property
*
* @param string $property_name property name
* @param mixed $value value
*
* @throws SmartyException
*/
public function __set($property_name, $value)
{
$this->$property_name = $value;
}
/**
* get extension object
*
* @param string $property_name property name
*
* @return mixed|Smarty_Template_Cached
* @throws SmartyException
*/
public function __get($property_name)
{
// object properties of runtime template extensions will start with '_'
if ($property_name[0] == '_') {
$class = 'Smarty_Internal_Runtime_' . ucfirst(substr($property_name, 1));
} else {
$class = 'Smarty_Internal_Method_' . ucfirst($property_name);
}
if (class_exists($class)) {
return $this->$property_name = new $class();
}
return $this;
}
/**
* Call error handler for undefined method
*
* @param string $name unknown method-name
* @param array $args argument array
*
* @return mixed
* @throws SmartyException
*/
public function __call($name, $args)
{
return call_user_func_array(array(new Smarty_Internal_Undefined(), $name), $args);
}
}

@ -1,52 +0,0 @@
<?php
/**
* Smarty Internal Plugin Function Call Handler
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
/**
* This class does call function defined with the {function} tag
*
* @package Smarty
* @subpackage PluginsInternal
*/
class Smarty_Internal_Function_Call_Handler
{
/**
* This function handles calls to template functions defined by {function}
* It does create a PHP function at the first call
*
* @param string $_name template function name
* @param Smarty_Internal_Template $_template template object
* @param array $_params Smarty variables passed as call parameter
* @param string $_hash nocache hash value
* @param bool $_nocache nocache flag
*/
public static function call($_name, Smarty_Internal_Template $_template, $_params, $_hash, $_nocache)
{
if ($_nocache) {
$_function = "smarty_template_function_{$_name}_nocache";
} else {
$_function = "smarty_template_function_{$_hash}_{$_name}";
}
if (!is_callable($_function)) {
$_code = "function {$_function}(\$_smarty_tpl,\$params) {
\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;
foreach (\$_smarty_tpl->smarty->template_functions['{$_name}']['parameter'] as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);};
foreach (\$params as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);}?>";
if ($_nocache) {
$_code .= preg_replace(array("!<\?php echo \\'/\*%%SmartyNocache:{$_template->smarty->template_functions[$_name]['nocache_hash']}%%\*/|/\*/%%SmartyNocache:{$_template->smarty->template_functions[$_name]['nocache_hash']}%%\*/\\';\?>!",
"!\\\'!"), array('', "'"), $_template->smarty->template_functions[$_name]['compiled']);
$_template->smarty->template_functions[$_name]['called_nocache'] = true;
} else {
$_code .= preg_replace("/{$_template->smarty->template_functions[$_name]['nocache_hash']}/", $_template->properties['nocache_hash'], $_template->smarty->template_functions[$_name]['compiled']);
}
$_code .= "<?php \$_smarty_tpl->tpl_vars = \$saved_tpl_vars;}";
eval($_code);
}
$_function($_template, $_params);
}
}

@ -1,46 +0,0 @@
<?php
/**
* Smarty read include path plugin
*
* @package Smarty
* @subpackage PluginsInternal
* @author Monte Ohrt
*/
/**
* Smarty Internal Read Include Path Class
*
* @package Smarty
* @subpackage PluginsInternal
*/
class Smarty_Internal_Get_Include_Path
{
/**
* Return full file path from PHP include_path
*
* @param string $filepath filepath
*
* @return string|boolean full filepath or false
*/
public static function getIncludePath($filepath)
{
static $_include_path = null;
if (function_exists('stream_resolve_include_path')) {
// available since PHP 5.3.2
return stream_resolve_include_path($filepath);
}
if ($_include_path === null) {
$_include_path = explode(PATH_SEPARATOR, get_include_path());
}
foreach ($_include_path as $_path) {
if (file_exists($_path . DS . $filepath)) {
return $_path . DS . $filepath;
}
}
return false;
}
}

@ -0,0 +1,51 @@
<?php
/**
* Smarty Method AddAutoloadFilters
*
* Smarty::addAutoloadFilters() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_AddAutoloadFilters extends Smarty_Internal_Method_SetAutoloadFilters
{
/**
* Add autoload filters
*
* @api Smarty::setAutoloadFilters()
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @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|\Smarty_Internal_Template
*/
public function addAutoloadFilters(Smarty_Internal_TemplateBase $obj, $filters, $type = null)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if ($type !== null) {
$this->_checkFilterType($type);
if (!empty($smarty->autoload_filters[$type])) {
$smarty->autoload_filters[$type] = array_merge($smarty->autoload_filters[$type], (array) $filters);
} else {
$smarty->autoload_filters[$type] = (array) $filters;
}
} else {
foreach ((array) $filters as $type => $value) {
$this->_checkFilterType($type);
if (!empty($smarty->autoload_filters[$type])) {
$smarty->autoload_filters[$type] = array_merge($smarty->autoload_filters[$type], (array) $value);
} else {
$smarty->autoload_filters[$type] = (array) $value;
}
}
}
return $obj;
}
}

@ -0,0 +1,42 @@
<?php
/**
* Smarty Method AddDefaultModifiers
*
* Smarty::addDefaultModifiers() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_AddDefaultModifiers
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Add default modifiers
*
* @api Smarty::addDefaultModifiers()
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param array|string $modifiers modifier or list of modifiers
* to add
*
* @return \Smarty|\Smarty_Internal_Template
*/
public function addDefaultModifiers(Smarty_Internal_TemplateBase $obj, $modifiers)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if (is_array($modifiers)) {
$this->default_modifiers = array_merge($smarty->default_modifiers, $modifiers);
} else {
$smarty->default_modifiers[] = $modifiers;
}
return $obj;
}
}

@ -0,0 +1,74 @@
<?php
/**
* Smarty Method Append
*
* Smarty::append() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_Append
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* appends values to template variables
*
* @api Smarty::append()
* @link http://www.smarty.net/docs/en/api.append.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param array|string $tpl_var the template variable name(s)
* @param mixed $value the value to append
* @param bool $merge flag if array elements shall be merged
* @param bool $nocache if true any output of this variable will
* be not cached
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public function append(Smarty_Internal_Data $data, $tpl_var, $value = null, $merge = false, $nocache = false)
{
if (is_array($tpl_var)) {
// $tpl_var is an array, ignore $value
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
$this->append($data, $_key, $_val, $merge, $nocache);
}
}
} else {
if ($tpl_var != '' && isset($value)) {
if (!isset($data->tpl_vars[$tpl_var])) {
$tpl_var_inst = $data->ext->getTemplateVars->_getVariable($data, $tpl_var, null, true, false);
if ($tpl_var_inst instanceof Smarty_Undefined_Variable) {
$data->tpl_vars[$tpl_var] = new Smarty_Variable(null, $nocache);
} else {
$data->tpl_vars[$tpl_var] = clone $tpl_var_inst;
}
}
if (!(is_array($data->tpl_vars[$tpl_var]->value) ||
$data->tpl_vars[$tpl_var]->value instanceof ArrayAccess)
) {
settype($data->tpl_vars[$tpl_var]->value, 'array');
}
if ($merge && is_array($value)) {
foreach ($value as $_mkey => $_mval) {
$data->tpl_vars[$tpl_var]->value[$_mkey] = $_mval;
}
} else {
$data->tpl_vars[$tpl_var]->value[] = $value;
}
}
if ($data->_objType == 2 && $data->scope) {
$data->ext->_updateScope->updateScope($data, $tpl_var);
}
}
return $data;
}
}

@ -0,0 +1,50 @@
<?php
/**
* Smarty Method AppendByRef
*
* Smarty::appendByRef() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_AppendByRef
{
/**
* appends values to template variables by reference
*
* @api Smarty::appendByRef()
* @link http://www.smarty.net/docs/en/api.append.by.ref.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $tpl_var the template variable name
* @param mixed &$value the referenced value to append
* @param bool $merge flag if array elements shall be merged
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public static function appendByRef(Smarty_Internal_Data $data, $tpl_var, &$value, $merge = false)
{
if ($tpl_var != '' && isset($value)) {
if (!isset($data->tpl_vars[$tpl_var])) {
$data->tpl_vars[$tpl_var] = new Smarty_Variable();
}
if (!is_array($data->tpl_vars[$tpl_var]->value)) {
settype($data->tpl_vars[$tpl_var]->value, 'array');
}
if ($merge && is_array($value)) {
foreach ($value as $_key => $_val) {
$data->tpl_vars[$tpl_var]->value[$_key] = &$value[$_key];
}
} else {
$data->tpl_vars[$tpl_var]->value[] = &$value;
}
if ($data->_objType == 2 && $data->scope) {
$data->ext->_updateScope->updateScope($data, $tpl_var);
}
}
return $data;
}
}

@ -0,0 +1,36 @@
<?php
/**
* Smarty Method AssignByRef
*
* Smarty::assignByRef() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_AssignByRef
{
/**
* assigns values to template variables by reference
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $tpl_var the template variable name
* @param $value
* @param boolean $nocache if true any output of this variable will be not cached
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public function assignByRef(Smarty_Internal_Data $data, $tpl_var, &$value, $nocache)
{
if ($tpl_var != '') {
$data->tpl_vars[$tpl_var] = new Smarty_Variable(null, $nocache);
$data->tpl_vars[$tpl_var]->value = &$value;
if ($data->_objType == 2 && $data->scope) {
$data->ext->_updateScope->updateScope($data, $tpl_var);
}
}
return $data;
}
}

@ -0,0 +1,43 @@
<?php
/**
* Smarty Method AssignGlobal
*
* Smarty::assignGlobal() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_AssignGlobal
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* assigns a global Smarty variable
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $varName the global variable name
* @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public function assignGlobal(Smarty_Internal_Data $data, $varName, $value = null, $nocache = false)
{
if ($varName != '') {
Smarty::$global_tpl_vars[$varName] = new Smarty_Variable($value, $nocache);
$ptr = $data;
while ($ptr->_objType == 2) {
$ptr->tpl_vars[$varName] = clone Smarty::$global_tpl_vars[$varName];
$ptr = $ptr->parent;
}
}
return $data;
}
}

@ -0,0 +1,37 @@
<?php
/**
* Smarty Method ClearAllAssign
*
* Smarty::clearAllAssign() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ClearAllAssign
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* clear all the assigned template variables.
*
* @api Smarty::clearAllAssign()
* @link http://www.smarty.net/docs/en/api.clear.all.assign.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public function clearAllAssign(Smarty_Internal_Data $data)
{
$data->tpl_vars = array();
return $data;
}
}

@ -0,0 +1,40 @@
<?php
/**
* Smarty Method ClearAllCache
*
* Smarty::clearAllCache() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ClearAllCache
{
/**
* Valid for Smarty object
*
* @var int
*/
public $objMap = 1;
/**
* Empty cache folder
*
* @api Smarty::clearAllCache()
* @link http://www.smarty.net/docs/en/api.clear.all.cache.tpl
*
* @param \Smarty $smarty
* @param integer $exp_time expiration time
* @param string $type resource type
*
* @return integer number of cache files deleted
*/
public function clearAllCache(Smarty $smarty, $exp_time = null, $type = null)
{
// load cache resource and call clearAll
$_cache_resource = Smarty_CacheResource::load($smarty, $type);
$_cache_resource->invalidLoadedCache($smarty);
return $_cache_resource->clearAll($smarty, $exp_time);
}
}

@ -0,0 +1,44 @@
<?php
/**
* Smarty Method ClearAssign
*
* Smarty::clearAssign() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ClearAssign
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* clear the given assigned template variable(s).
*
* @api Smarty::clearAssign()
* @link http://www.smarty.net/docs/en/api.clear.assign.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string|array $tpl_var the template variable(s) to clear
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public function clearAssign(Smarty_Internal_Data $data, $tpl_var)
{
if (is_array($tpl_var)) {
foreach ($tpl_var as $curr_var) {
unset($data->tpl_vars[$curr_var]);
}
} else {
unset($data->tpl_vars[$tpl_var]);
}
return $data;
}
}

@ -0,0 +1,43 @@
<?php
/**
* Smarty Method ClearCache
*
* Smarty::clearCache() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ClearCache
{
/**
* Valid for Smarty object
*
* @var int
*/
public $objMap = 1;
/**
* Empty cache for a specific template
*
* @api Smarty::clearCache()
* @link http://www.smarty.net/docs/en/api.clear.cache.tpl
*
* @param \Smarty $smarty
* @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(Smarty $smarty, $template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
{
// load cache resource and call clear
$_cache_resource = Smarty_CacheResource::load($smarty, $type);
$_cache_resource->invalidLoadedCache($smarty);
return $_cache_resource->clear($smarty, $template_name, $cache_id, $compile_id, $exp_time);
}
}

@ -0,0 +1,124 @@
<?php
/**
* Smarty Method ClearCompiledTemplate
*
* Smarty::clearCompiledTemplate() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ClearCompiledTemplate
{
/**
* Valid for Smarty object
*
* @var int
*/
public $objMap = 1;
/**
* Delete compiled template file
*
* @api Smarty::clearCompiledTemplate()
* @link http://www.smarty.net/docs/en/api.clear.compiled.template.tpl
*
* @param \Smarty $smarty
* @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(Smarty $smarty, $resource_name = null, $compile_id = null, $exp_time = null)
{
$_compile_dir = $smarty->getCompileDir();
if ($_compile_dir == '/') { //We should never want to delete this!
return 0;
}
$_compile_id = isset($compile_id) ? preg_replace('![^\w]+!', '_', $compile_id) : null;
$_dir_sep = $smarty->use_sub_dirs ? DS : '^';
if (isset($resource_name)) {
$_save_stat = $smarty->caching;
$smarty->caching = false;
/* @var Smarty_Internal_Template $tpl */
$tpl = new $smarty->template_class($resource_name, $smarty);
$smarty->caching = $_save_stat;
if ($tpl->source->exists) {
// remove from compileds cache
$tpl->source->compileds = array();
$_resource_part_1 = basename(str_replace('^', DS, $tpl->compiled->filepath));
$_resource_part_1_length = strlen($_resource_part_1);
} else {
return 0;
}
$_resource_part_2 = str_replace('.php', '.cache.php', $_resource_part_1);
$_resource_part_2_length = strlen($_resource_part_2);
}
$_dir = $_compile_dir;
if ($smarty->use_sub_dirs && isset($_compile_id)) {
$_dir .= $_compile_id . $_dir_sep;
}
if (isset($_compile_id)) {
$_compile_id_part = $_compile_dir . $_compile_id . $_dir_sep;
$_compile_id_part_length = strlen($_compile_id_part);
}
$_count = 0;
try {
$_compileDirs = new RecursiveDirectoryIterator($_dir);
// NOTE: UnexpectedValueException thrown for PHP >= 5.3
}
catch (Exception $e) {
return 0;
}
$_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($_compile as $_file) {
if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) {
continue;
}
$_filepath = (string) $_file;
if ($_file->isDir()) {
if (!$_compile->isDot()) {
// delete folder if empty
@rmdir($_file->getPathname());
}
} else {
$unlink = false;
if ((!isset($_compile_id) || (isset($_filepath[$_compile_id_part_length]) &&
$a = !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length))) &&
(!isset($resource_name) || (isset($_filepath[$_resource_part_1_length]) &&
substr_compare($_filepath, $_resource_part_1, - $_resource_part_1_length,
$_resource_part_1_length) == 0) ||
(isset($_filepath[$_resource_part_2_length]) &&
substr_compare($_filepath, $_resource_part_2, - $_resource_part_2_length,
$_resource_part_2_length) == 0))
) {
if (isset($exp_time)) {
if (time() - @filemtime($_filepath) >= $exp_time) {
$unlink = true;
}
} else {
$unlink = true;
}
}
if ($unlink && @unlink($_filepath)) {
$_count ++;
if (function_exists('opcache_invalidate')) {
opcache_invalidate($_filepath);
}
}
}
}
// clear template objects cache
$smarty->_cache['isCached'] = array();
if (isset($smarty->ext->_subtemplate)) {
$smarty->ext->_subtemplate->tplObjects = array();
}
return $_count;
}
}

@ -0,0 +1,41 @@
<?php
/**
* Smarty Method ClearConfig
*
* Smarty::clearConfig() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ClearConfig
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* clear a single or all config variables
*
* @api Smarty::clearConfig()
* @link http://www.smarty.net/docs/en/api.clear.config.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string|null $name variable name or null
*
* @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty
*/
public function clearConfig(Smarty_Internal_Data $data, $name = null)
{
if (isset($name)) {
unset($data->config_vars[$name]);
} else {
$data->config_vars = array();
}
return $data;
}
}

@ -0,0 +1,32 @@
<?php
/**
* Smarty Method CompileAllConfig
*
* Smarty::compileAllConfig() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_CompileAllConfig extends Smarty_Internal_Method_CompileAllTemplates
{
/**
* Compile all config files
*
* @api Smarty::compileAllConfig()
*
* @param \Smarty $smarty
* @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(Smarty $smarty, $extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null)
{
return $this->compileAll($smarty, $extension, $force_compile, $time_limit, $max_errors, true);
}
}

@ -0,0 +1,111 @@
<?php
/**
* Smarty Method CompileAllTemplates
*
* Smarty::compileAllTemplates() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_CompileAllTemplates
{
/**
* Valid for Smarty object
*
* @var int
*/
public $objMap = 1;
/**
* Compile all template files
*
* @api Smarty::compileAllTemplates()
*
* @param \Smarty $smarty
* @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(Smarty $smarty, $extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
{
return $this->compileAll($smarty, $extension, $force_compile, $time_limit, $max_errors);
}
/**
* Compile all template or config files
*
* @param \Smarty $smarty
* @param string $extension template file name extension
* @param bool $force_compile force all to recompile
* @param int $time_limit set maximum execution time
* @param int $max_errors set maximum allowed errors
* @param bool $isConfig flag true if called for config files
*
* @return int number of template files compiled
*/
protected function compileAll(Smarty $smarty, $extension, $force_compile, $time_limit, $max_errors, $isConfig = false)
{
// switch off time limit
if (function_exists('set_time_limit')) {
@set_time_limit($time_limit);
}
$_count = 0;
$_error_count = 0;
$sourceDir = $isConfig ? $smarty->getConfigDir() : $smarty->getTemplateDir();
// loop over array of source directories
foreach ($sourceDir as $_dir) {
$_dir_1 = new RecursiveDirectoryIterator($_dir);
$_dir_2 = new RecursiveIteratorIterator($_dir_1);
foreach ($_dir_2 as $_fileinfo) {
$_file = $_fileinfo->getFilename();
if (substr(basename($_fileinfo->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) {
continue;
}
if (!substr_compare($_file, $extension, - strlen($extension)) == 0) {
continue;
}
if ($_fileinfo->getPath() == !substr($_dir, 0, - 1)) {
$_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file;
}
echo "\n<br>", $_dir, '---', $_file;
flush();
$_start_time = microtime(true);
$_smarty = clone $smarty;
$_smarty->force_compile = $force_compile;
try {
/* @var Smarty_Internal_Template $_tpl */
$_tpl = new $smarty->template_class($_file, $_smarty);
$_tpl->caching = Smarty::CACHING_OFF;
$_tpl->source = $isConfig ? Smarty_Template_Config::load($_tpl) : Smarty_Template_Source::load($_tpl);
if ($_tpl->mustCompile()) {
$_tpl->compileTemplateSource();
$_count ++;
echo ' compiled in ', microtime(true) - $_start_time, ' seconds';
flush();
} else {
echo ' is up to date';
flush();
}
}
catch (Exception $e) {
echo "\n<br> ------>Error: ", $e->getMessage(), "<br><br>\n";
$_error_count ++;
}
// free memory
unset($_tpl);
$_smarty->_cache['template_objects'] = array();
if ($max_errors !== null && $_error_count == $max_errors) {
echo "\n<br><br>too many errors\n";
exit();
}
}
}
echo "\n<br>";
return $_count;
}
}

@ -0,0 +1,182 @@
<?php
/**
* Smarty Method ConfigLoad
*
* Smarty::configLoad() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_ConfigLoad
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* load a config file, optionally load just selected sections
*
* @api Smarty::configLoad()
* @link http://www.smarty.net/docs/en/api.config.load.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $config_file filename
* @param mixed $sections array of section names, single
* section or null
*
* @return \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template
* @throws \SmartyException
*/
public function configLoad(Smarty_Internal_Data $data, $config_file, $sections = null)
{
$this->_loadConfigFile($data, $config_file, $sections, 0);
return $data;
}
/**
* load a config file, optionally load just selected sections
*
* @api Smarty::configLoad()
* @link http://www.smarty.net/docs/en/api.config.load.tpl
*
* @param \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template $data
* @param string $config_file filename
* @param mixed $sections array of section names, single
* section or null
* @param int $scope scope into which config variables
* shall be loaded
*
* @return \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template
* @throws \SmartyException
*/
public function _loadConfigFile(Smarty_Internal_Data $data, $config_file, $sections = null, $scope = 0)
{
/* @var \Smarty $smarty */
$smarty = isset($data->smarty) ? $data->smarty : $data;
/* @var \Smarty_Internal_Template $confObj */
$confObj = new Smarty_Internal_Template($config_file, $smarty, $data);
$confObj->caching = Smarty::CACHING_OFF;
$confObj->source = Smarty_Template_Config::load($confObj);
$confObj->source->config_sections = $sections;
$confObj->source->scope = $scope;
$confObj->compiled = Smarty_Template_Compiled::load($confObj);
$confObj->compiled->render($confObj);
if ($data->_objType == 2) {
$data->compiled->file_dependency[$confObj->source->uid] =
array($confObj->source->filepath, $confObj->source->getTimeStamp(), $confObj->source->type);
}
}
/**
* load config variables into template object
*
* @param \Smarty_Internal_Template $tpl
* @param array $_config_vars
*
*/
public function _loadConfigVars(Smarty_Internal_Template $tpl, $_config_vars)
{
$this->_assignConfigVars($tpl->parent, $tpl, $_config_vars);
$scope = $tpl->source->scope;
if (!$scope && !$tpl->scope) {
return;
}
foreach (array($scope, $tpl->scope) as $s) {
$s = ($bubble_up = $s >= Smarty::SCOPE_BUBBLE_UP) ? $s - Smarty::SCOPE_BUBBLE_UP : $s;
if ($bubble_up && $s) {
$ptr = $tpl->parent->parent;
if (isset($ptr)) {
$this->_assignConfigVars($ptr, $tpl, $_config_vars);
$ptr = $ptr->parent;
}
if ($s == Smarty::SCOPE_PARENT) {
continue;
}
while (isset($ptr) && $ptr->_objType == 2) {
$this->_assignConfigVars($ptr, $tpl, $_config_vars);
$ptr = $ptr->parent;
}
if ($s == Smarty::SCOPE_TPL_ROOT) {
continue;
} elseif ($s == Smarty::SCOPE_SMARTY) {
$this->_assignConfigVars($tpl->smarty, $tpl, $_config_vars);
} elseif ($s == Smarty::SCOPE_GLOBAL) {
$this->_assignConfigVars($tpl->smarty, $tpl, $_config_vars);
} elseif ($s == Smarty::SCOPE_ROOT) {
while (isset($ptr->parent)) {
$ptr = $ptr->parent;
}
$this->_assignConfigVars($ptr, $tpl, $_config_vars);
}
}
}
}
/**
* Assign all config variables in given scope
*
* @param \Smarty_Internal_Data $scope_ptr
* @param \Smarty_Internal_Template $tpl
* @param array $_config_vars
*/
public function _assignConfigVars(Smarty_Internal_Data $scope_ptr, Smarty_Internal_Template $tpl, $_config_vars)
{
// copy global config vars
foreach ($_config_vars['vars'] as $variable => $value) {
if ($tpl->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] =
array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
// scan sections
$sections = $tpl->source->config_sections;
if (!empty($sections)) {
foreach ((array) $sections as $tpl_section) {
if (isset($_config_vars['sections'][$tpl_section])) {
foreach ($_config_vars['sections'][$tpl_section]['vars'] as $variable => $value) {
if ($tpl->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] =
array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
}
}
}
}
/**
* gets a config variable value
*
* @param \Smarty_Internal_Template $tpl template object
* @param string $varName the name of the config variable
* @param bool $errorEnable
*
* @return mixed the value of the config variable
*/
public function _getConfigVariable(Smarty_Internal_Template $tpl, $varName, $errorEnable = true)
{
$_ptr = $tpl;
while ($_ptr !== null) {
if (isset($_ptr->config_vars[$varName])) {
// found it, return it
return $_ptr->config_vars[$varName];
}
// not found, try at parent
$_ptr = $_ptr->parent;
}
if ($tpl->smarty->error_unassigned && $errorEnable) {
// force a notice
$x = $$varName;
}
return null;
}
}

@ -0,0 +1,44 @@
<?php
/**
* Smarty Method CreateData
*
* Smarty::createData() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_CreateData
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* creates a data object
*
* @api Smarty::createData()
* @link http://www.smarty.net/docs/en/api.create.data.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param \Smarty_Internal_Template|\Smarty_Internal_Data|\Smarty_Data|\Smarty $parent next higher level of Smarty
* variables
* @param string $name optional data block name
*
* @returns Smarty_Data data object
*/
public function createData(Smarty_Internal_TemplateBase $obj, Smarty_Internal_Data $parent = null, $name = null)
{
/* @var Smarty $smarty */
$smarty = isset($this->smarty) ? $this->smarty : $obj;
$dataObj = new Smarty_Data($parent, $smarty, $name);
if ($smarty->debugging) {
Smarty_Internal_Debug::register_data($dataObj);
}
return $dataObj;
}
}

@ -0,0 +1,37 @@
<?php
/**
* Smarty Method GetAutoloadFilters
*
* Smarty::getAutoloadFilters() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetAutoloadFilters extends Smarty_Internal_Method_SetAutoloadFilters
{
/**
* Get autoload filters
*
* @api Smarty::getAutoloadFilters()
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $type type of filter to get auto loads
* for. Defaults to all autoload
* filters
*
* @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type
* was specified
*/
public function getAutoloadFilters(Smarty_Internal_TemplateBase $obj, $type = null)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if ($type !== null) {
$this->_checkFilterType($type);
return isset($smarty->autoload_filters[$type]) ? $smarty->autoload_filters[$type] : array();
}
return $smarty->autoload_filters;
}
}

@ -0,0 +1,58 @@
<?php
/**
* Smarty Method GetConfigVars
*
* Smarty::getConfigVars() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetConfigVars
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* Returns a single or all config variables
*
* @api Smarty::getConfigVars()
* @link http://www.smarty.net/docs/en/api.get.config.vars.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $varname variable name or null
* @param bool $search_parents include parent templates?
*
* @return mixed variable value or or array of variables
*/
public function getConfigVars(Smarty_Internal_Data $data, $varname = null, $search_parents = true)
{
$_ptr = $data;
$var_array = array();
while ($_ptr !== null) {
if (isset($varname)) {
if (isset($_ptr->config_vars[$varname])) {
return $_ptr->config_vars[$varname];
}
} else {
$var_array = array_merge($_ptr->config_vars, $var_array);
}
// not found, try at parent
if ($search_parents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if (isset($varname)) {
return '';
} else {
return $var_array;
}
}
}

@ -0,0 +1,35 @@
<?php
/**
* Smarty Method GetDebugTemplate
*
* Smarty::getDebugTemplate() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetDebugTemplate
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* return name of debugging template
*
* @api Smarty::getDebugTemplate()
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
*
* @return string
*/
public function getDebugTemplate(Smarty_Internal_TemplateBase $obj)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
return $smarty->debug_tpl;
}
}

@ -0,0 +1,35 @@
<?php
/**
* Smarty Method GetDefaultModifiers
*
* Smarty::getDefaultModifiers() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetDefaultModifiers
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Get default modifiers
*
* @api Smarty::getDefaultModifiers()
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
*
* @return array list of default modifiers
*/
public function getDefaultModifiers(Smarty_Internal_TemplateBase $obj)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
return $smarty->default_modifiers;
}
}

@ -0,0 +1,44 @@
<?php
/**
* Smarty Method GetRegisteredObject
*
* Smarty::getRegisteredObject() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetRegisteredObject
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* return a reference to a registered object
*
* @api Smarty::getRegisteredObject()
* @link http://www.smarty.net/docs/en/api.get.registered.object.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $object_name object name
*
* @return object
* @throws \SmartyException if no such object is found
*/
public function getRegisteredObject(Smarty_Internal_TemplateBase $obj, $object_name)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if (!isset($smarty->registered_objects[$object_name])) {
throw new SmartyException("'$object_name' is not a registered object");
}
if (!is_object($smarty->registered_objects[$object_name][0])) {
throw new SmartyException("registered '$object_name' is not an object");
}
return $smarty->registered_objects[$object_name][0];
}
}

@ -0,0 +1,51 @@
<?php
/**
* Smarty Method GetStreamVariable
*
* Smarty::getStreamVariable() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetStreamVariable
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* gets a stream variable
*
* @api Smarty::getStreamVariable()
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $variable the stream of the variable
*
* @return mixed
* @throws \SmartyException
*/
public function getStreamVariable(Smarty_Internal_Data $data, $variable)
{
$_result = '';
$fp = fopen($variable, 'r+');
if ($fp) {
while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
$_result .= $current_line;
}
fclose($fp);
return $_result;
}
$smarty = isset($data->smarty) ? $data->smarty : $data;
if ($smarty->error_unassigned) {
throw new SmartyException('Undefined stream variable "' . $variable . '"');
} else {
return null;
}
}
}

@ -0,0 +1,62 @@
<?php
/**
* Smarty Method GetTags
*
* Smarty::getTags() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetTags
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Return array of tag/attributes of all tags used by an template
*
* @api Smarty::getTags()
* @link http://www.smarty.net/docs/en/api.get.tags.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param null|string|Smarty_Internal_Template $template
*
* @return array of tag/attributes
* @throws \SmartyException
*/
public function getTags(Smarty_Internal_TemplateBase $obj, $template = null)
{
/* @var Smarty $smarty */
$smarty = isset($this->smarty) ? $this->smarty : $obj;
if ($obj->_objType == 2 && !isset($template)) {
$tpl = clone $obj;
} elseif (isset($template) && $template->_objType == 2) {
$tpl = clone $template;
} elseif (isset($template) && is_string($template)) {
/* @var Smarty_Internal_Template $tpl */
$tpl = new $smarty->template_class($template, $smarty);
// checks if template exists
if (!$tpl->source->exists) {
throw new SmartyException("Unable to load template {$tpl->source->type} '{$tpl->source->name}'");
}
}
if (isset($tpl)) {
$tpl->smarty = clone $tpl->smarty;
$tpl->smarty->_cache['get_used_tags'] = true;
$tpl->_cache['used_tags'] = array();
$tpl->smarty->merge_compiled_includes = false;
$tpl->smarty->disableSecurity();
$tpl->caching = false;
$tpl->loadCompiler();
$tpl->compiler->compileTemplate($tpl);
return $tpl->_cache['used_tags'];
}
throw new SmartyException("Missing template specification");
}
}

@ -0,0 +1,114 @@
<?php
/**
* Smarty Method GetTemplateVars
*
* Smarty::getTemplateVars() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_GetTemplateVars
{
/**
* Valid for all objects
*
* @var int
*/
public $objMap = 7;
/**
* Returns a single or all template variables
*
* @api Smarty::getTemplateVars()
* @link http://www.smarty.net/docs/en/api.get.template.vars.tpl
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $varName variable name or null
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $_ptr optional pointer to data object
* @param bool $searchParents include parent templates?
*
* @return mixed variable value or or array of variables
*/
public function getTemplateVars(Smarty_Internal_Data $data, $varName = null, Smarty_Internal_Data $_ptr = null, $searchParents = true)
{
if (isset($varName)) {
$_var = $this->_getVariable($data, $varName, $_ptr, $searchParents, false);
if (is_object($_var)) {
return $_var->value;
} else {
return null;
}
} else {
$_result = array();
if ($_ptr === null) {
$_ptr = $data;
}
while ($_ptr !== null) {
foreach ($_ptr->tpl_vars AS $key => $var) {
if (!array_key_exists($key, $_result)) {
$_result[$key] = $var->value;
}
}
// not found, try at parent
if ($searchParents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if ($searchParents && isset(Smarty::$global_tpl_vars)) {
foreach (Smarty::$global_tpl_vars AS $key => $var) {
if (!array_key_exists($key, $_result)) {
$_result[$key] = $var->value;
}
}
}
return $_result;
}
}
/**
* gets the object of a Smarty variable
*
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data
* @param string $varName the name of the Smarty variable
* @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $_ptr optional pointer to data object
* @param bool $searchParents search also in parent data
* @param bool $errorEnable
*
* @return \Smarty_Variable
*/
public function _getVariable(Smarty_Internal_Data $data, $varName, Smarty_Internal_Data $_ptr = null, $searchParents = true, $errorEnable = true)
{
if ($_ptr === null) {
$_ptr = $data;
}
while ($_ptr !== null) {
if (isset($_ptr->tpl_vars[$varName])) {
// found it, return it
return $_ptr->tpl_vars[$varName];
}
// not found, try at parent
if ($searchParents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if (isset(Smarty::$global_tpl_vars[$varName])) {
// found it, return it
return Smarty::$global_tpl_vars[$varName];
}
/* @var \Smarty $smarty */
$smarty = isset($data->smarty) ? $data->smarty : $data;
if ($smarty->error_unassigned && $errorEnable) {
// force a notice
$x = $$varName;
}
return new Smarty_Undefined_Variable;
}
}

@ -0,0 +1,77 @@
<?php
/**
* Smarty Method LoadFilter
*
* Smarty::loadFilter() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_LoadFilter
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Valid filter types
*
* @var array
*/
private $filterTypes = array('pre' => true, 'post' => true, 'output' => true, 'variable' => true);
/**
* load a filter of specified type and name
*
* @api Smarty::loadFilter()
*
* @link http://www.smarty.net/docs/en/api.load.filter.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $type filter type
* @param string $name filter name
*
* @return bool
* @throws SmartyException if filter could not be loaded
*/
public function loadFilter(Smarty_Internal_TemplateBase $obj, $type, $name)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
$this->_checkFilterType($type);
$_plugin = "smarty_{$type}filter_{$name}";
$_filter_name = $_plugin;
if (is_callable($_plugin)) {
$smarty->registered_filters[$type][$_filter_name] = $_plugin;
return true;
}
if ($smarty->loadPlugin($_plugin)) {
if (class_exists($_plugin, false)) {
$_plugin = array($_plugin, 'execute');
}
if (is_callable($_plugin)) {
$smarty->registered_filters[$type][$_filter_name] = $_plugin;
return true;
}
}
throw new SmartyException("{$type}filter \"{$name}\" not found or callable");
}
/**
* Check if filter type is valid
*
* @param string $type
*
* @throws \SmartyException
*/
public function _checkFilterType($type)
{
if (!isset($this->filterTypes[$type])) {
throw new SmartyException("Illegal filter type \"{$type}\"");
}
}
}

@ -0,0 +1,111 @@
<?php
/**
* Smarty Extension Loadplugin
*
* $smarty->loadPlugin() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_LoadPlugin
{
/**
* Cache of searched plugin files
*
* @var array
*/
public $plugin_files = array();
/**
* Takes unknown classes and loads plugin files for them
* class name format: Smarty_PluginType_PluginName
* plugin filename format: plugintype.pluginname.php
*
* @param \Smarty $smarty
* @param string $plugin_name class plugin name to load
* @param bool $check check if already loaded
*
* @return bool|string
* @throws \SmartyException
*/
public function loadPlugin(Smarty $smarty, $plugin_name, $check)
{
// if function or class exists, exit silently (already loaded)
if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) {
return true;
}
if (!preg_match('#^smarty_((internal)|([^_]+))_(.+)$#i', $plugin_name, $match)) {
throw new SmartyException("plugin {$plugin_name} is not a valid name format");
}
if (!empty($match[2])) {
$file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php';
if (isset($this->plugin_files[$file])) {
if ($this->plugin_files[$file] !== false) {
return $this->plugin_files[$file];
} else {
return false;
}
} else {
if (is_file($file)) {
$this->plugin_files[$file] = $file;
require_once($file);
return $file;
} else {
$this->plugin_files[$file] = false;
return false;
}
}
}
// plugin filename is expected to be: [type].[name].php
$_plugin_filename = "{$match[1]}.{$match[4]}.php";
$_lower_filename = strtolower($_plugin_filename);
if (isset($this->plugin_files)) {
if (isset($this->plugin_files['plugins_dir'][$_lower_filename])) {
if (!$smarty->use_include_path || $this->plugin_files['plugins_dir'][$_lower_filename] !== false) {
return $this->plugin_files['plugins_dir'][$_lower_filename];
}
}
if (!$smarty->use_include_path || $smarty->ext->_getIncludePath->isNewIncludePath($smarty)) {
unset($this->plugin_files['include_path']);
} else {
if (isset($this->plugin_files['include_path'][$_lower_filename])) {
return $this->plugin_files['include_path'][$_lower_filename];
}
}
}
$_file_names = array($_plugin_filename);
if ($_lower_filename != $_plugin_filename) {
$_file_names[] = $_lower_filename;
}
$_p_dirs = $smarty->getPluginsDir();
if (!isset($this->plugin_files['plugins_dir'][$_lower_filename])) {
// loop through plugin dirs and find the plugin
foreach ($_p_dirs as $_plugin_dir) {
foreach ($_file_names as $name) {
$file = $_plugin_dir . $name;
if (is_file($file)) {
$this->plugin_files['plugins_dir'][$_lower_filename] = $file;
require_once($file);
return $file;
}
$this->plugin_files['plugins_dir'][$_lower_filename] = false;
}
}
}
if ($smarty->use_include_path) {
foreach ($_file_names as $_file_name) {
// try PHP include_path
$file = $smarty->ext->_getIncludePath->getIncludePath($_p_dirs, $_file_name, $smarty);
$this->plugin_files['include_path'][$_lower_filename] = $file;
if ($file !== false) {
require_once($file);
return $file;
}
}
}
// no plugin loaded
return false;
}
}

@ -0,0 +1,49 @@
<?php
/**
* Smarty Method UnloadFilter
*
* Smarty_Internal_Template::mustCompile() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_MustCompile
{
/**
* Valid for template object
*
* @var int
*/
public $objMap = 2;
/**
* Returns if the current template must be compiled by the Smarty compiler
* It does compare the timestamps of template source and the compiled templates and checks the force compile
* configuration
*
* @param \Smarty_Internal_Template $_template
*
* @return bool
* @throws \SmartyException
*/
public function mustCompile(Smarty_Internal_Template $_template)
{
if (!$_template->source->exists) {
if (isset($_template->parent) && $_template->parent->_objType == 2) {
$parent_resource = " in '$_template->parent->template_resource}'";
} else {
$parent_resource = '';
}
throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}");
}
if ($_template->mustCompile === null) {
$_template->mustCompile = (!$_template->source->handler->uncompiled &&
($_template->smarty->force_compile || $_template->source->handler->recompiled || !$_template->compiled->exists ||
($_template->smarty->compile_check && $_template->compiled->getTimeStamp() < $_template->source->getTimeStamp())));
}
return $_template->mustCompile;
}
}

@ -0,0 +1,39 @@
<?php
/**
* Smarty Method RegisterCacheResource
*
* Smarty::registerCacheResource() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterCacheResource
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Registers a resource to fetch a template
*
* @api Smarty::registerCacheResource()
* @link http://www.smarty.net/docs/en/api.register.cacheresource.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $name name of resource type
* @param \Smarty_CacheResource $resource_handler
*
* @return \Smarty|\Smarty_Internal_Template
*/
public function registerCacheResource(Smarty_Internal_TemplateBase $obj, $name, Smarty_CacheResource $resource_handler)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
$smarty->registered_cache_resources[$name] = $resource_handler;
return $obj;
}
}

@ -0,0 +1,46 @@
<?php
/**
* Smarty Method RegisterClass
*
* Smarty::registerClass() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterClass
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Registers static classes to be used in templates
*
* @api Smarty::registerClass()
* @link http://www.smarty.net/docs/en/api.register.class.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $class_name
* @param string $class_impl the referenced PHP class to
* register
*
* @return \Smarty|\Smarty_Internal_Template
* @throws \SmartyException
*/
public function registerClass(Smarty_Internal_TemplateBase $obj, $class_name, $class_impl)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
// test if exists
if (!class_exists($class_impl)) {
throw new SmartyException("Undefined class '$class_impl' in register template class");
}
// register the class
$smarty->registered_classes[$class_name] = $class_impl;
return $obj;
}
}

@ -0,0 +1,42 @@
<?php
/**
* Smarty Method RegisterDefaultConfigHandler
*
* Smarty::registerDefaultConfigHandler() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterDefaultConfigHandler
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Register config default handler
*
* @api Smarty::registerDefaultConfigHandler()
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param callable $callback class/method name
*
* @return \Smarty|\Smarty_Internal_Template
* @throws SmartyException if $callback is not callable
*/
public function registerDefaultConfigHandler(Smarty_Internal_TemplateBase $obj, $callback)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if (is_callable($callback)) {
$smarty->default_config_handler_func = $callback;
} else {
throw new SmartyException("Default config handler not callable");
}
return $obj;
}
}

@ -0,0 +1,43 @@
<?php
/**
* Smarty Method RegisterDefaultPluginHandler
*
* Smarty::registerDefaultPluginHandler() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterDefaultPluginHandler
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Registers a default plugin handler
*
* @api Smarty::registerDefaultPluginHandler()
* @link http://www.smarty.net/docs/en/api.register.default.plugin.handler.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param callable $callback class/method name
*
* @return \Smarty|\Smarty_Internal_Template
* @throws SmartyException if $callback is not callable
*/
public function registerDefaultPluginHandler(Smarty_Internal_TemplateBase $obj, $callback)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if (is_callable($callback)) {
$smarty->default_plugin_handler_func = $callback;
} else {
throw new SmartyException("Default plugin handler '$callback' not callable");
}
return $obj;
}
}

@ -0,0 +1,72 @@
<?php
/**
* Smarty Method RegisterDefaultTemplateHandler
*
* Smarty::registerDefaultTemplateHandler() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterDefaultTemplateHandler
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Register template default handler
*
* @api Smarty::registerDefaultTemplateHandler()
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param callable $callback class/method name
*
* @return \Smarty|\Smarty_Internal_Template
* @throws SmartyException if $callback is not callable
*/
public function registerDefaultTemplateHandler(Smarty_Internal_TemplateBase $obj, $callback)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if (is_callable($callback)) {
$smarty->default_template_handler_func = $callback;
} else {
throw new SmartyException("Default template handler not callable");
}
return $obj;
}
/**
* get default content from template or config resource handler
*
* @param Smarty_Template_Source $source
*/
public static function _getDefaultTemplate(Smarty_Template_Source $source)
{
if ($source->isConfig) {
$default_handler = $source->smarty->default_config_handler_func;
} else {
$default_handler = $source->smarty->default_template_handler_func;
}
$_content = $_timestamp = null;
$_return = call_user_func_array($default_handler, array($source->type, $source->name, &$_content, &$_timestamp,
$source->smarty));
if (is_string($_return)) {
$source->exists = is_file($_return);
if ($source->exists) {
$source->timestamp = filemtime($_return);
}
$source->filepath = $_return;
} elseif ($_return === true) {
$source->content = $_content;
$source->timestamp = $_timestamp;
$source->exists = true;
$source->handler->recompiled = true;
$source->filepath = false;
}
}
}

@ -0,0 +1,88 @@
<?php
/**
* Smarty Method RegisterFilter
*
* Smarty::registerFilter() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterFilter
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Valid filter types
*
* @var array
*/
private $filterTypes = array('pre' => true, 'post' => true, 'output' => true, 'variable' => true);
/**
* Registers a filter function
*
* @api Smarty::registerFilter()
*
* @link http://www.smarty.net/docs/en/api.register.filter.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $type filter type
* @param callback $callback
* @param string|null $name optional filter name
*
* @return \Smarty|\Smarty_Internal_Template
* @throws \SmartyException
*/
public function registerFilter(Smarty_Internal_TemplateBase $obj, $type, $callback, $name = null)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
$this->_checkFilterType($type);
$name = isset($name) ? $name : $this->_getFilterName($callback);
if (!is_callable($callback)) {
throw new SmartyException("{$type}filter \"{$name}\" not callable");
}
$smarty->registered_filters[$type][$name] = $callback;
return $obj;
}
/**
* Return internal filter name
*
* @param callback $function_name
*
* @return string internal filter name
*/
public function _getFilterName($function_name)
{
if (is_array($function_name)) {
$_class_name = (is_object($function_name[0]) ? get_class($function_name[0]) : $function_name[0]);
return $_class_name . '_' . $function_name[1];
} elseif (is_string($function_name)) {
return $function_name;
} else {
return 'closure';
}
}
/**
* Check if filter type is valid
*
* @param string $type
*
* @throws \SmartyException
*/
public function _checkFilterType($type)
{
if (!isset($this->filterTypes[$type])) {
throw new SmartyException("Illegal filter type \"{$type}\"");
}
}
}

@ -0,0 +1,71 @@
<?php
/**
* Smarty Method RegisterObject
*
* Smarty::registerObject() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterObject
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Registers object to be used in templates
*
* @api Smarty::registerObject()
* @link http://www.smarty.net/docs/en/api.register.object.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $object_name
* @param object $object the
* referenced
* PHP object to
* register
* @param array $allowed_methods_properties list of
* allowed
* methods
* (empty = all)
* @param bool $format smarty
* argument
* format, else
* traditional
* @param array $block_methods list of
* block-methods
*
* @return \Smarty|\Smarty_Internal_Template
* @throws \SmartyException
*/
public function registerObject(Smarty_Internal_TemplateBase $obj, $object_name, $object, $allowed_methods_properties = array(), $format = true, $block_methods = array())
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
// test if allowed methods callable
if (!empty($allowed_methods_properties)) {
foreach ((array) $allowed_methods_properties as $method) {
if (!is_callable(array($object, $method)) && !property_exists($object, $method)) {
throw new SmartyException("Undefined method or property '$method' in registered object");
}
}
}
// test if block methods callable
if (!empty($block_methods)) {
foreach ((array) $block_methods as $method) {
if (!is_callable(array($object, $method))) {
throw new SmartyException("Undefined method '$method' in registered object");
}
}
}
// register the object
$smarty->registered_objects[$object_name] = array($object, (array) $allowed_methods_properties,
(boolean) $format, (array) $block_methods);
return $obj;
}
}

@ -0,0 +1,50 @@
<?php
/**
* Smarty Method RegisterPlugin
*
* Smarty::registerPlugin() method
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Method_RegisterPlugin
{
/**
* Valid for Smarty and template object
*
* @var int
*/
public $objMap = 3;
/**
* Registers plugin to be used in templates
*
* @api Smarty::registerPlugin()
* @link http://www.smarty.net/docs/en/api.register.plugin.tpl
*
* @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
* @param string $type plugin type
* @param string $name name of template tag
* @param callback $callback PHP callback to register
* @param bool $cacheable if true (default) this
* function is cache able
* @param mixed $cache_attr caching attributes if any
*
* @return \Smarty|\Smarty_Internal_Template
* @throws SmartyException when the plugin tag is invalid
*/
public function registerPlugin(Smarty_Internal_TemplateBase $obj, $type, $name, $callback, $cacheable = true, $cache_attr = null)
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
if (isset($smarty->registered_plugins[$type][$name])) {
throw new SmartyException("Plugin tag \"{$name}\" already registered");
} elseif (!is_callable($callback)) {
throw new SmartyException("Plugin \"{$name}\" not callable");
} else {
$smarty->registered_plugins[$type][$name] = array($callback, (bool) $cacheable, (array) $cache_attr);
}
return $obj;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save