Smarty   F
last analyzed

Complexity

Total Complexity 116

Size/Duplication

Total Lines 1298
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 324
dl 0
loc 1298
rs 2
c 0
b 0
f 0
wmc 116

48 Methods

Rating   Name   Duplication   Size   Complexity  
A setCompileLocking() 0 3 1
A addConfigDir() 0 3 1
A setUseSubDirs() 0 3 1
A testInstall() 0 3 1
A setErrorReporting() 0 3 1
A _getSmartyObj() 0 3 1
A getCacheDir() 0 7 2
A loadPlugin() 0 3 1
A __get() 0 13 4
A setMergeCompiledIncludes() 0 3 1
B _normalizeTemplateConfig() 0 21 7
A setPluginsDir() 0 5 1
A setTemplateDir() 0 11 2
A setCacheDir() 0 5 1
A setLeftDelimiter() 0 3 1
A setConfigBooleanize() 0 3 1
A _clearTemplateCache() 0 4 1
A getRightDelimiter() 0 3 1
F createTemplate() 0 50 21
A addPluginsDir() 0 8 2
A templateExists() 0 5 1
B addTemplateDir() 0 33 6
A getTemplateDir() 0 14 6
A __construct() 0 16 4
A _normalizeDir() 0 3 1
A getPluginsDir() 0 17 5
A setCompileDir() 0 5 1
A setConfigDir() 0 3 1
A setConfigReadHidden() 0 3 1
A disableSecurity() 0 4 1
A setAutoLiteral() 0 3 1
A setRightDelimiter() 0 3 1
A setDebugging() 0 3 1
A setCachingType() 0 3 1
B _realpath() 0 29 6
A setDefaultResourceType() 0 3 1
A setForceCompile() 0 3 1
A muteUndefinedOrNullWarnings() 0 2 1
A setEscapeHtml() 0 3 1
A setConfigOverwrite() 0 3 1
A getConfigDir() 0 3 1
A isMutingUndefinedOrNullWarnings() 0 2 1
A getAutoLiteral() 0 3 1
A __set() 0 11 5
B _getTemplateId() 0 23 10
A getCompileDir() 0 7 2
A enableSecurity() 0 4 1
A getLeftDelimiter() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Smarty often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Smarty, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Project:     Smarty: the PHP compiling template engine
4
 * File:        Smarty.class.php
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 3.0 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 * For questions, help, comments, discussion, etc., please join the
20
 * Smarty mailing list. Send a blank e-mail to
21
 * [email protected]
22
 *
23
 * @link      https://www.smarty.net/
24
 * @copyright 2018 New Digital Group, Inc.
25
 * @copyright 2018 Uwe Tews
26
 * @author    Monte Ohrt <monte at ohrt dot com>
27
 * @author    Uwe Tews   <uwe dot tews at gmail dot com>
28
 * @author    Rodney Rehm
29
 * @package   Smarty
30
 */
31
/**
32
 * set SMARTY_DIR to absolute path to Smarty library files.
33
 * Sets SMARTY_DIR only if user application has not already defined it.
34
 */
35
if (!defined('SMARTY_DIR')) {
36
    /**
37
     *
38
     */
39
    define('SMARTY_DIR', __DIR__ . DIRECTORY_SEPARATOR);
40
}
41
/**
42
 * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
43
 * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
44
 */
45
if (!defined('SMARTY_SYSPLUGINS_DIR')) {
46
    /**
47
     *
48
     */
49
    define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR);
50
}
51
if (!defined('SMARTY_PLUGINS_DIR')) {
52
    /**
53
     *
54
     */
55
    define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DIRECTORY_SEPARATOR);
56
}
57
if (!defined('SMARTY_MBSTRING')) {
58
    /**
59
     *
60
     */
61
    define('SMARTY_MBSTRING', function_exists('mb_get_info'));
62
}
63
64
/**
65
 * Load helper functions
66
 */
67
if (!defined('SMARTY_HELPER_FUNCTIONS_LOADED')) {
68
    include __DIR__ . '/functions.php';
69
}
70
71
/**
72
 * Load Smarty_Autoloader
73
 */
74
if (!class_exists('Smarty_Autoloader')) {
75
    include __DIR__ . '/bootstrap.php';
76
}
77
78
/**
79
 * Load always needed external class files
80
 */
81
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
82
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
83
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
84
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
85
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
86
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
87
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
88
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
89
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
90
91
/**
92
 * This is the main Smarty class
93
 *
94
 * @package Smarty
95
 *
96
 * The following methods will be dynamically loaded by the extension handler when they are called.
97
 * They are located in a corresponding Smarty_Internal_Method_xxxx class
98
 *
99
 * @method int clearAllCache(int $exp_time = null, string $type = null)
100
 * @method int clearCache(string $template_name, string $cache_id = null, string $compile_id = null, int $exp_time = null, string $type = null)
101
 * @method int compileAllTemplates(string $extension = '.tpl', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
102
 * @method int compileAllConfig(string $extension = '.conf', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
103
 * @method int clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
104
 */
