Passed
Pull Request — master (#1322)
by Richard
08:51
created

Smarty::setPluginsDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
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      http://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', dirname(__FILE__) . 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
if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
64
    // UTF-8 can only be done properly when mbstring is available!
65
    /**
66
     * @deprecated in favor of Smarty::$_CHARSET
67
     */
68
    define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
69
}
70
if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
71
    /**
72
     * @deprecated in favor of Smarty::$_DATE_FORMAT
73
     */
74
    define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
75
}
76
/**
77
 * Load Smarty_Autoloader
78
 */
79
if (!class_exists('Smarty_Autoloader')) {
80
    include dirname(__FILE__) . '/bootstrap.php';
81
}
82
/**
83
 * Load always needed external class files
84
 */
85
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
86
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
87
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
88
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
89
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
90
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
91
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
92
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
93
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
94
95
/**
96
 * This is the main Smarty class
97
 *
98
 * @package Smarty
99
 *
100
 * The following methods will be dynamically loaded by the extension handler when they are called.
101
 * They are located in a corresponding Smarty_Internal_Method_xxxx class
102
 *
103
 * @method int clearAllCache(int $exp_time = null, string $type = null)
104
 * @method int clearCache(string $template_name, string $cache_id = null, string $compile_id = null, int $exp_time = null, string $type = null)
105
 * @method int compileAllTemplates(string $extension = '.tpl', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
106
 * @method int compileAllConfig(string $extension = '.conf', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
107
 * @method int clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
108
 */
