DefaultExtension::smarty_modifier_date_format()   C
last analyzed

Complexity

Conditions 12
Paths 26

Size

Total Lines 47
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 36
nc 26
nop 4
dl 0
loc 47
rs 6.9666
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Smarty\Extension;
4
5
use Smarty\Exception;
6
7
class DefaultExtension extends Base {
8
9
	private $modifiers = [];
10
11
	private $functionHandlers = [];
12
13
	private $blockHandlers = [];
14
15
	public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
16
17
		if (isset($this->modifiers[$modifier])) {
18
			return $this->modifiers[$modifier];
19
		}
20
21
		switch ($modifier) {
22
			case 'cat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CatModifierCompiler(); break;
23
			case 'count_characters': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountCharactersModifierCompiler(); break;
24
			case 'count_paragraphs': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountParagraphsModifierCompiler(); break;
25
			case 'count_sentences': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountSentencesModifierCompiler(); break;
26
			case 'count_words': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountWordsModifierCompiler(); break;
27
			case 'default': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\DefaultModifierCompiler(); break;
28
			case 'empty': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EmptyModifierCompiler(); break;
29
			case 'escape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EscapeModifierCompiler(); break;
30
			case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
31
			case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); break;
32
			case 'is_array': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IsArrayModifierCompiler(); break;
33
			case 'isset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IssetModifierCompiler(); break;
34
			case 'json_encode': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\JsonEncodeModifierCompiler(); break;
35
			case 'lower': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\LowerModifierCompiler(); break;
36
			case 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); break;
37
			case 'noprint': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\NoPrintModifierCompiler(); break;
38
			case 'raw': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RawModifierCompiler(); break;
39
			case 'round': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RoundModifierCompiler(); break;
40
			case 'str_repeat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrRepeatModifierCompiler(); break;
41
			case 'string_format': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StringFormatModifierCompiler(); break;
42
			case 'strip': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripModifierCompiler(); break;
43
			case 'strip_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); break;
44
			case 'strlen': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrlenModifierCompiler(); break;
45
			case 'substr': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\SubstrModifierCompiler(); break;
46
			case 'to_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\ToCharsetModifierCompiler(); break;
47
			case 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); break;
48
			case 'upper': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UpperModifierCompiler(); break;
49
			case 'wordwrap': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\WordWrapModifierCompiler(); break;
50
		}
51
52
		return $this->modifiers[$modifier] ?? null;
53
	}
54
55
	public function getModifierCallback(string $modifierName) {
56
		switch ($modifierName) {
57
			case 'capitalize': return [$this, 'smarty_modifier_capitalize'];
58
			case 'count': return [$this, 'smarty_modifier_count'];
59
			case 'date_format': return [$this, 'smarty_modifier_date_format'];
60
			case 'debug_print_var': return [$this, 'smarty_modifier_debug_print_var'];
61
			case 'escape': return [$this, 'smarty_modifier_escape'];
62
			case 'explode': return [$this, 'smarty_modifier_explode'];
63
			case 'implode': return [$this, 'smarty_modifier_implode'];
64
			case 'in_array': return [$this, 'smarty_modifier_in_array'];
65
			case 'join': return [$this, 'smarty_modifier_join'];
66
			case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
67
			case 'number_format': return [$this, 'smarty_modifier_number_format'];
68
			case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
69
			case 'replace': return [$this, 'smarty_modifier_replace'];
70
			case 'spacify': return [$this, 'smarty_modifier_spacify'];
71
			case 'split': return [$this, 'smarty_modifier_split'];
72
			case 'truncate': return [$this, 'smarty_modifier_truncate'];
73
		}
74
		return null;
75
	}
76
77
	public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
78
79
		if (isset($this->functionHandlers[$functionName])) {
80
			return $this->functionHandlers[$functionName];
81
		}
82
83
		switch ($functionName) {
84
			case 'count': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Count(); break;
85
			case 'counter': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Counter(); break;
86
			case 'cycle': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Cycle(); break;
87
			case 'fetch': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Fetch(); break;
88
			case 'html_checkboxes': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlCheckboxes(); break;
89
			case 'html_image': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlImage(); break;
90
			case 'html_options': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlOptions(); break;
91
			case 'html_radios': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlRadios(); break;
92
			case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
93
			case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
94
			case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
95
			case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
96
			case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
97
		}
