Skip to content

Commit c10047f

Browse files
committed
smarty/4-PHP8-compatible-code-fixes
1 parent a8d77c8 commit c10047f

File tree

6 files changed

+107
-6
lines changed

6 files changed

+107
-6
lines changed

libs/functions.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,100 @@ function smarty_strtolower_ascii($string): string {
4848
*/
4949
function smarty_strtoupper_ascii($string): string {
5050
return strtr($string, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
51+
}
52+
53+
/**
54+
* Polyfill for deprecated strftime() function (removed in PHP 8.1+).
55+
*
56+
* PHP 8.1+: strftime() was deprecated and removed. This function provides
57+
* a compatibility layer by converting strftime format codes to date() format.
58+
* For full locale support, use IntlDateFormatter directly in your application.
59+
*
60+
* @param string $format strftime format string
61+
* @param int|null $timestamp Unix timestamp (defaults to current time)
62+
*
63+
* @return string|false Formatted date string or false on failure
64+
*/
65+
function smarty_strftime($format, $timestamp = null) {
66+
// Use current time if no timestamp provided
67+
if ($timestamp === null) {
68+
$timestamp = time();
69+
}
70+
71+
// If the native strftime function still exists (PHP < 8.1), use it
72+
if (function_exists('strftime')) {
73+
return @strftime($format, $timestamp);
74+
}
75+
76+
// PHP 8.1+: Convert strftime format to date() format
77+
// This is a basic conversion that handles most common format codes
78+
$strftimeToDate = [
79+
// Day
80+
'%d' => 'd', // Day of month, 2 digits with leading zeros
81+
'%e' => 'j', // Day of month, with leading space if single digit
82+
'%j' => 'z', // Day of year, 3 digits with leading zeros
83+
'%u' => 'N', // ISO-8601 numeric representation of day of week
84+
'%w' => 'w', // Numeric representation of day of week
85+
86+
// Week
87+
'%U' => '', // Week number (Sunday as first day) - no direct equivalent
88+
'%V' => 'W', // ISO-8601 week number
89+
'%W' => '', // Week number (Monday as first day) - no direct equivalent
90+
91+
// Month
92+
'%b' => 'M', // Abbreviated month name
93+
'%B' => 'F', // Full month name
94+
'%h' => 'M', // Abbreviated month name (same as %b)
95+
'%m' => 'm', // Month, 2 digits with leading zeros
96+
97+
// Year
98+
'%C' => '', // Century - no direct equivalent
99+
'%g' => 'o', // ISO-8601 year (2 digits)
100+
'%G' => 'o', // ISO-8601 year (4 digits)
101+
'%y' => 'y', // Year, 2 digits
102+
'%Y' => 'Y', // Year, 4 digits
103+
104+
// Time
105+
'%H' => 'H', // Hour, 24-hour format, 2 digits
106+
'%I' => 'h', // Hour, 12-hour format, 2 digits
107+
'%l' => 'g', // Hour, 12-hour format, no leading zero
108+
'%M' => 'i', // Minutes, 2 digits
109+
'%p' => 'A', // AM or PM
110+
'%P' => 'a', // am or pm
111+
'%r' => 'h:i:s A', // Time in 12-hour format with AM/PM
112+
'%R' => 'H:i', // Time in 24-hour format HH:MM
113+
'%S' => 's', // Seconds, 2 digits
114+
'%T' => 'H:i:s', // Time in 24-hour format HH:MM:SS
115+
'%X' => 'H:i:s', // Preferred time representation (no locale support)
116+
'%z' => 'O', // Timezone offset
117+
'%Z' => 'T', // Timezone abbreviation
118+
119+
// Time and Date
120+
'%c' => 'D M d H:i:s Y', // Preferred date and time (no locale support)
121+
'%D' => 'm/d/y', // Date in US format (same as %m/%d/%y)
122+
'%F' => 'Y-m-d', // Date in ISO 8601 format
123+
'%s' => 'U', // Unix timestamp
124+
'%x' => 'm/d/y', // Preferred date representation (no locale support)
125+
126+
// Day names
127+
'%a' => 'D', // Abbreviated weekday name
128+
'%A' => 'l', // Full weekday name
129+
130+
// Misc
131+
'%n' => "\n", // Newline
132+
'%t' => "\t", // Tab
133+
'%%' => '%', // Literal %
134+
];
135+
136+
// Replace strftime format codes with date() format codes
137+
$dateFormat = str_replace(array_keys($strftimeToDate), array_values($strftimeToDate), $format);
138+
139+
// Handle %e (day with leading space) specially since date() doesn't have exact equivalent
140+
if (strpos($format, '%e') !== false) {
141+
$day = date('j', $timestamp);
142+
$dateFormat = str_replace('%e', sprintf('%2d', $day), $format);
143+
$dateFormat = str_replace(array_keys($strftimeToDate), array_values($strftimeToDate), $dateFormat);
144+
}
145+
146+
return date($dateFormat, $timestamp);
51147
}

libs/plugins/function.html_select_date.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem
316316
for ($i = 1; $i <= 12; $i++) {
317317
$_val = sprintf('%02d', $i);
318318
$_text = isset($month_names) ? smarty_function_escape_special_chars($month_names[ $i ]) :
319-
($month_format === '%m' ? $_val : @strftime($month_format, $_month_timestamps[ $i ]));
320-
$_value = $month_value_format === '%m' ? $_val : @strftime($month_value_format, $_month_timestamps[ $i ]);
319+
($month_format === '%m' ? $_val : smarty_strftime($month_format, $_month_timestamps[ $i ]));
320+
// PHP 8.1+: Use smarty_strftime() polyfill instead of deprecated strftime()
321+
$_value = $month_value_format === '%m' ? $_val : smarty_strftime($month_value_format, $_month_timestamps[ $i ]);
321322
$_html_months .= '<option value="' . $_value . '"' . ($_val == $_month ? ' selected="selected"' : '') .
322323
'>' . $_text . '</option>' . $option_separator;
323324
}

libs/plugins/modifier.date_format.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ function smarty_modifier_date_format($string, $format = null, $default_date = ''
7878
}
7979
$format = str_replace($_win_from, $_win_to, $format);
8080
}
81-
// @ to suppress deprecation errors when running in PHP8.1 or higher.
82-
return @strftime($format, $timestamp);
81+
// PHP 8.1+: Use smarty_strftime() polyfill instead of deprecated strftime()
82+
return smarty_strftime($format, $timestamp);
8383
} else {
8484
return date($format, $timestamp);
8585
}