105
class Smarty extends Smarty_Internal_TemplateBase
106
{
107
    /**
108
     * smarty version
109
     */
110
    const SMARTY_VERSION = '4.5.5';
111
    /**
112
     * define variable scopes
113
     */
114
    const SCOPE_LOCAL    = 1;
115
    const SCOPE_PARENT   = 2;
116
    const SCOPE_TPL_ROOT = 4;
117
    const SCOPE_ROOT     = 8;
118
    const SCOPE_SMARTY   = 16;
119
    const SCOPE_GLOBAL   = 32;
120
    /**
121
     * define caching modes
122
     */
123
    const CACHING_OFF              = 0;
124
    const CACHING_LIFETIME_CURRENT = 1;
125
    const CACHING_LIFETIME_SAVED   = 2;
126
    /**
127
     * define constant for clearing cache files be saved expiration dates
128
     */
129
    const CLEAR_EXPIRED = -1;
130
    /**
131
     * define compile check modes
132
     */
133
    const COMPILECHECK_OFF       = 0;
134
    const COMPILECHECK_ON        = 1;
135
    const COMPILECHECK_CACHEMISS = 2;
136
    /**
137
     * define debug modes
138
     */
139
    const DEBUG_OFF        = 0;
140
    const DEBUG_ON         = 1;
141
    const DEBUG_INDIVIDUAL = 2;
142
143
    /**
144
     * filter types
145
     */
146
    const FILTER_POST     = 'post';
147
    const FILTER_PRE      = 'pre';
148
    const FILTER_OUTPUT   = 'output';
149
    const FILTER_VARIABLE = 'variable';
150
    /**
151
     * plugin types
152
     */
153
    const PLUGIN_FUNCTION         = 'function';
154
    const PLUGIN_BLOCK            = 'block';
155
    const PLUGIN_COMPILER         = 'compiler';
156
    const PLUGIN_MODIFIER         = 'modifier';
157
    const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
158
159
    /**
160
     * assigned global tpl vars
161
     */
162
    public static $global_tpl_vars = array();
163
164
    /**
165
     * Flag denoting if Multibyte String functions are available
166
     */
167
    public static $_MBSTRING = SMARTY_MBSTRING;
168
169
    /**
170
     * The character set to adhere to (e.g. "UTF-8")
171
     */
172
    public static $_CHARSET = SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1';
173
174
    /**
175
     * The date format to be used internally
176
     * (accepts date() and strftime())
177
     */
178
    public static $_DATE_FORMAT = '%b %e, %Y';
179
180
    /**
181
     * Flag denoting if PCRE should run in UTF-8 mode
182
     */
183
    public static $_UTF8_MODIFIER = 'u';
184
185
    /**
186
     * Flag denoting if operating system is windows
187
     */
188
    public static $_IS_WINDOWS = false;
189
190
    /**
191
     * auto literal on delimiters with whitespace
192
     *
193
     * @var boolean
194
     */
195
    public $auto_literal = true;
196
197
    /**
198
     * display error on not assigned variables
199
     *
200
     * @var boolean
201
     */
202
    public $error_unassigned = false;
203
204
    /**
205
     * look up relative file path in include_path
206
     *
207
     * @var boolean
208
     */
209
    public $use_include_path = false;
210
211
    /**
212
     * flag if template_dir is normalized
213
     *
214
     * @var bool
215
     */
216
    public $_templateDirNormalized = false;
217
218
    /**
219
     * joined template directory string used in cache keys
220
     *
221
     * @var string
222
     */
223
    public $_joined_template_dir = null;
224
225
    /**
226
     * flag if config_dir is normalized
227
     *
228
     * @var bool
229
     */
230
    public $_configDirNormalized = false;
231
232
    /**
233
     * joined config directory string used in cache keys
234
     *
235
     * @var string
236
     */
237
    public $_joined_config_dir = null;
238
239
    /**
240
     * default template handler
241
     *
242
     * @var callable
243
     */
244
    public $default_template_handler_func = null;
245
246
    /**
247
     * default config handler
248
     *
249
     * @var callable
250
     */
251
    public $default_config_handler_func = null;
252
253
    /**
254
     * default plugin handler
255
     *
256
     * @var callable
257
     */
258
    public $default_plugin_handler_func = null;
259
260
    /**
261
     * flag if template_dir is normalized
262
     *
263
     * @var bool
264
     */
265
    public $_compileDirNormalized = false;
266
267
    /**
268
     * flag if plugins_dir is normalized
269
     *
270
     * @var bool
271
     */
272
    public $_pluginsDirNormalized = false;
273
274
    /**
275
     * flag if template_dir is normalized
276
     *
277
     * @var bool
278
     */
279
    public $_cacheDirNormalized = false;
280
281
    /**
282
     * force template compiling?
283
     *
284
     * @var boolean
285
     */
286
    public $force_compile = false;
287
288
    /**
289
     * use sub dirs for compiled/cached files?
290
     *
291
     * @var boolean
292
     */
293
    public $use_sub_dirs = false;
294
295
    /**
296
     * allow ambiguous resources (that are made unique by the resource handler)
297
     *
298
     * @var boolean
299
     */
300
    public $allow_ambiguous_resources = false;
301
302
    /**
303
     * merge compiled includes
304
     *
305
     * @var boolean
306
     */
307
    public $merge_compiled_includes = false;
308
309
    /*
310
    * flag for behaviour when extends: resource  and {extends} tag are used simultaneous
311
    *   if false disable execution of {extends} in templates called by extends resource.
312
    *   (behaviour as versions < 3.1.28)
313
    *
314
    * @var boolean
315
    */
316
    public $extends_recursion = true;
317
318
    /**
319
     * force cache file creation
320
     *
321
     * @var boolean
322
     */
323
    public $force_cache = false;
324
325
    /**
326
     * template left-delimiter
327
     *
328
     * @var string
329
     */
330
    public $left_delimiter = "{";
331
332
    /**
333
     * template right-delimiter
334
     *
335
     * @var string
336
     */
337
    public $right_delimiter = "}";
338
339
    /**
340
     * array of strings which shall be treated as literal by compiler
341
     *
342
     * @var array string
343
     */
344
    public $literals = array();
345
346
    /**
347
     * class name
348
     * This should be instance of Smarty_Security.
349
     *
350
     * @var string
351
     * @see Smarty_Security
352
     */
353
    public $security_class = 'Smarty_Security';
354
355
    /**
356
     * implementation of security class
357
     *
358
     * @var Smarty_Security
359
     */
360
    public $security_policy = null;
361
362
    /**
363
     * controls if the php template file resource is allowed
364
     *
365
     * @var bool
366
     */
367
    public $allow_php_templates = false;
368
369
    /**
370
     * debug mode
371
     * Setting this to true enables the debug-console.
372
     *
373
     * @var boolean
374
     */
375
    public $debugging = false;
376
377
    /**
378
     * This determines if debugging is enable-able from the browser.
379
     * <ul>
380
     *  <li>NONE => no debugging control allowed</li>
381
     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
382
     * </ul>
383
     *
384
     * @var string
385
     */
386
    public $debugging_ctrl = 'NONE';
387
388
    /**
389
     * Name of debugging URL-param.
390
     * Only used when $debugging_ctrl is set to 'URL'.
391
     * The name of the URL-parameter that activates debugging.
392
     *
393
     * @var string
394
     */
395
    public $smarty_debug_id = 'SMARTY_DEBUG';
396
397
    /**
398
     * Path of debug template.
399
     *
400
     * @var string
401
     */
402
    public $debug_tpl = null;
403
404
    /**
405
     * When set, smarty uses this value as error_reporting-level.
406
     *
407
     * @var int
408
     */
409
    public $error_reporting = null;
410
411
    /**
412
     * Controls whether variables with the same name overwrite each other.
413
     *
414
     * @var boolean
415
     */
416
    public $config_overwrite = true;
417
418
    /**
419
     * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
420
     *
421
     * @var boolean
422
     */
423
    public $config_booleanize = true;
424
425
    /**
426
     * Controls whether hidden config sections/vars are read from the file.
427
     *
428
     * @var boolean
429
     */
430
    public $config_read_hidden = false;
431
432
    /**
433
     * locking concurrent compiles
434
     *
435
     * @var boolean
436
     */
437
    public $compile_locking = true;
438
439
    /**
440
     * Controls whether cache resources should use locking mechanism
441
     *
442
     * @var boolean
443
     */
444
    public $cache_locking = false;
445
446
    /**
447
     * seconds to wait for acquiring a lock before ignoring the write lock
448
     *
449
     * @var float
450
     */
451
    public $locking_timeout = 10;
452
453
    /**
454
     * resource type used if none given
455
     * Must be an valid key of $registered_resources.
456
     *
457
     * @var string
458
     */
459
    public $default_resource_type = 'file';
460
461
    /**
462
     * caching type
463
     * Must be an element of $cache_resource_types.
464
     *
465
     * @var string
466
     */
467
    public $caching_type = 'file';
468
469
    /**
470
     * config type
471
     *
472
     * @var string
473
     */
474
    public $default_config_type = 'file';
475
476
    /**
477
     * check If-Modified-Since headers
478
     *
479
     * @var boolean
480
     */
481
    public $cache_modified_check = false;
482
483
    /**
484
     * registered plugins
485
     *
486
     * @var array
487
     */
488
    public $registered_plugins = array();
489
490
    /**
491
     * registered objects
492
     *
493
     * @var array
494
     */
495
    public $registered_objects = array();
496
497
    /**
498
     * registered classes
499
     *
500
     * @var array
501
     */
502
    public $registered_classes = array();
503
504
    /**
505
     * registered filters
506
     *
507
     * @var array
508
     */
509
    public $registered_filters = array();
510
511
    /**
512
     * registered resources
513
     *
514
     * @var array
515
     */
516
    public $registered_resources = array();
517
518
    /**
519
     * registered cache resources
520
     *
521
     * @var array
522
     */
523
    public $registered_cache_resources = array();
524
525
    /**
526
     * autoload filter
527
     *
528
     * @var array
529
     */
530
    public $autoload_filters = array();
531
532
    /**
533
     * default modifier
534
     *
535
     * @var array
536
     */
537
    public $default_modifiers = array();
538
539
    /**
540
     * autoescape variable output
541
     *
542
     * @var boolean
543
     */
544
    public $escape_html = false;
545
546
    /**
547
     * start time for execution time calculation
548
     *
549
     * @var int
550
     */
551
    public $start_time = 0;
552
553
    /**
554
     * required by the compiler for BC
555
     *
556
     * @var string
557
     */
558
    public $_current_file = null;
559
560
    /**
561
     * internal flag to enable parser debugging
562
     *
563
     * @var bool
564
     */
565
    public $_parserdebug = false;
566
567
    /**
568
     * This object type (Smarty = 1, template = 2, data = 4)
569
     *
570
     * @var int
571
     */
572
    public $_objType = 1;
573
574
    /**
575
     * Debug object
576
     *
577
     * @var Smarty_Internal_Debug
578
     */
579
    public $_debug = null;
580
581
    /**
582
     * template directory
583
     *
584
     * @var array
585
     */
586
    protected $template_dir = array('./templates/');
587
588
    /**
589
     * flags for normalized template directory entries
590
     *
591
     * @var array
592
     */
593
    protected $_processedTemplateDir = array();
594
595
    /**
596
     * config directory
597
     *
598
     * @var array
599
     */
600
    protected $config_dir = array('./configs/');
601
602
    /**
603
     * flags for normalized template directory entries
604
     *
605
     * @var array
606
     */
607
    protected $_processedConfigDir = array();
608
609
    /**
610
     * compile directory
611
     *
612
     * @var string
613
     */
614
    protected $compile_dir = './templates_c/';
615
616
    /**
617
     * plugins directory
618
     *
619
     * @var array
620
     */
621
    protected $plugins_dir = array();
622
623
    /**
624
     * cache directory
625
     *
626
     * @var string
627
     */
628
    protected $cache_dir = './cache/';
629
630
    /**
631
     * removed properties
632
     *
633
     * @var string[]
634
     */
635
    protected $obsoleteProperties = array(
636
        'resource_caching', 'template_resource_caching', 'direct_access_security',
637
        '_dir_perms', '_file_perms', 'plugin_search_order',
638
        'inheritance_merge_compiled_includes', 'resource_cache_mode',
639
    );
640
641
    /**
642
     * List of private properties which will call getter/setter on a direct access
643
     *
644
     * @var string[]
645
     */
646
    protected $accessMap = array(
647
        'template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir',
648
        'plugins_dir'  => 'PluginsDir', 'compile_dir' => 'CompileDir',
649
        'cache_dir'    => 'CacheDir',
650
    );
651
652
    /**
653
     * PHP7 Compatibility mode
654
     * @var bool
655
     */
656
    private $isMutingUndefinedOrNullWarnings = false;
657
658
    /**
659
     * Initialize new Smarty object
660
     */
661
    public function __construct()
662
    {
663
        $this->_clearTemplateCache();
664
        parent::__construct();
665
        if (is_callable('mb_internal_encoding')) {
666
            mb_internal_encoding(Smarty::$_CHARSET);
667
        }
668
        $this->start_time = microtime(true);
0 ignored issues
show
Documentation Bug introduced by
It seems like microtime(true) can also be of type string. However, the property $start_time is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
669
        if (isset($_SERVER[ 'SCRIPT_NAME' ])) {
670
            Smarty::$global_tpl_vars[ 'SCRIPT_NAME' ] = new Smarty_Variable($_SERVER[ 'SCRIPT_NAME' ]);
671
        }
672
        // Check if we're running on windows
673
        Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
674
        // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
675
        if (Smarty::$_CHARSET !== 'UTF-8') {
676
            Smarty::$_UTF8_MODIFIER = '';
677
        }
678
    }
679
680
    /**
681
     * Check if a template resource exists
682
     *
683
     * @param string $resource_name template name
684
     *
685
     * @return bool status
686
     * @throws \SmartyException
687
     */
688
    public function templateExists($resource_name)
689
    {
690
        // create source object
691
        $source = Smarty_Template_Source::load(null, $this, $resource_name);
692
        return $source->exists;
693
    }
694
695
    /**
696
     * Loads security class and enables security
697
     *
698
     * @param string|Smarty_Security $security_class if a string is used, it must be class-name
699
     *
700
     * @return Smarty                 current Smarty instance for chaining
701
     * @throws \SmartyException
702
     */
703
    public function enableSecurity($security_class = null)
704
    {
705
        Smarty_Security::enableSecurity($this, $security_class);
706
        return $this;
707
    }
708
709
    /**
710
     * Disable security
711
     *
712
     * @return Smarty current Smarty instance for chaining
713
     */
714
    public function disableSecurity()
715
    {
716
        $this->security_policy = null;
717
        return $this;
718
    }
719
720
    /**
721
     * Add template directory(s)
722
     *
723
     * @param string|array $template_dir directory(s) of template sources
724
     * @param string       $key          of the array element to assign the template dir to
725
     * @param bool         $isConfig     true for config_dir
726
     *
727
     * @return Smarty          current Smarty instance for chaining
728
     */
729
    public function addTemplateDir($template_dir, $key = null, $isConfig = false)
730
    {
731
        if ($isConfig) {
732
            $processed = &$this->_processedConfigDir;
733
            $dir = &$this->config_dir;
734
            $this->_configDirNormalized = false;
735
        } else {
736
            $processed = &$this->_processedTemplateDir;
737
            $dir = &$this->template_dir;
738
            $this->_templateDirNormalized = false;
739
        }
740
        if (is_array($template_dir)) {
741
            foreach ($template_dir as $k => $v) {
742
                if (is_int($k)) {
743
                    // indexes are not merged but appended
744
                    $dir[] = $v;
745
                } else {
746
                    // string indexes are overridden
747
                    $dir[ $k ] = $v;
748
                    unset($processed[ $key ]);
749
                }
750
            }
751
        } else {
752
            if ($key !== null) {
753
                // override directory at specified index
754
                $dir[ $key ] = $template_dir;
755
                unset($processed[ $key ]);
756
            } else {
757
                // append new directory
758
                $dir[] = $template_dir;
759
            }
760
        }
761
        return $this;
762
    }
763
764
    /**
765
     * Get template directories
766
     *
767
     * @param mixed $index    index of directory to get, null to get all
768
     * @param bool  $isConfig true for config_dir
769
     *
770
     * @return array|string list of template directories, or directory of $index
771
     */
772
    public function getTemplateDir($index = null, $isConfig = false)
773
    {
774
        if ($isConfig) {
775
            $dir = &$this->config_dir;
776
        } else {
777
            $dir = &$this->template_dir;
778
        }
779
        if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) {
780
            $this->_normalizeTemplateConfig($isConfig);
781
        }
782
        if ($index !== null) {
783
            return isset($dir[ $index ]) ? $dir[ $index ] : null;
784
        }
785
        return $dir;
786
    }