98
99
		return $this->functionHandlers[$functionName] ?? null;
100
	}
101
102
	public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
103
104
		switch ($blockTagName) {
105
			case 'textformat': $this->blockHandlers[$blockTagName] = new \Smarty\BlockHandler\TextFormat(); break;
106
		}
107
108
		return $this->blockHandlers[$blockTagName] ?? null;
109
	}
110
111
	/**
112
	 * Smarty spacify modifier plugin
113
	 * Type:     modifier
114
	 * Name:     spacify
115
	 * Purpose:  add spaces between characters in a string
116
	 *
117
	 * @author Monte Ohrt <monte at ohrt dot com>
118
	 *
119
	 * @param string $string       input string
120
	 * @param string $spacify_char string to insert between characters.
121
	 *
122
	 * @return string
123
	 */
124
	public function smarty_modifier_spacify($string, $spacify_char = ' ')
125
	{
126
		// well… what about charsets besides latin and UTF-8?
127
		return implode($spacify_char, preg_split('//' . \Smarty\Smarty::$_UTF8_MODIFIER, $string, -1, PREG_SPLIT_NO_EMPTY));
128
	}
129
130
	/**
131
	 * Smarty capitalize modifier plugin
132
	 * Type:     modifier
133
	 * Name:     capitalize
134
	 * Purpose:  capitalize words in the string
135
	 * {@internal {$string|capitalize:true:true} is the fastest option for MBString enabled systems }}
136
	 *
137
	 * @param string  $string    string to capitalize
138
	 * @param boolean $uc_digits also capitalize "x123" to "X123"
139
	 * @param boolean $lc_rest   capitalize first letters, lowercase all following letters "aAa" to "Aaa"
140
	 *
141
	 * @return string capitalized string
142
	 * @author Monte Ohrt <monte at ohrt dot com>
143
	 * @author Rodney Rehm
144
	 */
145
	public function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
146
	{
147
		$string = (string) $string;
148
149
		if ($lc_rest) {
150
			// uppercase (including hyphenated words)
151
			$upper_string = mb_convert_case($string, MB_CASE_TITLE, \Smarty\Smarty::$_CHARSET);
152
		} else {
153
			// uppercase word breaks
154
			$upper_string = preg_replace_callback(
155
				"!(^|[^\p{L}'])([\p{Ll}])!S" . \Smarty\Smarty::$_UTF8_MODIFIER,
156
				function ($matches)	{
157
					return stripslashes($matches[1]) .
158
						mb_convert_case(stripslashes($matches[2]), MB_CASE_UPPER, \Smarty\Smarty::$_CHARSET);
159
				},
160
				$string
161
			);
162
		}
163
		// check uc_digits case
164
		if (!$uc_digits) {
165
			if (preg_match_all(
166
				"!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . \Smarty\Smarty::$_UTF8_MODIFIER,
167
				$string,
168
				$matches,
169
				PREG_OFFSET_CAPTURE
170
			)
171
			) {
172
				foreach ($matches[ 1 ] as $match) {
173
					$upper_string =
174
						substr_replace(
175
							$upper_string,
176
							mb_strtolower($match[ 0 ], \Smarty\Smarty::$_CHARSET),
177
							$match[ 1 ],
178
							strlen($match[ 0 ])
179
						);
180
				}
181
			}
182
		}
183
		$upper_string =
184
			preg_replace_callback(
185
				"!((^|\s)['\"])(\w)!" . \Smarty\Smarty::$_UTF8_MODIFIER,
186
				function ($matches) {
187
					return stripslashes(
188
						$matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 3 ]),
189
						MB_CASE_UPPER,
190
						\Smarty\Smarty::$_CHARSET
191
					);
192
				},
193
				$upper_string
194
			);
195
		return $upper_string;
196
	}