libs/sysplugins/smarty_internal_compile_block.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
129129
$output .= "class {$_className} extends Smarty_Internal_Block\n";
130130
$output .= "{\n";
131131
foreach ($_block as $property => $value) {
132-
$output .= "public \${$property} = " . var_export($value, true) . ";\n";
132+
// PHP 8.2+: Replaced deprecated ${} interpolation with concatenation for clarity
133+
$output .= 'public $' . $property . ' = ' . var_export($value, true) . ";\n";
133134
}
134135
$output .= "public function callBlock(Smarty_Internal_Template \$_smarty_tpl) {\n";
135136
$output .= $compiler->compileRequiredPlugins();

libs/sysplugins/smarty_internal_data.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
* @method Smarty_Internal_Data clearConfig(string $varName = null)
3030
* @method Smarty_Internal_Data configLoad(string $config_file, mixed $sections = null, string $scope = 'local')
3131
*/
32+
// PHP 8.2+: Allow dynamic properties for extension handler and backward compatibility
33+
#[\AllowDynamicProperties]
3234
abstract class Smarty_Internal_Data
3335
{
3436
/**

libs/sysplugins/smarty_internal_runtime_make_nocache.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public function save(Smarty_Internal_Template $tpl, $var)
2424
$export =
2525
preg_replace('/^\\\\?Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true));
2626
if (preg_match('/(\w+)::__set_state/', $export, $match)) {
27-
throw new SmartyException("{make_nocache \${$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'");
27+
// PHP 8.2+: Replaced deprecated ${} interpolation with {} syntax
28+
throw new SmartyException("{make_nocache {\$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'");
2829
}
2930
echo "/*%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/<?php " .
3031
addcslashes("\$_smarty_tpl->smarty->ext->_make_nocache->store(\$_smarty_tpl, '{$var}', ", '\\') .

0 commit comments

Comments
 (0)