787
788
    /**
789
     * Set template directory
790
     *
791
     * @param string|array $template_dir directory(s) of template sources
792
     * @param bool         $isConfig     true for config_dir
793
     *
794
     * @return \Smarty current Smarty instance for chaining
795
     */
796
    public function setTemplateDir($template_dir, $isConfig = false)
797
    {
798
        if ($isConfig) {
799
            $this->config_dir = array();
800
            $this->_processedConfigDir = array();
801
        } else {
802
            $this->template_dir = array();
803
            $this->_processedTemplateDir = array();
804
        }
805
        $this->addTemplateDir($template_dir, null, $isConfig);
806
        return $this;
807
    }
808
809
    /**
810
     * Add config directory(s)
811
     *
812
     * @param string|array $config_dir directory(s) of config sources
813
     * @param mixed        $key        key of the array element to assign the config dir to
814
     *
815
     * @return Smarty current Smarty instance for chaining
816
     */
817
    public function addConfigDir($config_dir, $key = null)
818
    {
819
        return $this->addTemplateDir($config_dir, $key, true);
820
    }
821
822
    /**
823
     * Get config directory
824
     *
825
     * @param mixed $index index of directory to get, null to get all
826
     *
827
     * @return array configuration directory
828
     */
829
    public function getConfigDir($index = null)