197
198
	/**
199
	 * Smarty count modifier plugin
200
	 * Type:     modifier
201
	 * Name:     count
202
	 * Purpose:  counts all elements in an array or in a Countable object
203
	 * Input:
204
	 *          - Countable|array: array or object to count
205
	 *          - mode: int defaults to 0 for normal count mode, if set to 1 counts recursive
206
	 *
207
	 * @param mixed $arrayOrObject  input array/object
208
	 * @param int $mode       count mode
209
	 *
210
	 * @return int
211
	 */
212
	public function smarty_modifier_count($arrayOrObject, $mode = 0) {
213
		/*
214
		 * @see https://www.php.net/count
215
		 * > Prior to PHP 8.0.0, if the parameter was neither an array nor an object that implements the Countable interface,
216
		 * > 1 would be returned, unless value was null, in which case 0 would be returned.
217
		 */
218
219
		if ($arrayOrObject instanceof \Countable || is_array($arrayOrObject)) {
220
			return count($arrayOrObject, (int) $mode);
221
		} elseif ($arrayOrObject === null) {
222
			return 0;
223
		}
224
		return 1;
225
	}
226
227
	/**
228
	 * Smarty date_format modifier plugin
229
	 * Type:     modifier
230
	 * Name:     date_format
231
	 * Purpose:  format datestamps via strftime
232
	 * Input:
233
	 *          - string: input date string
234
	 *          - format: strftime format for output
235
	 *          - default_date: default date if $string is empty
236
	 *
237
	 * @author Monte Ohrt <monte at ohrt dot com>
238
	 *
239
	 * @param string $string       input date string
240
	 * @param string $format       strftime format for output
241
	 * @param string $default_date default date if $string is empty
242
	 * @param string $formatter    either 'strftime' or 'auto'
243
	 *
244
	 * @return string |void
245
	 * @uses   smarty_make_timestamp()
246
	 */
247
	public function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto')
248
	{
249
		if ($format === null) {
250
			$format = \Smarty\Smarty::$_DATE_FORMAT;
251
		}
252
253
		if (!empty($string) && $string !== '0000-00-00' && $string !== '0000-00-00 00:00:00') {
254
			$timestamp = smarty_make_timestamp($string);
255
		} elseif (!empty($default_date)) {
256
			$timestamp = smarty_make_timestamp($default_date);
257
		} else {
258
			return;
259
		}
260
		if ($formatter === 'strftime' || ($formatter === 'auto' && strpos($format, '%') !== false)) {
261
			if (\Smarty\Smarty::$_IS_WINDOWS) {
262
				$_win_from = array(
263
					'%D',
264
					'%h',
265
					'%n',
266
					'%r',
267
					'%R',
268
					'%t',
269
					'%T'
270
				);
271
				$_win_to = array(
272
					'%m/%d/%y',
273
					'%b',
274
					"\n",
275
					'%I:%M:%S %p',
276
					'%H:%M',
277
					"\t",
278
					'%H:%M:%S'
279
				);
280
				if (strpos($format, '%e') !== false) {
281
					$_win_from[] = '%e';
282
					$_win_to[] = sprintf('%\' 2d', date('j', $timestamp));
283
				}
284
				if (strpos($format, '%l') !== false) {
285
					$_win_from[] = '%l';
286
					$_win_to[] = sprintf('%\' 2d', date('h', $timestamp));
287
				}
288
				$format = str_replace($_win_from, $_win_to, $format);
289
			}
290
			// @ to suppress deprecation errors when running in PHP8.1 or higher.
291
			return @strftime($format, $timestamp);
0 ignored issues
show
Bug Best Practice introduced by
The expression return @strftime($format, $timestamp) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
292
		} else {
293
			return date($format, $timestamp);
294
		}
295
	}
296
297
	/**
298
	 * Smarty debug_print_var modifier plugin
299
	 * Type:     modifier
300
	 * Name:     debug_print_var
301
	 * Purpose:  formats variable contents for display in the console
302
	 *
303
	 * @author Monte Ohrt <monte at ohrt dot com>
304
	 *
305
	 * @param array|object $var     variable to be formatted
306
	 * @param int          $max     maximum recursion depth if $var is an array or object
307
	 * @param int          $length  maximum string length if $var is a string
308
	 * @param int          $depth   actual recursion depth
309
	 * @param array        $objects processed objects in actual depth to prevent recursive object processing
310
	 *
311
	 * @return string
312
	 */
