diff --git a/Smarty.addons.php b/Smarty.addons.php
index 61cdfab6..c5557ab9 100644
--- a/Smarty.addons.php
+++ b/Smarty.addons.php
@@ -8,6 +8,26 @@
*
*/
+/*============================================*\
+ Modifiers
+\*============================================*/
+
+function _smarty_mod_handler()
+{
+ $args = func_get_args();
+ $func_name = array_shift($args);
+ $var = $args[0];
+
+ if (is_array($var)) {
+ foreach ($var as $key => $val) {
+ $args[0] = $val;
+ $var[$key] = call_user_func_array($func_name, $args);
+ }
+ return $var;
+ } else
+ return call_user_func_array($func_name, $args);
+}
+
/*======================================================================*\
Function: smarty_mod_escape
@@ -55,17 +75,31 @@ function smarty_mod_spacify($string, $spacify_char = ' ')
}
+function smarty_mod_date_format($string, $format)
+{
+ return strftime($format, $string);
+}
+
+
+function smarty_mod_replace($string, $search, $replace)
+{
+ return str_replace($search, $replace, $string);
+}
+
+
/*============================================*\
Custom tag functions
\*============================================*/
/*======================================================================*\
Function: smarty_func_html_options
- Purpose: Returns the list of \n";
}
+ if ($print_result)
+ print $html_result;
+ else
+ return $html_result;
+}
+
+
+/*======================================================================*\
+ Function: smarty_func_html_select_date
+ Purpose: Prints the dropdowns for date selection.
+\*======================================================================*/
+function smarty_func_html_select_date()
+{
+ /* Default values. */
+ $prefix = "Date_";
+ $time = time();
+ $start_year = strftime("%Y");
+ $end_year = $start_year;
+ $display_days = true;
+ $display_months = true;
+ $display_years = true;
+ $month_format = "%B";
+ $day_format = "%02d";
+ $year_as_text = false;
+
+ extract(func_get_arg(0));
+
+ $html_result = "";
+
+ if ($display_months) {
+ $month_names = array();
+
+ for ($i = 1; $i <= 12; $i++)
+ $month_names[] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
+
+ $html_result .= '\n";
+ }
+
+ if ($display_days) {
+ $days = range(1, 31);
+ array_walk($days, create_function('&$x', '$x = sprintf("'.$day_format.'", $x);'));
+
+ $html_result .= '\n";
+ }
+
+ if ($display_years) {
+ if ($year_as_text) {
+ $html_result .= '';
+ } else {
+ $years = range($start_year, $end_year);
+
+ $html_result .= '\n";
+ }
+ }
+
print $html_result;
}
diff --git a/Smarty.class.php b/Smarty.class.php
index a4540d71..ff74d081 100644
--- a/Smarty.class.php
+++ b/Smarty.class.php
@@ -41,7 +41,8 @@ class Smarty
var $config_dir = "./configs"; // directory where config files are located
- var $custom_tags = array( 'html_options' => 'smarty_func_html_options'
+ var $custom_tags = array( 'html_options' => 'smarty_func_html_options',
+ 'html_select_date' => 'smarty_func_html_select_date'
);
var $modifiers = array( 'lower' => 'strtolower',
@@ -49,7 +50,9 @@ class Smarty
'capitalize' => 'ucwords',
'escape' => 'smarty_mod_escape',
'truncate' => 'smarty_mod_truncate',
- 'spacify' => 'smarty_mod_spacify'
+ 'spacify' => 'smarty_mod_spacify',
+ 'date_format' => 'smarty_mod_date_format',
+ 'replace' => 'smarty_mod_replace'
);
var $global_assign = array( 'SCRIPT_NAME'
);
@@ -362,7 +365,8 @@ class Smarty
/* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
if (preg_match_all("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", $compiled_contents, $match)) {
$strip_tags = $match[0];
- $strip_tags_modified = preg_replace("!$ldq/?strip$rdq|[\t ]+$|^[\t ]+|/[\r\n]+!m", '', $strip_tags);
+ $strip_tags_modified = preg_replace("!$ldq/?strip$rdq|[\t ]+$|^[\t ]+!m", '', $strip_tags);
+ $strip_tags_modified = preg_replace('![\r\n]+!m', ' ', $strip_tags_modified);
for ($i = 0; $i < count($strip_tags); $i++)
$compiled_contents = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
$strip_tags_modified[$i], $compiled_contents, 1);
@@ -403,6 +407,9 @@ class Smarty
case 'else':
return '';
+ case 'elseif':
+ return $this->_compile_if_tag($tag_args, true);
+
case '/if':
return '';
@@ -451,10 +458,13 @@ class Smarty
{
$attrs = $this->_parse_attrs($tag_args);
$function = $this->custom_tags[$tag_command];
- foreach ($attrs as $arg_name => $arg_value)
+ foreach ($attrs as $arg_name => $arg_value) {
+ if (is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
+ }
- return "";
+ return "";
}
@@ -493,9 +503,9 @@ class Smarty
return 'template_dir.$this->compile_dir_ext.'/'.$attrs['file'].'"; ?>';
}
- function _compile_section_start($tokens)
+ function _compile_section_start($tag_args)
{
- $attrs = $this->_parse_attrs($tokens);
+ $attrs = $this->_parse_attrs($tag_args);
$output = " $attr_value) {
switch ($attr_name) {
case 'loop':
- $output .= "
- if (is_array($attr_value))
- {$section_props}['loop'] = count($attr_value);
- else
- {$section_props}['loop'] = $attr_value;\n";
+ $output .= "{$section_props}['loop'] = count($attr_value);\n";
break;
default:
@@ -544,7 +550,7 @@ class Smarty
return $output;
}
- function _compile_if_tag($tag_args)
+ function _compile_if_tag($tag_args, $elseif = false)
{
/* Tokenize args for 'if' tag. */
preg_match_all('/(?:
@@ -638,7 +644,10 @@ class Smarty
}
}
- return '';
+ if ($elseif)
+ return '';
+ else
+ return '';
}
function _parse_is_expr($is_arg, $tokens)
@@ -694,15 +703,13 @@ class Smarty
function _parse_attrs($tag_args)
{
/* Tokenize tag attributes. */
- preg_match_all('/(?:
- "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | # match all double quoted strings allowed escaped double quotes
- \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | # match all single quoted strings allowed escaped single quotes
- [=] | # match equal sign
- [^"\'\s=]+ # match any other token that is not any of the above
- )/x', $tag_args, $match);
+ preg_match_all('/(?:"[^"\\\\]*(?:\\\\.[^"\\\\]*)*" |
+ \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | (?>[^"\'= ]+)
+ )+ |
+ [=]
+ /x', $tag_args, $match);
$tokens = $match[0];
- $this->_parse_vars_props($tokens);
$attrs = array();
/* Parse state:
0 - expecting attr name
@@ -729,27 +736,30 @@ class Smarty
current token and don't switch state.
If the token is '=', then we go to state 2. */
- if (preg_match('!\w+!', $token)) {
- $attrs[$attr_name] = "";
- $attr_name = $token;
- } else if ($token == '=') {
+ if ($token == '=') {
$state = 2;
} else
- /* TODO syntax error: expecting attr name or '=' */;
+ /* TODO syntax error: expecting '=' */;
break;
case 2:
/* If token is not '=', we set the attribute value and go to
state 0. */
if ($token != '=') {
- /* If the token is not variable (doesn't start with '$')
- and not enclosed in single or double quotes
- we single-quote it. */
- if ($token{0} != '$' &&
- !(($token{0} == '"' || $token[0] == "'") &&
- $token{strlen($token)-1} == $token{0})) {
+ /* We booleanize the token if it's a non-quoted possible
+ boolean value. */
+ if (preg_match('!^(on|yes|true)$!', $token))
+ $token = true;
+ else if (preg_match('!^(off|no|false)$!', $token))
+ $token = false;
+ /* If the token is not variable (doesn't start with
+ '$', '#', or '%') and not enclosed in single or
+ double quotes we single-quote it. */
+ else if (!in_array($token{0}, array('$', '#', '%')) &&
+ !(($token{0} == '"' || $token[0] == "'") &&
+ $token{strlen($token)-1} == $token{0}))
$token = "'".$token."'";
- }
+
$attrs[$attr_name] = $token;
$state = 0;
} else
@@ -758,6 +768,8 @@ class Smarty
}
}
+ $this->_parse_vars_props($attrs);
+
return $attrs;
}
@@ -859,7 +871,7 @@ class Smarty
else
$modifier_args = '';
- $output = "$mod_func_name($output$modifier_args)";
+ $output = "_smarty_mod_handler('$mod_func_name', $output$modifier_args)";
}
}
diff --git a/demo/templates/index.tpl b/demo/templates/index.tpl
index 7d1db15d..762f54d9 100644
--- a/demo/templates/index.tpl
+++ b/demo/templates/index.tpl
@@ -1,11 +1,11 @@
-{config_load file=test.conf section=my foo}
+{config_load file=test.conf section="my foo"}
Title: {#title#|capitalize}
{$SCRIPT_NAME}
{* A simple variable test *}
-hello, my name is {$Name}
+hello, my name is {$Name|upper}
My interests are:
{section name=outer loop=$FirstName}
@@ -18,4 +18,4 @@ My interests are:
none
{/section}
-{html_options output=$FirstName values=$LastName selected="Case"}
+{html_options values=$LastName output=$FirstName|replace:"a":"@"}
diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php
index a4540d71..ff74d081 100644
--- a/libs/Smarty.class.php
+++ b/libs/Smarty.class.php
@@ -41,7 +41,8 @@ class Smarty
var $config_dir = "./configs"; // directory where config files are located
- var $custom_tags = array( 'html_options' => 'smarty_func_html_options'
+ var $custom_tags = array( 'html_options' => 'smarty_func_html_options',
+ 'html_select_date' => 'smarty_func_html_select_date'
);
var $modifiers = array( 'lower' => 'strtolower',
@@ -49,7 +50,9 @@ class Smarty
'capitalize' => 'ucwords',
'escape' => 'smarty_mod_escape',
'truncate' => 'smarty_mod_truncate',
- 'spacify' => 'smarty_mod_spacify'
+ 'spacify' => 'smarty_mod_spacify',
+ 'date_format' => 'smarty_mod_date_format',
+ 'replace' => 'smarty_mod_replace'
);
var $global_assign = array( 'SCRIPT_NAME'
);
@@ -362,7 +365,8 @@ class Smarty
/* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
if (preg_match_all("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", $compiled_contents, $match)) {
$strip_tags = $match[0];
- $strip_tags_modified = preg_replace("!$ldq/?strip$rdq|[\t ]+$|^[\t ]+|/[\r\n]+!m", '', $strip_tags);
+ $strip_tags_modified = preg_replace("!$ldq/?strip$rdq|[\t ]+$|^[\t ]+!m", '', $strip_tags);
+ $strip_tags_modified = preg_replace('![\r\n]+!m', ' ', $strip_tags_modified);
for ($i = 0; $i < count($strip_tags); $i++)
$compiled_contents = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
$strip_tags_modified[$i], $compiled_contents, 1);
@@ -403,6 +407,9 @@ class Smarty
case 'else':
return '';
+ case 'elseif':
+ return $this->_compile_if_tag($tag_args, true);
+
case '/if':
return '';
@@ -451,10 +458,13 @@ class Smarty
{
$attrs = $this->_parse_attrs($tag_args);
$function = $this->custom_tags[$tag_command];
- foreach ($attrs as $arg_name => $arg_value)
+ foreach ($attrs as $arg_name => $arg_value) {
+ if (is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
+ }
- return "";
+ return "";
}
@@ -493,9 +503,9 @@ class Smarty
return 'template_dir.$this->compile_dir_ext.'/'.$attrs['file'].'"; ?>';
}
- function _compile_section_start($tokens)
+ function _compile_section_start($tag_args)
{
- $attrs = $this->_parse_attrs($tokens);
+ $attrs = $this->_parse_attrs($tag_args);
$output = " $attr_value) {
switch ($attr_name) {
case 'loop':
- $output .= "
- if (is_array($attr_value))
- {$section_props}['loop'] = count($attr_value);
- else
- {$section_props}['loop'] = $attr_value;\n";
+ $output .= "{$section_props}['loop'] = count($attr_value);\n";
break;
default:
@@ -544,7 +550,7 @@ class Smarty
return $output;
}
- function _compile_if_tag($tag_args)
+ function _compile_if_tag($tag_args, $elseif = false)
{
/* Tokenize args for 'if' tag. */
preg_match_all('/(?:
@@ -638,7 +644,10 @@ class Smarty
}
}
- return '';
+ if ($elseif)
+ return '';
+ else
+ return '';
}
function _parse_is_expr($is_arg, $tokens)
@@ -694,15 +703,13 @@ class Smarty
function _parse_attrs($tag_args)
{
/* Tokenize tag attributes. */
- preg_match_all('/(?:
- "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | # match all double quoted strings allowed escaped double quotes
- \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | # match all single quoted strings allowed escaped single quotes
- [=] | # match equal sign
- [^"\'\s=]+ # match any other token that is not any of the above
- )/x', $tag_args, $match);
+ preg_match_all('/(?:"[^"\\\\]*(?:\\\\.[^"\\\\]*)*" |
+ \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | (?>[^"\'= ]+)
+ )+ |
+ [=]
+ /x', $tag_args, $match);
$tokens = $match[0];
- $this->_parse_vars_props($tokens);
$attrs = array();
/* Parse state:
0 - expecting attr name
@@ -729,27 +736,30 @@ class Smarty
current token and don't switch state.
If the token is '=', then we go to state 2. */
- if (preg_match('!\w+!', $token)) {
- $attrs[$attr_name] = "";
- $attr_name = $token;
- } else if ($token == '=') {
+ if ($token == '=') {
$state = 2;
} else
- /* TODO syntax error: expecting attr name or '=' */;
+ /* TODO syntax error: expecting '=' */;
break;
case 2:
/* If token is not '=', we set the attribute value and go to
state 0. */
if ($token != '=') {
- /* If the token is not variable (doesn't start with '$')
- and not enclosed in single or double quotes
- we single-quote it. */
- if ($token{0} != '$' &&
- !(($token{0} == '"' || $token[0] == "'") &&
- $token{strlen($token)-1} == $token{0})) {
+ /* We booleanize the token if it's a non-quoted possible
+ boolean value. */
+ if (preg_match('!^(on|yes|true)$!', $token))
+ $token = true;
+ else if (preg_match('!^(off|no|false)$!', $token))
+ $token = false;
+ /* If the token is not variable (doesn't start with
+ '$', '#', or '%') and not enclosed in single or
+ double quotes we single-quote it. */
+ else if (!in_array($token{0}, array('$', '#', '%')) &&
+ !(($token{0} == '"' || $token[0] == "'") &&
+ $token{strlen($token)-1} == $token{0}))
$token = "'".$token."'";
- }
+
$attrs[$attr_name] = $token;
$state = 0;
} else
@@ -758,6 +768,8 @@ class Smarty
}
}
+ $this->_parse_vars_props($attrs);
+
return $attrs;
}
@@ -859,7 +871,7 @@ class Smarty
else
$modifier_args = '';
- $output = "$mod_func_name($output$modifier_args)";
+ $output = "_smarty_mod_handler('$mod_func_name', $output$modifier_args)";
}
}
diff --git a/templates/index.tpl b/templates/index.tpl
index 7d1db15d..762f54d9 100644
--- a/templates/index.tpl
+++ b/templates/index.tpl
@@ -1,11 +1,11 @@
-{config_load file=test.conf section=my foo}
+{config_load file=test.conf section="my foo"}
Title: {#title#|capitalize}
{$SCRIPT_NAME}
{* A simple variable test *}
-hello, my name is {$Name}
+hello, my name is {$Name|upper}
My interests are:
{section name=outer loop=$FirstName}
@@ -18,4 +18,4 @@ My interests are:
none
{/section}
-{html_options output=$FirstName values=$LastName selected="Case"}
+{html_options values=$LastName output=$FirstName|replace:"a":"@"}