830
    {
831
        return $this->getTemplateDir($index, true);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getTemplateDir($index, true) also could return the type string which is incompatible with the documented return type array.
Loading history...
832
    }
833
834
    /**
835
     * Set config directory
836
     *
837
     * @param $config_dir
838
     *
839
     * @return Smarty       current Smarty instance for chaining
840
     */
841
    public function setConfigDir($config_dir)
842
    {
843
        return $this->setTemplateDir($config_dir, true);
844
    }
845
846
    /**
847
     * Adds directory of plugin files
848
     *
849
     * @param null|array|string $plugins_dir
850
     *
851
     * @return Smarty current Smarty instance for chaining
852
     */
853
    public function addPluginsDir($plugins_dir)
854
    {
855
        if (empty($this->plugins_dir)) {
856
            $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
857
        }
858
        $this->plugins_dir = array_merge($this->plugins_dir, (array)$plugins_dir);
859
        $this->_pluginsDirNormalized = false;
860
        return $this;
861
    }
862
863
    /**
864
     * Get plugin directories
865
     *
866
     * @return array list of plugin directories
867
     */
868
    public function getPluginsDir()
869
    {
870
        if (empty($this->plugins_dir)) {
871
            $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
872
            $this->_pluginsDirNormalized = false;
873
        }
874
        if (!$this->_pluginsDirNormalized) {
875
            if (!is_array($this->plugins_dir)) {
0 ignored issues
show
introduced by
The condition is_array($this->plugins_dir) is always true.
Loading history...
876
                $this->plugins_dir = (array)$this->plugins_dir;
877
            }
878
            foreach ($this->plugins_dir as $k => $v) {
879
                $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true);
880
            }
881
            $this->_cache[ 'plugin_files' ] = array();
882
            $this->_pluginsDirNormalized = true;
883
        }