313
	public function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
314
	{
315
		$_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t');
316
		switch (gettype($var)) {
317
			case 'array':
318
				$results = '<b>Array (' . count($var) . ')</b>';
319
				if ($depth === $max) {
320
					break;
321
				}
322
				foreach ($var as $curr_key => $curr_val) {
323
					$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b>' . strtr($curr_key, $_replace) .
324
						'</b> =&gt; ' .
325
						$this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
326
					$depth--;
327
				}
328
				break;
329
			case 'object':
330
				$object_vars = get_object_vars($var);
331
				$results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
332
				if (in_array($var, $objects)) {
333
					$results .= ' called recursive';
334
					break;
335
				}
336
				if ($depth === $max) {
337
					break;
338
				}
339
				$objects[] = $var;
340
				foreach ($object_vars as $curr_key => $curr_val) {
341
					$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b> -&gt;' . strtr($curr_key, $_replace) .
342
						'</b> = ' . $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
343
					$depth--;
344
				}
345
				break;
346
			case 'boolean':
347
			case 'NULL':
348
			case 'resource':
349
				if (true === $var) {
350
					$results = 'true';
351
				} elseif (false === $var) {
352
					$results = 'false';
353
				} elseif (null === $var) {
354
					$results = 'null';
355
				} else {
356
					$results = htmlspecialchars((string)$var);
357
				}
358
				$results = '<i>' . $results . '</i>';
359
				break;
360
			case 'integer':
361
			case 'float':
362
				$results = htmlspecialchars((string)$var);
363
				break;
364
			case 'string':
365
				$results = strtr($var, $_replace);
366
				if (mb_strlen($var, \Smarty\Smarty::$_CHARSET) > $length) {
367
					$results = mb_substr($var, 0, $length - 3, \Smarty\Smarty::$_CHARSET) . '...';
368
				}
369
				$results = htmlspecialchars('"' . $results . '"', ENT_QUOTES, \Smarty\Smarty::$_CHARSET);
370
				break;
371
			case 'unknown type':
372
			default:
373
				$results = strtr((string)$var, $_replace);
374
				if (mb_strlen($results, \Smarty\Smarty::$_CHARSET) > $length) {
375
					$results = mb_substr($results, 0, $length - 3, \Smarty\Smarty::$_CHARSET) . '...';
376
				}
377
				$results = htmlspecialchars($results, ENT_QUOTES, \Smarty\Smarty::$_CHARSET);
378
		}
379
		return $results;
380
	}
381
382
	/**
383
	 * Smarty escape modifier plugin
384
	 * Type:     modifier
385
	 * Name:     escape
386
	 * Purpose:  escape string for output
387
	 *
388
	 * @author Monte Ohrt <monte at ohrt dot com>
389
	 *
390
	 * @param string  $string        input string
391
	 * @param string  $esc_type      escape type
392
	 * @param string  $char_set      character set, used for htmlspecialchars() or htmlentities()
393
	 * @param boolean $double_encode encode already encoded entitites again, used for htmlspecialchars() or htmlentities()
394
	 *
395
	 * @return string escaped input string
396
	 */
397
	public function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true)