109
class Smarty extends Smarty_Internal_TemplateBase
110
{
111
    /**
112
     * smarty version
113
     */
114
    const SMARTY_VERSION = '3.1.48';
115
    /**
116
     * define variable scopes
117
     */
118
    const SCOPE_LOCAL    = 1;
119
    const SCOPE_PARENT   = 2;
120
    const SCOPE_TPL_ROOT = 4;
121
    const SCOPE_ROOT     = 8;
122
    const SCOPE_SMARTY   = 16;
123
    const SCOPE_GLOBAL   = 32;
124
    /**
125
     * define caching modes
126
     */
127
    const CACHING_OFF              = 0;
128
    const CACHING_LIFETIME_CURRENT = 1;
129
    const CACHING_LIFETIME_SAVED   = 2;
130
    /**
131
     * define constant for clearing cache files be saved expiration dates
132
     */
133
    const CLEAR_EXPIRED = -1;
134
    /**
135
     * define compile check modes
136
     */
137
    const COMPILECHECK_OFF       = 0;
138
    const COMPILECHECK_ON        = 1;
139
    const COMPILECHECK_CACHEMISS = 2;
140
    /**
141
     * define debug modes
142
     */
143
    const DEBUG_OFF        = 0;
144
    const DEBUG_ON         = 1;
145
    const DEBUG_INDIVIDUAL = 2;
146
    /**
147
     * modes for handling of "<?php ... ?>" tags in templates.
148
     */
149
    const PHP_PASSTHRU = 0; //-> print tags as plain text
150
    const PHP_QUOTE    = 1; //-> escape tags as entities
151
    const PHP_REMOVE   = 2; //-> escape tags as entities
152
    const PHP_ALLOW    = 3; //-> escape tags as entities
153
    /**
154
     * filter types
155
     */
156
    const FILTER_POST     = 'post';
157
    const FILTER_PRE      = 'pre';
158
    const FILTER_OUTPUT   = 'output';
159
    const FILTER_VARIABLE = 'variable';
160
    /**
161
     * plugin types
162
     */
163
    const PLUGIN_FUNCTION         = 'function';
164
    const PLUGIN_BLOCK            = 'block';
165
    const PLUGIN_COMPILER         = 'compiler';
166
    const PLUGIN_MODIFIER         = 'modifier';
167
    const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
168
169
    /**
170
     * assigned global tpl vars
171
     */
172
    public static $global_tpl_vars = array();
173
174
    /**
175
     * Flag denoting if Multibyte String functions are available
176
     */
177
    public static $_MBSTRING = SMARTY_MBSTRING;
178
179
    /**
180
     * The character set to adhere to (e.g. "UTF-8")
181
     */
182
    public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
0 ignored issues
show
introduced by
The constant SMARTY_RESOURCE_CHAR_SET has been deprecated: in favor of Smarty::$_CHARSET ( Ignorable by Annotation )

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

182
    public static $_CHARSET = /** @scrutinizer ignore-deprecated */ SMARTY_RESOURCE_CHAR_SET;
Loading history...
183
184
    /**
185
     * The date format to be used internally
186
     * (accepts date() and strftime())
187
     */
188
    public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
0 ignored issues
show
introduced by
The constant SMARTY_RESOURCE_DATE_FORMAT has been deprecated: in favor of Smarty::$_DATE_FORMAT ( Ignorable by Annotation )

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

188
    public static $_DATE_FORMAT = /** @scrutinizer ignore-deprecated */ SMARTY_RESOURCE_DATE_FORMAT;
Loading history...
189
190
    /**
191
     * Flag denoting if PCRE should run in UTF-8 mode
192
     */
193
    public static $_UTF8_MODIFIER = 'u';
194
195
    /**
196
     * Flag denoting if operating system is windows
197
     */
198
    public static $_IS_WINDOWS = false;
199
200
    /**
201
     * auto literal on delimiters with whitespace
202
     *
203
     * @var boolean
204
     */
205
    public $auto_literal = true;
206
207
    /**
208
     * display error on not assigned variables
209
     *
210
     * @var boolean
211
     */
212
    public $error_unassigned = false;
213
214
    /**
215
     * look up relative file path in include_path
216
     *
217
     * @var boolean
218
     */
219
    public $use_include_path = false;
220
221
    /**
222
     * flag if template_dir is normalized
223
     *
224
     * @var bool
225
     */
226
    public $_templateDirNormalized = false;
227
228
    /**
229
     * joined template directory string used in cache keys
230
     *
231
     * @var string
232
     */
233
    public $_joined_template_dir = null;
234
235
    /**
236
     * flag if config_dir is normalized
237
     *
238
     * @var bool
239
     */
240
    public $_configDirNormalized = false;
241
242
    /**
243
     * joined config directory string used in cache keys
244
     *
245
     * @var string
246
     */
247
    public $_joined_config_dir = null;
248
249
    /**
250
     * default template handler
251
     *
252
     * @var callable
253
     */
254
    public $default_template_handler_func = null;
255
256
    /**
257
     * default config handler
258
     *
259
     * @var callable
260
     */
261
    public $default_config_handler_func = null;
262
263
    /**
264
     * default plugin handler
265
     *
266
     * @var callable
267
     */
268
    public $default_plugin_handler_func = null;
269
270
    /**
271
     * flag if template_dir is normalized
272
     *
273
     * @var bool
274
     */
275
    public $_compileDirNormalized = false;
276
277
    /**
278
     * flag if plugins_dir is normalized
279
     *
280
     * @var bool
281
     */
282
    public $_pluginsDirNormalized = false;
283
284
    /**
285
     * flag if template_dir is normalized
286
     *
287
     * @var bool
288
     */
289
    public $_cacheDirNormalized = false;
290
291
    /**
292
     * force template compiling?
293
     *
294
     * @var boolean
295
     */
296
    public $force_compile = false;
297
298
    /**
299
     * use sub dirs for compiled/cached files?
300
     *
301
     * @var boolean
302
     */
303
    public $use_sub_dirs = false;
304
305
    /**
306
     * allow ambiguous resources (that are made unique by the resource handler)
307
     *
308
     * @var boolean
309
     */
310
    public $allow_ambiguous_resources = false;
311
312
    /**
313
     * merge compiled includes
314
     *
315
     * @var boolean
316
     */
317
    public $merge_compiled_includes = false;
318
319
    /*
320
    * flag for behaviour when extends: resource  and {extends} tag are used simultaneous
321
    *   if false disable execution of {extends} in templates called by extends resource.
322
    *   (behaviour as versions < 3.1.28)
323
    *
324
    * @var boolean
325
    */
326
    public $extends_recursion = true;
327
328
    /**
329
     * force cache file creation
330
     *
331
     * @var boolean
332
     */
333
    public $force_cache = false;
334
335
    /**
336
     * template left-delimiter
337
     *
338
     * @var string
339
     */
340
    public $left_delimiter = "{";
341
342
    /**
343
     * template right-delimiter
344
     *
345
     * @var string
346
     */
347
    public $right_delimiter = "}";
348
349
    /**
350
     * array of strings which shall be treated as literal by compiler
351
     *
352
     * @var array string
353
     */
354
    public $literals = array();
355
356
    /**
357
     * class name
358
     * This should be instance of Smarty_Security.
359
     *
360
     * @var string
361
     * @see Smarty_Security
362
     */
363
    public $security_class = 'Smarty_Security';
364
365
    /**
366
     * implementation of security class
367
     *
368
     * @var Smarty_Security
369
     */
370
    public $security_policy = null;
371
372
    /**
373
     * controls handling of PHP-blocks
374
     *
375
     * @var integer
376
     */
377
    public $php_handling = self::PHP_PASSTHRU;
378
379
    /**
380
     * controls if the php template file resource is allowed
381
     *
382
     * @var bool
383
     */
384
    public $allow_php_templates = false;
385
386
    /**
387
     * debug mode
388
     * Setting this to true enables the debug-console.
389
     *
390
     * @var boolean
391
     */
392
    public $debugging = false;
393
394
    /**
395
     * This determines if debugging is enable-able from the browser.
396
     * <ul>
397
     *  <li>NONE => no debugging control allowed</li>
398
     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
399
     * </ul>
400
     *
401
     * @var string
402
     */
403
    public $debugging_ctrl = 'NONE';
404
405
    /**
406
     * Name of debugging URL-param.
407
     * Only used when $debugging_ctrl is set to 'URL'.
408
     * The name of the URL-parameter that activates debugging.
409
     *
410
     * @var string
411
     */
412
    public $smarty_debug_id = 'SMARTY_DEBUG';
413
414
    /**
415
     * Path of debug template.
416
     *
417
     * @var string
418
     */
419
    public $debug_tpl = null;
420
421
    /**
422
     * When set, smarty uses this value as error_reporting-level.
423
     *
424
     * @var int
425
     */
426
    public $error_reporting = null;
427
428
    /**
429
     * Controls whether variables with the same name overwrite each other.
430
     *
431
     * @var boolean
432
     */
433
    public $config_overwrite = true;
434
435
    /**
436
     * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
437
     *
438
     * @var boolean
439
     */
440
    public $config_booleanize = true;
441
442
    /**
443
     * Controls whether hidden config sections/vars are read from the file.
444
     *
445
     * @var boolean
446
     */
447
    public $config_read_hidden = false;
448
449
    /**
450
     * locking concurrent compiles
451
     *
452
     * @var boolean
453
     */
454
    public $compile_locking = true;
455
456
    /**
457
     * Controls whether cache resources should use locking mechanism
458
     *
459
     * @var boolean
460
     */
461
    public $cache_locking = false;
462
463
    /**
464
     * seconds to wait for acquiring a lock before ignoring the write lock
465
     *
466
     * @var float
467
     */
468
    public $locking_timeout = 10;
469
470
    /**
471
     * resource type used if none given
472
     * Must be an valid key of $registered_resources.
473
     *
474
     * @var string
475
     */
476
    public $default_resource_type = 'file';
477
478
    /**
479
     * caching type
480
     * Must be an element of $cache_resource_types.
481
     *
482
     * @var string
483
     */
484
    public $caching_type = 'file';
485
486
    /**
487
     * config type
488
     *
489
     * @var string
490
     */
491
    public $default_config_type = 'file';
492
493
    /**
494
     * check If-Modified-Since headers
495
     *
496
     * @var boolean
497
     */
498
    public $cache_modified_check = false;
499
500
    /**
501
     * registered plugins
502
     *
503
     * @var array
504
     */
505
    public $registered_plugins = array();
506
507
    /**
508
     * registered objects
509
     *
510
     * @var array
511
     */
512
    public $registered_objects = array();
513
514
    /**
515
     * registered classes
516
     *
517
     * @var array
518
     */
519
    public $registered_classes = array();
520
521
    /**
522
     * registered filters
523
     *
524
     * @var array
525
     */
526
    public $registered_filters = array();
527
528
    /**
529
     * registered resources
530
     *
531
     * @var array
532
     */
533
    public $registered_resources = array();
534
535
    /**
536
     * registered cache resources
537
     *
538
     * @var array
539
     */
540
    public $registered_cache_resources = array();
541
542
    /**
543
     * autoload filter
544
     *
545
     * @var array
546
     */
547
    public $autoload_filters = array();
548
549
    /**
550
     * default modifier
551
     *
552
     * @var array
553
     */
554
    public $default_modifiers = array();
555
556
    /**
557
     * autoescape variable output
558
     *
559
     * @var boolean
560
     */
561
    public $escape_html = false;
562
563
    /**
564
     * start time for execution time calculation
565
     *
566
     * @var int
567
     */
568
    public $start_time = 0;
569
570
    /**
571
     * required by the compiler for BC
572
     *
573
     * @var string
574
     */
575
    public $_current_file = null;
576
577
    /**
578
     * internal flag to enable parser debugging
579
     *
580
     * @var bool
581
     */
582
    public $_parserdebug = false;
583
584
    /**
585
     * This object type (Smarty = 1, template = 2, data = 4)
586
     *
587
     * @var int
588
     */
589
    public $_objType = 1;
590
591
    /**
592
     * Debug object
593
     *
594
     * @var Smarty_Internal_Debug
595
     */
596
    public $_debug = null;
597
598
    /**
599
     * template directory
600
     *
601
     * @var array
602
     */
603
    protected $template_dir = array('./templates/');
604
605
    /**
606
     * flags for normalized template directory entries
607
     *
608
     * @var array
609
     */
610
    protected $_processedTemplateDir = array();
611
612
    /**
613
     * config directory
614
     *
615
     * @var array
616
     */
617
    protected $config_dir = array('./configs/');
618
619
    /**
620
     * flags for normalized template directory entries
621
     *
622
     * @var array
623
     */
624
    protected $_processedConfigDir = array();
625
626
    /**
627
     * compile directory
628
     *
629
     * @var string
630
     */
631
    protected $compile_dir = './templates_c/';
632
633
    /**
634
     * plugins directory
635
     *
636
     * @var array
637
     */
638
    protected $plugins_dir = array();
639
640
    /**
641
     * cache directory
642
     *
643
     * @var string
644
     */
645
    protected $cache_dir = './cache/';
646
647
    /**
648
     * removed properties
649
     *
650
     * @var string[]
651
     */
652
    protected $obsoleteProperties = array(
653
        'resource_caching', 'template_resource_caching', 'direct_access_security',
654
        '_dir_perms', '_file_perms', 'plugin_search_order',
655
        'inheritance_merge_compiled_includes', 'resource_cache_mode',
656
    );
657
658
    /**
659
     * List of private properties which will call getter/setter on a direct access
660
     *
661
     * @var string[]
662
     */
663
    protected $accessMap = array(
664
        'template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir',
665
        'plugins_dir'  => 'PluginsDir', 'compile_dir' => 'CompileDir',
666
        'cache_dir'    => 'CacheDir',
667
    );
668
669
    /**
670
     * Initialize new Smarty object
671
     */
672
    public function __construct()
673
    {
674
        $this->_clearTemplateCache();
675
        parent::__construct();
676
        if (is_callable('mb_internal_encoding')) {
677
            mb_internal_encoding(Smarty::$_CHARSET);
678
        }
679
        $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...
680
        if (isset($_SERVER[ 'SCRIPT_NAME' ])) {
681
            Smarty::$global_tpl_vars[ 'SCRIPT_NAME' ] = new Smarty_Variable($_SERVER[ 'SCRIPT_NAME' ]);
682
        }
683
        // Check if we're running on windows
684
        Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
685
        // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
686
        if (Smarty::$_CHARSET !== 'UTF-8') {
687
            Smarty::$_UTF8_MODIFIER = '';
688
        }
689
    }
690
691
    /**
692
     * Enable error handler to mute expected messages
693
     *
694
     * @return     boolean
695
     * @deprecated
696
     */
697
    public static function muteExpectedErrors()
698
    {
699
        return Smarty_Internal_ErrorHandler::muteExpectedErrors();
0 ignored issues
show
Bug introduced by
Are you sure the usage of Smarty_Internal_ErrorHandler::muteExpectedErrors() targeting Smarty_Internal_ErrorHandler::muteExpectedErrors() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

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