884
        return $this->plugins_dir;
885
    }
886
887
    /**
888
     * Set plugins directory
889
     *
890
     * @param string|array $plugins_dir directory(s) of plugins
891
     *
892
     * @return Smarty       current Smarty instance for chaining
893
     */
894
    public function setPluginsDir($plugins_dir)
895
    {
896
        $this->plugins_dir = (array)$plugins_dir;
897
        $this->_pluginsDirNormalized = false;
898
        return $this;
899
    }
900
901
    /**
902
     * Get compiled directory
903
     *
904
     * @return string path to compiled templates
905
     */
906
    public function getCompileDir()
907
    {
908
        if (!$this->_compileDirNormalized) {
909
            $this->_normalizeDir('compile_dir', $this->compile_dir);
910
            $this->_compileDirNormalized = true;
911
        }
912
        return $this->compile_dir;
913
    }
914
915
    /**
916
     *
917
     * @param  string $compile_dir directory to store compiled templates in
918
     *
919
     * @return Smarty current Smarty instance for chaining
920
     */
921
    public function setCompileDir($compile_dir)
922
    {
923
        $this->_normalizeDir('compile_dir', $compile_dir);
924
        $this->_compileDirNormalized = true;
925
        return $this;
926
    }
927
928
    /**
929
     * Get cache directory
930
     *
931
     * @return string path of cache directory
932
     */
933
    public function getCacheDir()
934
    {
935
        if (!$this->_cacheDirNormalized) {
936
            $this->_normalizeDir('cache_dir', $this->cache_dir);
937
            $this->_cacheDirNormalized = true;
938
        }
939
        return $this->cache_dir;
940
    }