398
	{
399
		if (!$char_set) {
400
			$char_set = \Smarty\Smarty::$_CHARSET;
401
		}
402
403
		$string = (string)$string;
404
405
		switch ($esc_type) {
406
			case 'html':
407
				return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
408
			// no break
409
			case 'htmlall':
410
				$string = mb_convert_encoding($string, 'UTF-8', $char_set);
411
				return htmlentities($string, ENT_QUOTES, 'UTF-8', $double_encode);
0 ignored issues
show
Bug introduced by
It seems like $string can also be of type array; however, parameter $string of htmlentities() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

411
				return htmlentities(/** @scrutinizer ignore-type */ $string, ENT_QUOTES, 'UTF-8', $double_encode);
Loading history...
412
			// no break
413
			case 'url':
414
				return rawurlencode($string);
415
			case 'urlpathinfo':
416
				return str_replace('%2F', '/', rawurlencode($string));
417
			case 'quotes':
418
				// escape unescaped single quotes
419
				return preg_replace("%(?<!\\\\)'%", "\\'", $string);
420
			case 'hex':
421
				// escape every byte into hex
422
				// Note that the UTF-8 encoded character ä will be represented as %c3%a4
423
				$return = '';
424
				$_length = strlen($string);
425
				for ($x = 0; $x < $_length; $x++) {
426
					$return .= '%' . bin2hex($string[ $x ]);
427
				}
428
				return $return;
429
			case 'hexentity':
430
				$return = '';
431
				foreach ($this->mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
432
					$return .= '&#x' . strtoupper(dechex($unicode)) . ';';
433
				}
434
				return $return;
435
			case 'decentity':
436
				$return = '';
437
				foreach ($this->mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
438
					$return .= '&#' . $unicode . ';';
439
				}
440
				return $return;
441
			case 'javascript':
442
				// escape quotes and backslashes, newlines, etc.
443
				return strtr(
444
					$string,
445
					array(
446
						'\\' => '\\\\',
447
						"'"  => "\\'",
448
						'"'  => '\\"',
449
						"\r" => '\\r',
450
						"\n" => '\\n',
451
						'</' => '<\/',
452
						// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
453
						'<!--' => '<\!--',
454
						'<s'   => '<\s',
455
						'<S'   => '<\S',
456
						"`" => "\\\\`",
457
						"\${" => "\\\\\\$\\{"
458
					)
459
				);
460
			case 'mail':
461
				return smarty_mb_str_replace(
462
					array(
463
						'@',
464
						'.'
465
					),
466
					array(
467
						' [AT] ',
468
						' [DOT] '
469
					),
470
					$string
471
				);
472
			case 'nonstd':
473
				// escape non-standard chars, such as ms document quotes
474
				$return = '';
475
				foreach ($this->mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
476
					if ($unicode >= 126) {
477
						$return .= '&#' . $unicode . ';';
478
					} else {
479
						$return .= chr($unicode);
480
					}
481
				}
482
				return $return;
483
			default:
484
				trigger_error("escape: unsupported type: $esc_type - returning unmodified string", E_USER_NOTICE);
485
				return $string;
486
		}
487
	}
488
489
490
	/**
491
	 * convert characters to their decimal unicode equivalents
492
	 *
493
	 * @link   http://www.ibm.com/developerworks/library/os-php-unicode/index.html#listing3 for inspiration
494
	 *
495
	 * @param string $string   characters to calculate unicode of
496
	 * @param string $encoding encoding of $string
497
	 *
498
	 * @return array sequence of unicodes
499
	 * @author Rodney Rehm
500
	 */
501
	private function mb_to_unicode($string, $encoding = null) {
502
		if ($encoding) {
503
			$expanded = mb_convert_encoding($string, 'UTF-32BE', $encoding);
504
		} else {
505
			$expanded = mb_convert_encoding($string, 'UTF-32BE');
506
		}
507
		return unpack('N*', $expanded);
0 ignored issues
show
Bug introduced by
It seems like $expanded can also be of type array; however, parameter $string of unpack() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

507
		return unpack('N*', /** @scrutinizer ignore-type */ $expanded);
Loading history...
508
	}
509
510
	/**
511
	 * Smarty explode modifier plugin
512
	 * Type:     modifier
513
	 * Name:     explode
514
	 * Purpose:  split a string by a string
515
	 *
516
	 * @param string   $separator
517
	 * @param string   $string
518
	 * @param int|null $limit
519
	 *
520
	 * @return array
521
	 */
522
	public function smarty_modifier_explode($separator, $string, ?int $limit = null)
523
	{
524
		trigger_error("Using explode is deprecated. " .
525
			"Use split, using the array first, separator second.", E_USER_DEPRECATED);
526
		// provide $string default to prevent deprecation errors in PHP >=8.1
527
		return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
528
	}