941
942
    /**
943
     * Set cache directory
944
     *
945
     * @param string $cache_dir directory to store cached templates in
946
     *
947
     * @return Smarty current Smarty instance for chaining
948
     */
949
    public function setCacheDir($cache_dir)
950
    {
951
        $this->_normalizeDir('cache_dir', $cache_dir);
952
        $this->_cacheDirNormalized = true;
953
        return $this;
954
    }
955
956
    /**
957
     * creates a template object
958
     *
959
     * @param string  $template   the resource handle of the template file
960
     * @param mixed   $cache_id   cache id to be used with this template
961
     * @param mixed   $compile_id compile id to be used with this template
962
     * @param object  $parent     next higher level of Smarty variables
963
     * @param boolean $do_clone   flag is Smarty object shall be cloned
964
     *
965
     * @return \Smarty_Internal_Template template object
966
     * @throws \SmartyException
967
     */
968
    public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
969
    {
970
        if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
971
            $parent = $cache_id;
972
            $cache_id = null;
973
        }
974
        if ($parent !== null && is_array($parent)) {
975
            $data = $parent;
976
            $parent = null;
977
        } else {
978
            $data = null;
979
        }
980
        if (!$this->_templateDirNormalized) {
981
            $this->_normalizeTemplateConfig(false);
982
        }
983
        $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id);
984
        $tpl = null;
985
        if ($this->caching && isset(Smarty_Internal_Template::$isCacheTplObj[ $_templateId ])) {
986
            $tpl = $do_clone ? clone Smarty_Internal_Template::$isCacheTplObj[ $_templateId ] :
987
                Smarty_Internal_Template::$isCacheTplObj[ $_templateId ];
988
            $tpl->inheritance = null;
989
            $tpl->tpl_vars = $tpl->config_vars = array();
990
        } elseif (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) {
991
            $tpl = clone Smarty_Internal_Template::$tplObjCache[ $_templateId ];
992
            $tpl->inheritance = null;
993
            $tpl->tpl_vars = $tpl->config_vars = array();
994
        } else {
995
            /* @var Smarty_Internal_Template $tpl */
996
            $tpl = new $this->template_class($template, $this, null, $cache_id, $compile_id, null, null);
997
            $tpl->templateId = $_templateId;
998
        }
999
        if ($do_clone) {
1000
            $tpl->smarty = clone $tpl->smarty;
1001
        }
1002
        $tpl->parent = $parent ? $parent : $this;
1003
        // fill data if present
1004
        if (!empty($data) && is_array($data)) {
1005
            // set up variable values
1006
            foreach ($data as $_key => $_val) {
1007
                $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val);
1008
            }
1009
        }
1010
        if ($this->debugging || $this->debugging_ctrl === 'URL') {
1011
            $tpl->smarty->_debug = new Smarty_Internal_Debug();
1012
            // check URL debugging control
1013
            if (!$this->debugging && $this->debugging_ctrl === 'URL') {
1014
                $tpl->smarty->_debug->debugUrl($tpl->smarty);
1015
            }
1016
        }
1017
        return $tpl;
1018
    }
1019
1020
    /**
1021
     * Takes unknown classes and loads plugin files for them
1022
     * class name format: Smarty_PluginType_PluginName
1023
     * plugin filename format: plugintype.pluginname.php
1024
     *
1025
     * @param string $plugin_name class plugin name to load
1026
     * @param bool   $check       check if already loaded
1027
     *
1028
     * @return string |boolean filepath of loaded file or false
1029
     * @throws \SmartyException
1030
     */
1031
    public function loadPlugin($plugin_name, $check = true)
1032
    {
1033
        return $this->ext->loadPlugin->loadPlugin($this, $plugin_name, $check);
1034
    }
1035
1036
    /**
1037
     * Get unique template id
1038
     *
1039
     * @param string                         $template_name
1040
     * @param null|mixed                     $cache_id
1041
     * @param null|mixed                     $compile_id
1042
     * @param null                           $caching
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $caching is correct as it would always require null to be passed?
Loading history...
1043
     * @param \Smarty_Internal_Template|null $template
1044
     *
1045
     * @return string
1046
     * @throws \SmartyException
1047
     */
1048
    public function _getTemplateId(
1049
        $template_name,
1050
        $cache_id = null,
1051
        $compile_id = null,
1052
        $caching = null,
1053
        ?Smarty_Internal_Template $template = null
1054
    ) {
1055
        $template_name = (strpos($template_name, ':') === false) ? "{$this->default_resource_type}:{$template_name}" :
1056
            $template_name;
1057
        $cache_id = $cache_id === null ? $this->cache_id : $cache_id;
1058
        $compile_id = $compile_id === null ? $this->compile_id : $compile_id;
1059
        $caching = (int)($caching === null ? $this->caching : $caching);
0 ignored issues
show
introduced by
The condition $caching === null is always true.
Loading history...
1060
        if ((isset($template) && strpos($template_name, ':.') !== false) || $this->allow_ambiguous_resources) {
1061
            $_templateId =
1062
                Smarty_Resource::getUniqueTemplateName((isset($template) ? $template : $this), $template_name) .
1063
                "#{$cache_id}#{$compile_id}#{$caching}";
1064
        } else {
1065
            $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}";
1066
        }
1067
        if (isset($_templateId[ 150 ])) {
1068
            $_templateId = sha1($_templateId);
1069
        }
1070
        return $_templateId;
1071
    }