529
530
	/**
531
	 * Smarty split modifier plugin
532
	 * Type:     modifier
533
	 * Name:     split
534
	 * Purpose:  split a string by a string
535
	 *
536
	 * @param string $string
537
	 * @param string   $separator
538
	 * @param int|null $limit
539
	 *
540
	 * @return array
541
	 */
542
	public function smarty_modifier_split($string, $separator, ?int $limit = null)
543
	{
544
		// provide $string default to prevent deprecation errors in PHP >=8.1
545
		return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
546
	}
547
548
	/**
549
	 * Smarty implode modifier plugin
550
	 * Type:     modifier
551
	 * Name:     implode
552
	 * Purpose:  join an array of values into a single string
553
	 *
554
	 * @param array   $values
555
	 * @param string   $separator
556
	 *
557
	 * @return string
558
	 */
559
	public function smarty_modifier_implode($values, $separator = '')
560
	{
561
562
		trigger_error("Using implode is deprecated. " .
563
			"Use join using the array first, separator second.", E_USER_DEPRECATED);
564
565
		if (is_array($separator)) {
0 ignored issues
show
introduced by
The condition is_array($separator) is always false.
Loading history...
566
			return implode((string) ($values ?? ''), (array) $separator);
567
		}
568
		return implode((string) ($separator ?? ''), (array) $values);
569
	}
570
571
	/**
572
	 * Smarty in_array modifier plugin
573
	 * Type:     modifier
574
	 * Name:     in_array
575
	 * Purpose:  test if value is contained in an array
576
	 *
577
	 * @param mixed   $needle
578
	 * @param array   $array
579
	 * @param bool   $strict
580
	 *
581
	 * @return bool
582
	 */
583
	public function smarty_modifier_in_array($needle, $array, $strict = false)
584
	{
585
		return in_array($needle, (array) $array, (bool) $strict);
586
	}
587
588
	/**
589
	 * Smarty join modifier plugin
590
	 * Type:     modifier
591
	 * Name:     join
592
	 * Purpose:  join an array of values into a single string
593
	 *
594
	 * @param array   $values
595
	 * @param string   $separator
596
	 *
597
	 * @return string
598
	 */
599
	public function smarty_modifier_join($values, $separator = '')
600
	{
601
		if (is_array($separator)) {
0 ignored issues
show
introduced by
The condition is_array($separator) is always false.
Loading history...
602
			trigger_error("Using join with the separator first is deprecated. " .
603
				"Call join using the array first, separator second.", E_USER_DEPRECATED);
604
			return implode((string) ($values ?? ''), (array) $separator);
605
		}
606
		return implode((string) ($separator ?? ''), (array) $values);
607
	}
608
609
	/**
610
	 * Smarty wordwrap modifier plugin
611
	 * Type:     modifier
612
	 * Name:     mb_wordwrap
613
	 * Purpose:  Wrap a string to a given number of characters
614
	 *
615
	 * @link   https://php.net/manual/en/function.wordwrap.php for similarity
616
	 *
617
	 * @param string  $str   the string to wrap
618
	 * @param int     $width the width of the output
619
	 * @param string  $break the character used to break the line
620
	 * @param boolean $cut   ignored parameter, just for the sake of
621
	 *
622
	 * @return string  wrapped string
623
	 * @author Rodney Rehm
624
	 */
625
	public function smarty_modifier_mb_wordwrap($str, $width = 75, $break = "\n", $cut = false)
626
	{
627
		return smarty_mb_wordwrap($str, $width, $break, $cut);
628
	}
629
630
	/**
631
	 * Smarty number_format modifier plugin
632
	 * Type:     modifier
633
	 * Name:     number_format
634
	 * Purpose:  Format a number with grouped thousands
635
	 *
636
	 * @param float|null  $num
637
	 * @param int         $decimals
638
	 * @param string|null $decimal_separator
639
	 * @param string|null $thousands_separator
640
	 *
641
	 * @return string
642
	 */
643
	public function smarty_modifier_number_format(?float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = ",")
644
	{
645
		// provide $num default to prevent deprecation errors in PHP >=8.1
646
		return number_format($num ?? 0.0, $decimals, $decimal_separator, $thousands_separator);
647
	}
648
649
	/**
650
	 * Smarty regex_replace modifier plugin
651
	 * Type:     modifier
652
	 * Name:     regex_replace
653
	 * Purpose:  regular expression search/replace
654
	 *
655
	 * @author Monte Ohrt <monte at ohrt dot com>
656
	 *
657
	 * @param string       $string  input string
658
	 * @param string|array $search  regular expression(s) to search for
659
	 * @param string|array $replace string(s) that should be replaced
660
	 * @param int          $limit   the maximum number of replacements
661
	 *
662
	 * @return string
663
	 */
664
	public function smarty_modifier_regex_replace($string, $search, $replace, $limit = -1)
665
	{
666
		if (is_array($search)) {
667
			foreach ($search as $idx => $s) {
668
				$search[ $idx ] = $this->regex_replace_check($s);
669
			}
670
		} else {
671
			$search = $this->regex_replace_check($search);
672
		}
673
		return preg_replace($search, $replace, $string, $limit);
674
	}
675
676
	/**
677
	 * @param  string $search string(s) that should be replaced
678
	 *
679
	 * @return string
680
	 * @ignore
681
	 */
682
	private function regex_replace_check($search)
683
	{
684
		// null-byte injection detection
685
		// anything behind the first null-byte is ignored
686
		if (($pos = strpos($search, "\0")) !== false) {
687
			$search = substr($search, 0, $pos);
688
		}
689
		// remove eval-modifier from $search
690
		if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[ 1 ], 'e') !== false)) {
691
			$search = substr($search, 0, -strlen($match[ 1 ])) . preg_replace('![e\s]+!', '', $match[ 1 ]);
692
		}
693
		return $search;
694
	}
695
696
	/**
697
	 * Smarty replace modifier plugin
698
	 * Type:     modifier
699
	 * Name:     replace
700
	 * Purpose:  simple search/replace
701
	 *
702
	 * @author Monte Ohrt <monte at ohrt dot com>
703
	 * @author Uwe Tews
704
	 *
705
	 * @param string $string  input string
706
	 * @param string $search  text to search for
707
	 * @param string $replace replacement text
708
	 *
709
	 * @return string
710
	 */
711
	public function smarty_modifier_replace($string, $search, $replace)
712
	{
713
		return smarty_mb_str_replace($search, $replace, $string);
714
	}
715
716
	/**
717
	 * Smarty truncate modifier plugin
718
	 * Type:     modifier
719
	 * Name:     truncate
720
	 * Purpose:  Truncate a string to a certain length if necessary,
721
	 *               optionally splitting in the middle of a word, and
722
	 *               appending the $etc string or inserting $etc into the middle.
723
	 *
724
	 * @author Monte Ohrt <monte at ohrt dot com>
725
	 *
726
	 * @param string  $string      input string
727
	 * @param integer $length      length of truncated text
728
	 * @param string  $etc         end string
729
	 * @param boolean $break_words truncate at word boundary
730
	 * @param boolean $middle      truncate in the middle of text
731
	 *
732
	 * @return string truncated string
733
	 */
734
	public function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false)
735
	{
736
		if ($length === 0 || $string === null) {
737
			return '';
738
		}
739
		if (mb_strlen($string, \Smarty\Smarty::$_CHARSET) > $length) {
740
			$length -= min($length, mb_strlen($etc, \Smarty\Smarty::$_CHARSET));
741
			if (!$break_words && !$middle) {
742
				$string = preg_replace(
743
					'/\s+?(\S+)?$/' . \Smarty\Smarty::$_UTF8_MODIFIER,
744
					'',
745
					mb_substr($string, 0, $length + 1, \Smarty\Smarty::$_CHARSET)
746
				);
747
			}
748
			if (!$middle) {
749
				return mb_substr($string, 0, $length, \Smarty\Smarty::$_CHARSET) . $etc;
750
			}
751
			return mb_substr($string, 0, intval($length / 2), \Smarty\Smarty::$_CHARSET) . $etc .
752
				mb_substr($string, -intval($length / 2), $length, \Smarty\Smarty::$_CHARSET);
753
		}
754
		return $string;
755
	}
756
757
}
758