1072
1073
    /**
1074
     * Normalize path
1075
     *  - remove /./ and /../
1076
     *  - make it absolute if required
1077
     *
1078
     * @param string $path     file path
1079
     * @param bool   $realpath if true - convert to absolute
1080
     *                         false - convert to relative
1081
     *                         null - keep as it is but
1082
     *                         remove /./ /../
1083
     *
1084
     * @return string
1085
     */
1086
    public function _realpath($path, $realpath = null)
1087
    {
1088
        $nds = array('/' => '\\', '\\' => '/');
1089
        preg_match(
1090
            '%^(?<root>(?:[[:alpha:]]:[\\\\/]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(.*))$%u',
1091
            $path,
1092
            $parts
1093
        );
1094
        $path = $parts[ 'path' ];
1095
        if ($parts[ 'root' ] === '\\') {
1096
            $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ];
1097
        } else {
1098
            if ($realpath !== null && !$parts[ 'root' ]) {
1099
                $path = getcwd() . DIRECTORY_SEPARATOR . $path;
1100
            }
1101
        }
1102
        // normalize DIRECTORY_SEPARATOR
1103
        $path = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $path);
1104
        $parts[ 'root' ] = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $parts[ 'root' ]);
1105
        do {
1106
            $path = preg_replace(
1107
                array('#[\\\\/]{2}#', '#[\\\\/][.][\\\\/]#', '#[\\\\/]([^\\\\/.]+)[\\\\/][.][.][\\\\/]#'),
1108
                DIRECTORY_SEPARATOR,
1109
                $path,
1110
                -1,
1111
                $count
1112
            );
1113
        } while ($count > 0);
1114
        return $realpath !== false ? $parts[ 'root' ] . $path : str_ireplace(getcwd(), '.', $parts[ 'root' ] . $path);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $realpath !== fal...$parts['root'] . $path) also could return the type array which is incompatible with the documented return type string.
Loading history...
1115
    }
1116
1117
    /**
1118
     * Empty template objects cache
1119
     */
1120
    public function _clearTemplateCache()
1121
    {
1122
        Smarty_Internal_Template::$isCacheTplObj = array();
1123
        Smarty_Internal_Template::$tplObjCache = array();
1124
    }
1125
1126
    /**
1127
     * @param boolean $use_sub_dirs
1128
     */
1129
    public function setUseSubDirs($use_sub_dirs)
1130
    {
1131
        $this->use_sub_dirs = $use_sub_dirs;
1132
    }
1133
1134
    /**
1135
     * @param int $error_reporting
1136
     */
1137
    public function setErrorReporting($error_reporting)
1138
    {
1139
        $this->error_reporting = $error_reporting;
1140
    }
1141
1142
    /**
1143
     * @param boolean $escape_html
1144
     */
1145
    public function setEscapeHtml($escape_html)
1146
    {
1147
        $this->escape_html = $escape_html;
1148
    }
1149
1150
    /**
1151
     * Return auto_literal flag
1152
     *
1153
     * @return boolean
1154
     */
1155
    public function getAutoLiteral()
1156
    {
1157
        return $this->auto_literal;
1158
    }
1159
1160
    /**
1161
     * Set auto_literal flag
1162
     *
1163
     * @param boolean $auto_literal
1164
     */
1165
    public function setAutoLiteral($auto_literal = true)
1166
    {
1167
        $this->auto_literal = $auto_literal;
1168
    }
1169
1170
    /**
1171
     * @param boolean $force_compile
1172
     */
1173
    public function setForceCompile($force_compile)
1174
    {
1175
        $this->force_compile = $force_compile;
1176
    }
1177
1178
    /**
1179
     * @param boolean $merge_compiled_includes
1180
     */
1181
    public function setMergeCompiledIncludes($merge_compiled_includes)
1182
    {
1183
        $this->merge_compiled_includes = $merge_compiled_includes;
1184
    }
1185
1186
    /**
1187
     * Get left delimiter
1188
     *
1189
     * @return string
1190
     */
1191
    public function getLeftDelimiter()
1192
    {
1193
        return $this->left_delimiter;
1194
    }
1195
1196
    /**
1197
     * Set left delimiter
1198
     *
1199
     * @param string $left_delimiter
1200
     */
1201
    public function setLeftDelimiter($left_delimiter)
1202
    {
1203
        $this->left_delimiter = $left_delimiter;
1204
    }
1205
1206
    /**
1207
     * Get right delimiter
1208
     *
1209
     * @return string $right_delimiter
1210
     */
1211
    public function getRightDelimiter()
1212
    {
1213
        return $this->right_delimiter;
1214
    }
1215
1216
    /**
1217
     * Set right delimiter
1218
     *
1219
     * @param string
1220
     */
1221
    public function setRightDelimiter($right_delimiter)
1222
    {
1223
        $this->right_delimiter = $right_delimiter;
1224
    }
1225
1226
    /**
1227
     * @param boolean $debugging
1228
     */
1229
    public function setDebugging($debugging)
1230
    {
1231
        $this->debugging = $debugging;
1232
    }
1233
1234
    /**
1235
     * @param boolean $config_overwrite
1236
     */
1237
    public function setConfigOverwrite($config_overwrite)
1238
    {
1239
        $this->config_overwrite = $config_overwrite;
1240
    }
1241
1242
    /**
1243
     * @param boolean $config_booleanize
1244
     */
1245
    public function setConfigBooleanize($config_booleanize)
1246
    {
1247
        $this->config_booleanize = $config_booleanize;
1248
    }
1249
1250
    /**
1251
     * @param boolean $config_read_hidden
1252
     */
1253
    public function setConfigReadHidden($config_read_hidden)
1254
    {
1255
        $this->config_read_hidden = $config_read_hidden;
1256
    }
1257
1258
    /**
1259
     * @param boolean $compile_locking
1260
     */
1261
    public function setCompileLocking($compile_locking)
1262
    {
1263
        $this->compile_locking = $compile_locking;
1264
    }
1265
1266
    /**
1267
     * @param string $default_resource_type
1268
     */
1269
    public function setDefaultResourceType($default_resource_type)
1270
    {
1271
        $this->default_resource_type = $default_resource_type;
1272
    }
1273
1274
    /**
1275
     * @param string $caching_type
1276
     */
1277
    public function setCachingType($caching_type)
1278
    {
1279
        $this->caching_type = $caching_type;
1280
    }
1281
1282
    /**
1283
     * Test install
1284
     *
1285
     * @param null $errors
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $errors is correct as it would always require null to be passed?
Loading history...
1286
     */
1287
    public function testInstall(&$errors = null)
1288
    {
1289
        Smarty_Internal_TestInstall::testInstall($this, $errors);
1290
    }
1291
1292
    /**
1293
     * Get Smarty object
1294
     *
1295
     * @return Smarty
1296
     */
1297
    public function _getSmartyObj()
1298
    {
1299
        return $this;
1300
    }
1301
1302
    /**
1303
     * <<magic>> Generic getter.
1304
     * Calls the appropriate getter function.
1305
     * Issues an E_USER_NOTICE if no valid getter is found.
1306
     *
1307
     * @param string $name property name
1308
     *
1309
     * @return mixed
1310
     */
1311
    public function __get($name)
1312
    {
1313
        if (isset($this->accessMap[ $name ])) {
1314
            $method = 'get' . $this->accessMap[ $name ];
1315
            return $this->{$method}();
1316
        } elseif (isset($this->_cache[ $name ])) {
1317
            return $this->_cache[ $name ];
1318
        } elseif (in_array($name, $this->obsoleteProperties)) {
1319
            return null;
1320
        } else {
1321
            trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1322
        }
1323
        return null;
1324
    }
1325
1326
    /**
1327
     * <<magic>> Generic setter.
1328
     * Calls the appropriate setter function.
1329
     * Issues an E_USER_NOTICE if no valid setter is found.
1330
     *
1331
     * @param string $name  property name
1332
     * @param mixed  $value parameter passed to setter
1333
     *
1334
     */
1335
    public function __set($name, $value)
1336
    {
1337
        if (isset($this->accessMap[ $name ])) {
1338
            $method = 'set' . $this->accessMap[ $name ];
1339
            $this->{$method}($value);
1340
        } elseif (in_array($name, $this->obsoleteProperties)) {
1341
            return;
1342
        } elseif (is_object($value) && method_exists($value, $name)) {
1343
            $this->$name = $value;
1344
        } else {
1345
            trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1346
        }
1347
    }
1348
1349
    /**
1350
     * Normalize and set directory string
1351
     *
1352
     * @param string $dirName cache_dir or compile_dir
1353
     * @param string $dir     filepath of folder
1354
     */
1355
    private function _normalizeDir($dirName, $dir)
1356
    {
1357
        $this->{$dirName} = $this->_realpath(rtrim($dir ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
1358
    }
1359
1360
    /**
1361
     * Normalize template_dir or config_dir
1362
     *
1363
     * @param bool $isConfig true for config_dir
1364
     */
1365
    private function _normalizeTemplateConfig($isConfig)
1366
    {
1367
        if ($isConfig) {
1368
            $processed = &$this->_processedConfigDir;
1369
            $dir = &$this->config_dir;
1370
        } else {
1371
            $processed = &$this->_processedTemplateDir;
1372
            $dir = &$this->template_dir;
1373
        }
1374
        if (!is_array($dir)) {
0 ignored issues
show
introduced by
The condition is_array($dir) is always true.
Loading history...
1375
            $dir = (array)$dir;
1376
        }
1377
        foreach ($dir as $k => $v) {
1378
            if (!isset($processed[ $k ])) {
1379
                $dir[ $k ] = $v = $this->_realpath(rtrim($v ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
1380
                $processed[ $k ] = true;
1381
            }
1382
        }
1383
        $isConfig ? $this->_configDirNormalized = true : $this->_templateDirNormalized = true;
1384
        $isConfig ? $this->_joined_config_dir = join('#', $this->config_dir) :
1385
            $this->_joined_template_dir = join('#', $this->template_dir);
1386
    }
1387
1388
    /**
1389
     * Mutes errors for "undefined index", "undefined array key" and "trying to read property of null".
1390
     *
1391
     * @void
1392
     */
1393
    public function muteUndefinedOrNullWarnings(): void {
1394
        $this->isMutingUndefinedOrNullWarnings = true;
1395
    }
1396
1397
    /**
1398
     * Indicates if Smarty will mute errors for "undefined index", "undefined array key" and "trying to read property of null".
1399
     * @bool
1400
     */
1401
    public function isMutingUndefinedOrNullWarnings(): bool {
1402
        return $this->isMutingUndefinedOrNullWarnings;
1403
    }
1404
1405
}
1406