Completed
Push — master ( bf2930...494091 )
by David
07:08 queued 03:26
created
lib/Dwoo/Smarty/Adapter.php 1 patch
Indentation   +657 added lines, -657 removed lines patch added patch discarded remove patch
@@ -26,14 +26,14 @@  discard block
 block discarded – undo
26 26
 use Dwoo\Smarty\Processor\Adapter as ProcessorAdapter;
27 27
 
28 28
 if (!defined('DIR_SEP')) {
29
-    define('DIR_SEP', DIRECTORY_SEPARATOR);
29
+	define('DIR_SEP', DIRECTORY_SEPARATOR);
30 30
 }
31 31
 
32 32
 if (!defined('SMARTY_PHP_PASSTHRU')) {
33
-    define('SMARTY_PHP_PASSTHRU', 0);
34
-    define('SMARTY_PHP_QUOTE', 1);
35
-    define('SMARTY_PHP_REMOVE', 2);
36
-    define('SMARTY_PHP_ALLOW', 3);
33
+	define('SMARTY_PHP_PASSTHRU', 0);
34
+	define('SMARTY_PHP_QUOTE', 1);
35
+	define('SMARTY_PHP_REMOVE', 2);
36
+	define('SMARTY_PHP_ALLOW', 3);
37 37
 }
38 38
 
39 39
 /**
@@ -43,656 +43,656 @@  discard block
 block discarded – undo
43 43
  */
44 44
 class Adapter extends Core
45 45
 {
46
-    /**
47
-     * Magic get/set/call functions that handle unsupported features
48
-     *
49
-     * @param string $p
50
-     * @param string $v
51
-     */
52
-    public function __set($p, $v)
53
-    {
54
-        if ($p === 'scope') {
55
-            $this->scope = $v;
56
-
57
-            return;
58
-        }
59
-        if ($p === 'data') {
60
-            $this->data = $v;
61
-
62
-            return;
63
-        }
64
-        if (array_key_exists($p, $this->compat['properties']) !== false) {
65
-            if ($this->show_compat_errors) {
66
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
67
-            }
68
-            $this->compat['properties'][$p] = $v;
69
-        } else {
70
-            if ($this->show_compat_errors) {
71
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
72
-            }
73
-        }
74
-    }
75
-
76
-    /**
77
-     * @param $p
78
-     *
79
-     * @return mixed
80
-     */
81
-    public function __get($p)
82
-    {
83
-        if (array_key_exists($p, $this->compat['properties']) !== false) {
84
-            if ($this->show_compat_errors) {
85
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
86
-            }
87
-
88
-            return $this->compat['properties'][$p];
89
-        } else {
90
-            if ($this->show_compat_errors) {
91
-                $this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
92
-            }
93
-        }
94
-    }
95
-
96
-    /**
97
-     * @param string $m
98
-     * @param array  $a
99
-     *
100
-     * @return mixed|void
101
-     */
102
-    public function __call($m, $a)
103
-    {
104
-        if (method_exists($this->dataProvider, $m)) {
105
-            call_user_func_array(
106
-                array(
107
-                $this->dataProvider,
108
-                $m
109
-                ), $a
110
-            );
111
-        } elseif ($this->show_compat_errors) {
112
-            if (array_search($m, $this->compat['methods']) !== false) {
113
-                $this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
114
-            } else {
115
-                $this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
116
-            }
117
-        }
118
-    }
119
-
120
-    /**
121
-     * List of unsupported properties and methods
122
-     */
123
-    protected $compat = array(
124
-        'methods'    => array(
125
-            'register_resource',
126
-            'unregister_resource',
127
-            'load_filter',
128
-            'clear_compiled_tpl',
129
-            'clear_config',
130
-            'get_config_vars',
131
-            'config_load',
132
-        ),
133
-        'properties' => array(
134
-            'cache_handler_func'            => null,
135
-            'debugging'                     => false,
136
-            'error_reporting'               => null,
137
-            'debugging_ctrl'                => 'NONE',
138
-            'request_vars_order'            => 'EGPCS',
139
-            'request_use_auto_globals'      => true,
140
-            'use_sub_dirs'                  => false,
141
-            'autoload_filters'              => array(),
142
-            'default_template_handler_func' => '',
143
-            'debug_tpl'                     => '',
144
-            'cache_modified_check'          => false,
145
-            'default_modifiers'             => array(),
146
-            'default_resource_type'         => 'file',
147
-            'config_overwrite'              => true,
148
-            'config_booleanize'             => true,
149
-            'config_read_hidden'            => false,
150
-            'config_fix_newlines'           => true,
151
-            'config_class'                  => 'Config_File',
152
-        ),
153
-    );
154
-
155
-    /**
156
-     * Security vars
157
-     */
158
-    public $security          = false;
159
-    public $trusted_dir       = array();
160
-    public $secure_dir        = array();
161
-    public $php_handling      = SMARTY_PHP_PASSTHRU;
162
-    public $security_settings = array(
163
-        'PHP_HANDLING'    => false,
164
-        'IF_FUNCS'        => array(
165
-            'list',
166
-            'empty',
167
-            'count',
168
-            'sizeof',
169
-            'in_array',
170
-            'is_array',
171
-        ),
172
-        'INCLUDE_ANY'     => false,
173
-        'PHP_TAGS'        => false,
174
-        'MODIFIER_FUNCS'  => array(),
175
-        'ALLOW_CONSTANTS' => false,
176
-    );
177
-
178
-    /**
179
-     * Paths
180
-     */
181
-    public $template_dir = 'templates';
182
-    public $compile_dir  = 'templates_c';
183
-    public $config_dir   = 'configs';
184
-    public $cache_dir    = 'cache';
185
-    public $plugins_dir  = array();
186
-
187
-    /**
188
-     * Misc options
189
-     */
190
-    public $left_delimiter  = '{';
191
-    public $right_delimiter = '}';
192
-    public $compile_check   = true;
193
-    public $force_compile   = false;
194
-    public $caching         = 0;
195
-    public $cache_lifetime  = 3600;
196
-    public $compile_id      = null;
197
-    public $compiler_file   = null;
198
-    public $compiler_class  = null;
199
-
200
-    /**
201
-     * Dwoo/Smarty compat layer
202
-     */
203
-    public           $show_compat_errors = false;
204
-    protected        $dataProvider;
205
-    protected        $_filters           = array(
206
-        'pre'    => array(),
207
-        'post'   => array(),
208
-        'output' => array()
209
-    );
210
-    protected static $tplCache           = array();
211
-    protected        $compiler           = null;
212
-
213
-    /**
214
-     * Adapter constructor.
215
-     */
216
-    public function __construct()
217
-    {
218
-        parent::__construct();
219
-        $this->charset      = 'iso-8859-1';
220
-        $this->dataProvider = new Data();
221
-        $this->compiler     = new Compiler();
222
-    }
223
-
224
-    /**
225
-     * @param      $filename
226
-     * @param null $cacheId
227
-     * @param null $compileId
228
-     */
229
-    public function display($filename, $cacheId = null, $compileId = null)
230
-    {
231
-        $this->fetch($filename, $cacheId, $compileId, true);
232
-    }
233
-
234
-    /**
235
-     * @param      $filename
236
-     * @param null $cacheId
237
-     * @param null $compileId
238
-     * @param bool $display
239
-     *
240
-     * @return string|void
241
-     */
242
-    public function fetch($filename, $cacheId = null, $compileId = null, $display = false)
243
-    {
244
-        $this->setCacheDir($this->cache_dir);
245
-        $this->setCompileDir($this->compile_dir);
246
-
247
-        if ($this->security) {
248
-            $policy = new SecurityPolicy();
249
-            $policy->addPhpFunction(array_merge($this->security_settings['IF_FUNCS'], $this->security_settings['MODIFIER_FUNCS']));
250
-
251
-            $phpTags = $this->security_settings['PHP_HANDLING'] ? SMARTY_PHP_ALLOW : $this->php_handling;
252
-            if ($this->security_settings['PHP_TAGS']) {
253
-                $phpTags = SMARTY_PHP_ALLOW;
254
-            }
255
-            switch ($phpTags) {
256
-            case SMARTY_PHP_ALLOW:
257
-            case SMARTY_PHP_PASSTHRU:
258
-                $phpTags = SecurityPolicy::PHP_ALLOW;
259
-                break;
260
-            case SMARTY_PHP_QUOTE:
261
-                $phpTags = SecurityPolicy::PHP_ENCODE;
262
-                break;
263
-            case SMARTY_PHP_REMOVE:
264
-            default:
265
-                $phpTags = SecurityPolicy::PHP_REMOVE;
266
-                break;
267
-            }
268
-            $policy->setPhpHandling($phpTags);
269
-
270
-            $policy->setConstantHandling($this->security_settings['ALLOW_CONSTANTS']);
271
-
272
-            if ($this->security_settings['INCLUDE_ANY']) {
273
-                $policy->allowDirectory(preg_replace('{^((?:[a-z]:)?[\\\\/]).*}i', '$1', __FILE__));
274
-            } else {
275
-                $policy->allowDirectory($this->secure_dir);
276
-            }
277
-
278
-            $this->setSecurityPolicy($policy);
279
-        }
280
-
281
-        if (!empty($this->plugins_dir)) {
282
-            foreach ($this->plugins_dir as $dir) {
283
-                $this->getLoader()->addDirectory(rtrim($dir, '\\/'));
284
-            }
285
-        }
286
-
287
-        $tpl = $this->makeTemplate($filename, $cacheId, $compileId);
288
-        if ($this->force_compile) {
289
-            $tpl->forceCompilation();
290
-        }
291
-
292
-        if ($this->caching > 0) {
293
-            $this->cacheTime = $this->cache_lifetime;
294
-        } else {
295
-            $this->cacheTime = 0;
296
-        }
297
-
298
-        if ($this->compiler_class !== null) {
299
-            if ($this->compiler_file !== null && !class_exists($this->compiler_class)) {
300
-                include $this->compiler_file;
301
-            }
302
-            $this->compiler = new $this->compiler_class();
303
-        } else {
304
-            $this->compiler->addPreProcessor('PluginSmartyCompatible', true);
305
-            $this->compiler->setLooseOpeningHandling(true);
306
-        }
307
-
308
-        $this->compiler->setDelimiters($this->left_delimiter, $this->right_delimiter);
309
-
310
-        return $this->get($tpl, $this->dataProvider, $this->compiler, $display === true);
311
-    }
312
-
313
-    /**
314
-     * @param mixed $_tpl
315
-     * @param array $data
316
-     * @param null  $_compiler
317
-     * @param bool  $_output
318
-     *
319
-     * @return string|void
320
-     */
321
-    public function get($_tpl, $data = array(), $_compiler = null, $_output = false)
322
-    {
323
-        if ($_compiler === null) {
324
-            $_compiler = $this->compiler;
325
-        }
326
-
327
-        return parent::get($_tpl, $data, $_compiler, $_output);
328
-    }
329
-
330
-    /**
331
-     * @param      $name
332
-     * @param      $callback
333
-     * @param bool $cacheable
334
-     * @param null $cache_attrs
335
-     *
336
-     * @throws Exception
337
-     */
338
-    public function register_function($name, $callback, $cacheable = true, $cache_attrs = null)
339
-    {
340
-        if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_FUNCTION) {
341
-            throw new Exception('Multiple plugins of different types can not share the same name');
342
-        }
343
-        $this->plugins[$name] = array(
344
-            'type'     => self::SMARTY_FUNCTION,
345
-            'callback' => $callback
346
-        );
347
-    }
348
-
349
-    /**
350
-     * @param $name
351
-     */
352
-    public function unregister_function($name)
353
-    {
354
-        unset($this->plugins[$name]);
355
-    }
356
-
357
-    /**
358
-     * @param      $name
359
-     * @param      $callback
360
-     * @param bool $cacheable
361
-     * @param null $cache_attrs
362
-     *
363
-     * @throws Exception
364
-     */
365
-    public function register_block($name, $callback, $cacheable = true, $cache_attrs = null)
366
-    {
367
-        if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_BLOCK) {
368
-            throw new Exception('Multiple plugins of different types can not share the same name');
369
-        }
370
-        $this->plugins[$name] = array(
371
-            'type'     => self::SMARTY_BLOCK,
372
-            'callback' => $callback
373
-        );
374
-    }
375
-
376
-    /**
377
-     * @param $name
378
-     */
379
-    public function unregister_block($name)
380
-    {
381
-        unset($this->plugins[$name]);
382
-    }
383
-
384
-    /**
385
-     * @param $name
386
-     * @param $callback
387
-     *
388
-     * @throws Exception
389
-     */
390
-    public function register_modifier($name, $callback)
391
-    {
392
-        if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_MODIFIER) {
393
-            throw new Exception('Multiple plugins of different types can not share the same name');
394
-        }
395
-        $this->plugins[$name] = array(
396
-            'type'     => self::SMARTY_MODIFIER,
397
-            'callback' => $callback
398
-        );
399
-    }
400
-
401
-    /**
402
-     * @param $name
403
-     */
404
-    public function unregister_modifier($name)
405
-    {
406
-        unset($this->plugins[$name]);
407
-    }
408
-
409
-    /**
410
-     * @param $callback
411
-     */
412
-    public function register_prefilter($callback)
413
-    {
414
-        $processor = new ProcessorAdapter($this->compiler);
415
-        $processor->registerCallback($callback);
416
-        $this->_filters['pre'][] = $processor;
417
-        $this->compiler->addPreProcessor($processor);
418
-    }
419
-
420
-    /**
421
-     * @param $callback
422
-     */
423
-    public function unregister_prefilter($callback)
424
-    {
425
-        foreach ($this->_filters['pre'] as $index => $processor) {
426
-            if ($processor->callback === $callback) {
427
-                $this->compiler->removePostProcessor($processor);
428
-                unset($this->_filters['pre'][$index]);
429
-            }
430
-        }
431
-    }
432
-
433
-    /**
434
-     * @param $callback
435
-     */
436
-    public function register_postfilter($callback)
437
-    {
438
-        $processor = new ProcessorAdapter($this->compiler);
439
-        $processor->registerCallback($callback);
440
-        $this->_filters['post'][] = $processor;
441
-        $this->compiler->addPostProcessor($processor);
442
-    }
443
-
444
-    /**
445
-     * @param $callback
446
-     */
447
-    public function unregister_postfilter($callback)
448
-    {
449
-        foreach ($this->_filters['post'] as $index => $processor) {
450
-            if ($processor->callback === $callback) {
451
-                $this->compiler->removePostProcessor($processor);
452
-                unset($this->_filters['post'][$index]);
453
-            }
454
-        }
455
-    }
456
-
457
-    /**
458
-     * @param $callback
459
-     */
460
-    public function register_outputfilter($callback)
461
-    {
462
-        $filter = new FilterAdapter($this);
463
-        $filter->registerCallback($callback);
464
-        $this->_filters['output'][] = $filter;
465
-        $this->addFilter($filter);
466
-    }
467
-
468
-    /**
469
-     * @param $callback
470
-     */
471
-    public function unregister_outputfilter($callback)
472
-    {
473
-        foreach ($this->_filters['output'] as $index => $filter) {
474
-            if ($filter->callback === $callback) {
475
-                $this->removeOutputFilter($filter);
476
-                unset($this->_filters['output'][$index]);
477
-            }
478
-        }
479
-    }
480
-
481
-    /**
482
-     * @param       $object
483
-     * @param       $object_impl
484
-     * @param array $allowed
485
-     * @param bool  $smarty_args
486
-     * @param array $block_methods
487
-     */
488
-    public function register_object($object, $object_impl, $allowed = array(), $smarty_args = false, $block_methods = array())
489
-    {
490
-        settype($allowed, 'array');
491
-        settype($block_methods, 'array');
492
-        settype($smarty_args, 'boolean');
493
-
494
-        if (!empty($allowed) && $this->show_compat_errors) {
495
-            $this->triggerError('You can register objects but can not restrict the method/properties used, this is PHP5, you have proper OOP access restrictions so use them.', E_USER_NOTICE);
496
-        }
497
-
498
-        if ($smarty_args) {
499
-            $this->triggerError('You can register objects but methods will be called using method($arg1, $arg2, $arg3), not as an argument array like smarty did.', E_USER_NOTICE);
500
-        }
501
-
502
-        if (!empty($block_methods)) {
503
-            $this->triggerError('You can register objects but can not use methods as being block methods, you have to build a plugin for that.', E_USER_NOTICE);
504
-        }
505
-
506
-        $this->dataProvider->assign($object, $object_impl);
507
-    }
508
-
509
-    /**
510
-     * @param $object
511
-     */
512
-    public function unregister_object($object)
513
-    {
514
-        $this->dataProvider->clear($object);
515
-    }
516
-
517
-    /**
518
-     * @param $name
519
-     *
520
-     * @return mixed
521
-     */
522
-    public function get_registered_object($name)
523
-    {
524
-        $data = $this->dataProvider->getData();
525
-        if (isset($data[$name]) && is_object($data[$name])) {
526
-            return $data[$name];
527
-        } else {
528
-            trigger_error('Dwoo_Compiler: object "' . $name . '" was not registered or is not an object', E_USER_ERROR);
529
-        }
530
-    }
531
-
532
-    /**
533
-     * @param $filename
534
-     *
535
-     * @return bool
536
-     */
537
-    public function template_exists($filename)
538
-    {
539
-        if (!is_array($this->template_dir)) {
540
-            return file_exists($this->template_dir . DIRECTORY_SEPARATOR . $filename);
541
-        } else {
542
-            foreach ($this->template_dir as $tpl_dir) {
543
-                if (file_exists($tpl_dir . DIRECTORY_SEPARATOR . $filename)) {
544
-                    return true;
545
-                }
546
-            }
547
-
548
-            return false;
549
-        }
550
-    }
551
-
552
-    /**
553
-     * @param      $tpl
554
-     * @param null $cacheId
555
-     * @param null $compileId
556
-     *
557
-     * @return bool
558
-     */
559
-    public function is_cached($tpl, $cacheId = null, $compileId = null)
560
-    {
561
-        return $this->isCached($this->makeTemplate($tpl, $cacheId, $compileId));
562
-    }
563
-
564
-    /**
565
-     * @param      $var
566
-     * @param      $value
567
-     * @param bool $merge
568
-     */
569
-    public function append_by_ref($var, &$value, $merge = false)
570
-    {
571
-        $this->dataProvider->appendByRef($var, $value, $merge);
572
-    }
573
-
574
-    /**
575
-     * @param $name
576
-     * @param $val
577
-     */
578
-    public function assign_by_ref($name, &$val)
579
-    {
580
-        $this->dataProvider->assignByRef($name, $val);
581
-    }
582
-
583
-    /**
584
-     * @param $var
585
-     */
586
-    public function clear_assign($var)
587
-    {
588
-        $this->dataProvider->clear($var);
589
-    }
590
-
591
-    /**
592
-     *
593
-     */
594
-    public function clear_all_assign()
595
-    {
596
-        $this->dataProvider->clear();
597
-    }
598
-
599
-    /**
600
-     * @param null $name
601
-     *
602
-     * @return array|null
603
-     */
604
-    public function get_template_vars($name = null)
605
-    {
606
-        if ($this->show_compat_errors) {
607
-            trigger_error('get_template_vars does not return values by reference, if you try to modify the data that way you should modify your code.', E_USER_NOTICE);
608
-        }
609
-
610
-        $data = $this->dataProvider->getData();
611
-        if ($name === null) {
612
-            return $data;
613
-        } elseif (isset($data[$name])) {
614
-            return $data[$name];
615
-        }
616
-
617
-        return null;
618
-    }
619
-
620
-    /**
621
-     * @param int $olderThan
622
-     */
623
-    public function clear_all_cache($olderThan = 0)
624
-    {
625
-        $this->clearCache($olderThan);
626
-    }
627
-
628
-    /**
629
-     * @param      $template
630
-     * @param null $cacheId
631
-     * @param null $compileId
632
-     * @param int  $olderThan
633
-     */
634
-    public function clear_cache($template, $cacheId = null, $compileId = null, $olderThan = 0)
635
-    {
636
-        $this->makeTemplate($template, $cacheId, $compileId)->clearCache($olderThan);
637
-    }
638
-
639
-    /**
640
-     * @param     $error_msg
641
-     * @param int $error_type
642
-     */
643
-    public function trigger_error($error_msg, $error_type = E_USER_WARNING)
644
-    {
645
-        $this->triggerError($error_msg, $error_type);
646
-    }
647
-
648
-    /**
649
-     *
650
-     */
651
-    protected function initGlobals()
652
-    {
653
-        parent::initGlobals();
654
-        $this->globals['ldelim'] = '{';
655
-        $this->globals['rdelim'] = '}';
656
-    }
657
-
658
-    /**
659
-     * @param $file
660
-     * @param $cacheId
661
-     * @param $compileId
662
-     *
663
-     * @return mixed
664
-     * @throws Exception
665
-     */
666
-    protected function makeTemplate($file, $cacheId, $compileId)
667
-    {
668
-        if ($compileId === null) {
669
-            $compileId = $this->compile_id;
670
-        }
671
-
672
-        $hash = bin2hex(md5($file . $cacheId . $compileId, true));
673
-        if (!isset(self::$tplCache[$hash])) {
674
-            // abs path
675
-            if (substr($file, 0, 1) === '/' || substr($file, 1, 1) === ':') {
676
-                self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId);
677
-            } elseif (is_string($this->template_dir) || is_array($this->template_dir)) {
678
-                self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId, $this->template_dir);
679
-            } else {
680
-                throw new Exception('Unable to load "' . $file . '", check the template_dir');
681
-            }
682
-        }
683
-
684
-        return self::$tplCache[$hash];
685
-    }
686
-
687
-    /**
688
-     * @param string $message
689
-     * @param int    $level
690
-     */
691
-    public function triggerError($message, $level = E_USER_NOTICE)
692
-    {
693
-        if (is_object($this->template)) {
694
-            parent::triggerError($message, $level);
695
-        }
696
-        trigger_error('Dwoo error : ' . $message, $level);
697
-    }
46
+	/**
47
+	 * Magic get/set/call functions that handle unsupported features
48
+	 *
49
+	 * @param string $p
50
+	 * @param string $v
51
+	 */
52
+	public function __set($p, $v)
53
+	{
54
+		if ($p === 'scope') {
55
+			$this->scope = $v;
56
+
57
+			return;
58
+		}
59
+		if ($p === 'data') {
60
+			$this->data = $v;
61
+
62
+			return;
63
+		}
64
+		if (array_key_exists($p, $this->compat['properties']) !== false) {
65
+			if ($this->show_compat_errors) {
66
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
67
+			}
68
+			$this->compat['properties'][$p] = $v;
69
+		} else {
70
+			if ($this->show_compat_errors) {
71
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
72
+			}
73
+		}
74
+	}
75
+
76
+	/**
77
+	 * @param $p
78
+	 *
79
+	 * @return mixed
80
+	 */
81
+	public function __get($p)
82
+	{
83
+		if (array_key_exists($p, $this->compat['properties']) !== false) {
84
+			if ($this->show_compat_errors) {
85
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
86
+			}
87
+
88
+			return $this->compat['properties'][$p];
89
+		} else {
90
+			if ($this->show_compat_errors) {
91
+				$this->triggerError('Property ' . $p . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
92
+			}
93
+		}
94
+	}
95
+
96
+	/**
97
+	 * @param string $m
98
+	 * @param array  $a
99
+	 *
100
+	 * @return mixed|void
101
+	 */
102
+	public function __call($m, $a)
103
+	{
104
+		if (method_exists($this->dataProvider, $m)) {
105
+			call_user_func_array(
106
+				array(
107
+				$this->dataProvider,
108
+				$m
109
+				), $a
110
+			);
111
+		} elseif ($this->show_compat_errors) {
112
+			if (array_search($m, $this->compat['methods']) !== false) {
113
+				$this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE);
114
+			} else {
115
+				$this->triggerError('Method ' . $m . ' is not available in the Dwoo\Smarty\Adapter, but it is not listed as such, so you might want to tell me about it at [email protected]', E_USER_NOTICE);
116
+			}
117
+		}
118
+	}
119
+
120
+	/**
121
+	 * List of unsupported properties and methods
122
+	 */
123
+	protected $compat = array(
124
+		'methods'    => array(
125
+			'register_resource',
126
+			'unregister_resource',
127
+			'load_filter',
128
+			'clear_compiled_tpl',
129
+			'clear_config',
130
+			'get_config_vars',
131
+			'config_load',
132
+		),
133
+		'properties' => array(
134
+			'cache_handler_func'            => null,
135
+			'debugging'                     => false,
136
+			'error_reporting'               => null,
137
+			'debugging_ctrl'                => 'NONE',
138
+			'request_vars_order'            => 'EGPCS',
139
+			'request_use_auto_globals'      => true,
140
+			'use_sub_dirs'                  => false,
141
+			'autoload_filters'              => array(),
142
+			'default_template_handler_func' => '',
143
+			'debug_tpl'                     => '',
144
+			'cache_modified_check'          => false,
145
+			'default_modifiers'             => array(),
146
+			'default_resource_type'         => 'file',
147
+			'config_overwrite'              => true,
148
+			'config_booleanize'             => true,
149
+			'config_read_hidden'            => false,
150
+			'config_fix_newlines'           => true,
151
+			'config_class'                  => 'Config_File',
152
+		),
153
+	);
154
+
155
+	/**
156
+	 * Security vars
157
+	 */
158
+	public $security          = false;
159
+	public $trusted_dir       = array();
160
+	public $secure_dir        = array();
161
+	public $php_handling      = SMARTY_PHP_PASSTHRU;
162
+	public $security_settings = array(
163
+		'PHP_HANDLING'    => false,
164
+		'IF_FUNCS'        => array(
165
+			'list',
166
+			'empty',
167
+			'count',
168
+			'sizeof',
169
+			'in_array',
170
+			'is_array',
171
+		),
172
+		'INCLUDE_ANY'     => false,
173
+		'PHP_TAGS'        => false,
174
+		'MODIFIER_FUNCS'  => array(),
175
+		'ALLOW_CONSTANTS' => false,
176
+	);
177
+
178
+	/**
179
+	 * Paths
180
+	 */
181
+	public $template_dir = 'templates';
182
+	public $compile_dir  = 'templates_c';
183
+	public $config_dir   = 'configs';
184
+	public $cache_dir    = 'cache';
185
+	public $plugins_dir  = array();
186
+
187
+	/**
188
+	 * Misc options
189
+	 */
190
+	public $left_delimiter  = '{';
191
+	public $right_delimiter = '}';
192
+	public $compile_check   = true;
193
+	public $force_compile   = false;
194
+	public $caching         = 0;
195
+	public $cache_lifetime  = 3600;
196
+	public $compile_id      = null;
197
+	public $compiler_file   = null;
198
+	public $compiler_class  = null;
199
+
200
+	/**
201
+	 * Dwoo/Smarty compat layer
202
+	 */
203
+	public           $show_compat_errors = false;
204
+	protected        $dataProvider;
205
+	protected        $_filters           = array(
206
+		'pre'    => array(),
207
+		'post'   => array(),
208
+		'output' => array()
209
+	);
210
+	protected static $tplCache           = array();
211
+	protected        $compiler           = null;
212
+
213
+	/**
214
+	 * Adapter constructor.
215
+	 */
216
+	public function __construct()
217
+	{
218
+		parent::__construct();
219
+		$this->charset      = 'iso-8859-1';
220
+		$this->dataProvider = new Data();
221
+		$this->compiler     = new Compiler();
222
+	}
223
+
224
+	/**
225
+	 * @param      $filename
226
+	 * @param null $cacheId
227
+	 * @param null $compileId
228
+	 */
229
+	public function display($filename, $cacheId = null, $compileId = null)
230
+	{
231
+		$this->fetch($filename, $cacheId, $compileId, true);
232
+	}
233
+
234
+	/**
235
+	 * @param      $filename
236
+	 * @param null $cacheId
237
+	 * @param null $compileId
238
+	 * @param bool $display
239
+	 *
240
+	 * @return string|void
241
+	 */
242
+	public function fetch($filename, $cacheId = null, $compileId = null, $display = false)
243
+	{
244
+		$this->setCacheDir($this->cache_dir);
245
+		$this->setCompileDir($this->compile_dir);
246
+
247
+		if ($this->security) {
248
+			$policy = new SecurityPolicy();
249
+			$policy->addPhpFunction(array_merge($this->security_settings['IF_FUNCS'], $this->security_settings['MODIFIER_FUNCS']));
250
+
251
+			$phpTags = $this->security_settings['PHP_HANDLING'] ? SMARTY_PHP_ALLOW : $this->php_handling;
252
+			if ($this->security_settings['PHP_TAGS']) {
253
+				$phpTags = SMARTY_PHP_ALLOW;
254
+			}
255
+			switch ($phpTags) {
256
+			case SMARTY_PHP_ALLOW:
257
+			case SMARTY_PHP_PASSTHRU:
258
+				$phpTags = SecurityPolicy::PHP_ALLOW;
259
+				break;
260
+			case SMARTY_PHP_QUOTE:
261
+				$phpTags = SecurityPolicy::PHP_ENCODE;
262
+				break;
263
+			case SMARTY_PHP_REMOVE:
264
+			default:
265
+				$phpTags = SecurityPolicy::PHP_REMOVE;
266
+				break;
267
+			}
268
+			$policy->setPhpHandling($phpTags);
269
+
270
+			$policy->setConstantHandling($this->security_settings['ALLOW_CONSTANTS']);
271
+
272
+			if ($this->security_settings['INCLUDE_ANY']) {
273
+				$policy->allowDirectory(preg_replace('{^((?:[a-z]:)?[\\\\/]).*}i', '$1', __FILE__));
274
+			} else {
275
+				$policy->allowDirectory($this->secure_dir);
276
+			}
277
+
278
+			$this->setSecurityPolicy($policy);
279
+		}
280
+
281
+		if (!empty($this->plugins_dir)) {
282
+			foreach ($this->plugins_dir as $dir) {
283
+				$this->getLoader()->addDirectory(rtrim($dir, '\\/'));
284
+			}
285
+		}
286
+
287
+		$tpl = $this->makeTemplate($filename, $cacheId, $compileId);
288
+		if ($this->force_compile) {
289
+			$tpl->forceCompilation();
290
+		}
291
+
292
+		if ($this->caching > 0) {
293
+			$this->cacheTime = $this->cache_lifetime;
294
+		} else {
295
+			$this->cacheTime = 0;
296
+		}
297
+
298
+		if ($this->compiler_class !== null) {
299
+			if ($this->compiler_file !== null && !class_exists($this->compiler_class)) {
300
+				include $this->compiler_file;
301
+			}
302
+			$this->compiler = new $this->compiler_class();
303
+		} else {
304
+			$this->compiler->addPreProcessor('PluginSmartyCompatible', true);
305
+			$this->compiler->setLooseOpeningHandling(true);
306
+		}
307
+
308
+		$this->compiler->setDelimiters($this->left_delimiter, $this->right_delimiter);
309
+
310
+		return $this->get($tpl, $this->dataProvider, $this->compiler, $display === true);
311
+	}
312
+
313
+	/**
314
+	 * @param mixed $_tpl
315
+	 * @param array $data
316
+	 * @param null  $_compiler
317
+	 * @param bool  $_output
318
+	 *
319
+	 * @return string|void
320
+	 */
321
+	public function get($_tpl, $data = array(), $_compiler = null, $_output = false)
322
+	{
323
+		if ($_compiler === null) {
324
+			$_compiler = $this->compiler;
325
+		}
326
+
327
+		return parent::get($_tpl, $data, $_compiler, $_output);
328
+	}
329
+
330
+	/**
331
+	 * @param      $name
332
+	 * @param      $callback
333
+	 * @param bool $cacheable
334
+	 * @param null $cache_attrs
335
+	 *
336
+	 * @throws Exception
337
+	 */
338
+	public function register_function($name, $callback, $cacheable = true, $cache_attrs = null)
339
+	{
340
+		if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_FUNCTION) {
341
+			throw new Exception('Multiple plugins of different types can not share the same name');
342
+		}
343
+		$this->plugins[$name] = array(
344
+			'type'     => self::SMARTY_FUNCTION,
345
+			'callback' => $callback
346
+		);
347
+	}
348
+
349
+	/**
350
+	 * @param $name
351
+	 */
352
+	public function unregister_function($name)
353
+	{
354
+		unset($this->plugins[$name]);
355
+	}
356
+
357
+	/**
358
+	 * @param      $name
359
+	 * @param      $callback
360
+	 * @param bool $cacheable
361
+	 * @param null $cache_attrs
362
+	 *
363
+	 * @throws Exception
364
+	 */
365
+	public function register_block($name, $callback, $cacheable = true, $cache_attrs = null)
366
+	{
367
+		if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_BLOCK) {
368
+			throw new Exception('Multiple plugins of different types can not share the same name');
369
+		}
370
+		$this->plugins[$name] = array(
371
+			'type'     => self::SMARTY_BLOCK,
372
+			'callback' => $callback
373
+		);
374
+	}
375
+
376
+	/**
377
+	 * @param $name
378
+	 */
379
+	public function unregister_block($name)
380
+	{
381
+		unset($this->plugins[$name]);
382
+	}
383
+
384
+	/**
385
+	 * @param $name
386
+	 * @param $callback
387
+	 *
388
+	 * @throws Exception
389
+	 */
390
+	public function register_modifier($name, $callback)
391
+	{
392
+		if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_MODIFIER) {
393
+			throw new Exception('Multiple plugins of different types can not share the same name');
394
+		}
395
+		$this->plugins[$name] = array(
396
+			'type'     => self::SMARTY_MODIFIER,
397
+			'callback' => $callback
398
+		);
399
+	}
400
+
401
+	/**
402
+	 * @param $name
403
+	 */
404
+	public function unregister_modifier($name)
405
+	{
406
+		unset($this->plugins[$name]);
407
+	}
408
+
409
+	/**
410
+	 * @param $callback
411
+	 */
412
+	public function register_prefilter($callback)
413
+	{
414
+		$processor = new ProcessorAdapter($this->compiler);
415
+		$processor->registerCallback($callback);
416
+		$this->_filters['pre'][] = $processor;
417
+		$this->compiler->addPreProcessor($processor);
418
+	}
419
+
420
+	/**
421
+	 * @param $callback
422
+	 */
423
+	public function unregister_prefilter($callback)
424
+	{
425
+		foreach ($this->_filters['pre'] as $index => $processor) {
426
+			if ($processor->callback === $callback) {
427
+				$this->compiler->removePostProcessor($processor);
428
+				unset($this->_filters['pre'][$index]);
429
+			}
430
+		}
431
+	}
432
+
433
+	/**
434
+	 * @param $callback
435
+	 */
436
+	public function register_postfilter($callback)
437
+	{
438
+		$processor = new ProcessorAdapter($this->compiler);
439
+		$processor->registerCallback($callback);
440
+		$this->_filters['post'][] = $processor;
441
+		$this->compiler->addPostProcessor($processor);
442
+	}
443
+
444
+	/**
445
+	 * @param $callback
446
+	 */
447
+	public function unregister_postfilter($callback)
448
+	{
449
+		foreach ($this->_filters['post'] as $index => $processor) {
450
+			if ($processor->callback === $callback) {
451
+				$this->compiler->removePostProcessor($processor);
452
+				unset($this->_filters['post'][$index]);
453
+			}
454
+		}
455
+	}
456
+
457
+	/**
458
+	 * @param $callback
459
+	 */
460
+	public function register_outputfilter($callback)
461
+	{
462
+		$filter = new FilterAdapter($this);
463
+		$filter->registerCallback($callback);
464
+		$this->_filters['output'][] = $filter;
465
+		$this->addFilter($filter);
466
+	}
467
+
468
+	/**
469
+	 * @param $callback
470
+	 */
471
+	public function unregister_outputfilter($callback)
472
+	{
473
+		foreach ($this->_filters['output'] as $index => $filter) {
474
+			if ($filter->callback === $callback) {
475
+				$this->removeOutputFilter($filter);
476
+				unset($this->_filters['output'][$index]);
477
+			}
478
+		}
479
+	}
480
+
481
+	/**
482
+	 * @param       $object
483
+	 * @param       $object_impl
484
+	 * @param array $allowed
485
+	 * @param bool  $smarty_args
486
+	 * @param array $block_methods
487
+	 */
488
+	public function register_object($object, $object_impl, $allowed = array(), $smarty_args = false, $block_methods = array())
489
+	{
490
+		settype($allowed, 'array');
491
+		settype($block_methods, 'array');
492
+		settype($smarty_args, 'boolean');
493
+
494
+		if (!empty($allowed) && $this->show_compat_errors) {
495
+			$this->triggerError('You can register objects but can not restrict the method/properties used, this is PHP5, you have proper OOP access restrictions so use them.', E_USER_NOTICE);
496
+		}
497
+
498
+		if ($smarty_args) {
499
+			$this->triggerError('You can register objects but methods will be called using method($arg1, $arg2, $arg3), not as an argument array like smarty did.', E_USER_NOTICE);
500
+		}
501
+
502
+		if (!empty($block_methods)) {
503
+			$this->triggerError('You can register objects but can not use methods as being block methods, you have to build a plugin for that.', E_USER_NOTICE);
504
+		}
505
+
506
+		$this->dataProvider->assign($object, $object_impl);
507
+	}
508
+
509
+	/**
510
+	 * @param $object
511
+	 */
512
+	public function unregister_object($object)
513
+	{
514
+		$this->dataProvider->clear($object);
515
+	}
516
+
517
+	/**
518
+	 * @param $name
519
+	 *
520
+	 * @return mixed
521
+	 */
522
+	public function get_registered_object($name)
523
+	{
524
+		$data = $this->dataProvider->getData();
525
+		if (isset($data[$name]) && is_object($data[$name])) {
526
+			return $data[$name];
527
+		} else {
528
+			trigger_error('Dwoo_Compiler: object "' . $name . '" was not registered or is not an object', E_USER_ERROR);
529
+		}
530
+	}
531
+
532
+	/**
533
+	 * @param $filename
534
+	 *
535
+	 * @return bool
536
+	 */
537
+	public function template_exists($filename)
538
+	{
539
+		if (!is_array($this->template_dir)) {
540
+			return file_exists($this->template_dir . DIRECTORY_SEPARATOR . $filename);
541
+		} else {
542
+			foreach ($this->template_dir as $tpl_dir) {
543
+				if (file_exists($tpl_dir . DIRECTORY_SEPARATOR . $filename)) {
544
+					return true;
545
+				}
546
+			}
547
+
548
+			return false;
549
+		}
550
+	}
551
+
552
+	/**
553
+	 * @param      $tpl
554
+	 * @param null $cacheId
555
+	 * @param null $compileId
556
+	 *
557
+	 * @return bool
558
+	 */
559
+	public function is_cached($tpl, $cacheId = null, $compileId = null)
560
+	{
561
+		return $this->isCached($this->makeTemplate($tpl, $cacheId, $compileId));
562
+	}
563
+
564
+	/**
565
+	 * @param      $var
566
+	 * @param      $value
567
+	 * @param bool $merge
568
+	 */
569
+	public function append_by_ref($var, &$value, $merge = false)
570
+	{
571
+		$this->dataProvider->appendByRef($var, $value, $merge);
572
+	}
573
+
574
+	/**
575
+	 * @param $name
576
+	 * @param $val
577
+	 */
578
+	public function assign_by_ref($name, &$val)
579
+	{
580
+		$this->dataProvider->assignByRef($name, $val);
581
+	}
582
+
583
+	/**
584
+	 * @param $var
585
+	 */
586
+	public function clear_assign($var)
587
+	{
588
+		$this->dataProvider->clear($var);
589
+	}
590
+
591
+	/**
592
+	 *
593
+	 */
594
+	public function clear_all_assign()
595
+	{
596
+		$this->dataProvider->clear();
597
+	}
598
+
599
+	/**
600
+	 * @param null $name
601
+	 *
602
+	 * @return array|null
603
+	 */
604
+	public function get_template_vars($name = null)
605
+	{
606
+		if ($this->show_compat_errors) {
607
+			trigger_error('get_template_vars does not return values by reference, if you try to modify the data that way you should modify your code.', E_USER_NOTICE);
608
+		}
609
+
610
+		$data = $this->dataProvider->getData();
611
+		if ($name === null) {
612
+			return $data;
613
+		} elseif (isset($data[$name])) {
614
+			return $data[$name];
615
+		}
616
+
617
+		return null;
618
+	}
619
+
620
+	/**
621
+	 * @param int $olderThan
622
+	 */
623
+	public function clear_all_cache($olderThan = 0)
624
+	{
625
+		$this->clearCache($olderThan);
626
+	}
627
+
628
+	/**
629
+	 * @param      $template
630
+	 * @param null $cacheId
631
+	 * @param null $compileId
632
+	 * @param int  $olderThan
633
+	 */
634
+	public function clear_cache($template, $cacheId = null, $compileId = null, $olderThan = 0)
635
+	{
636
+		$this->makeTemplate($template, $cacheId, $compileId)->clearCache($olderThan);
637
+	}
638
+
639
+	/**
640
+	 * @param     $error_msg
641
+	 * @param int $error_type
642
+	 */
643
+	public function trigger_error($error_msg, $error_type = E_USER_WARNING)
644
+	{
645
+		$this->triggerError($error_msg, $error_type);
646
+	}
647
+
648
+	/**
649
+	 *
650
+	 */
651
+	protected function initGlobals()
652
+	{
653
+		parent::initGlobals();
654
+		$this->globals['ldelim'] = '{';
655
+		$this->globals['rdelim'] = '}';
656
+	}
657
+
658
+	/**
659
+	 * @param $file
660
+	 * @param $cacheId
661
+	 * @param $compileId
662
+	 *
663
+	 * @return mixed
664
+	 * @throws Exception
665
+	 */
666
+	protected function makeTemplate($file, $cacheId, $compileId)
667
+	{
668
+		if ($compileId === null) {
669
+			$compileId = $this->compile_id;
670
+		}
671
+
672
+		$hash = bin2hex(md5($file . $cacheId . $compileId, true));
673
+		if (!isset(self::$tplCache[$hash])) {
674
+			// abs path
675
+			if (substr($file, 0, 1) === '/' || substr($file, 1, 1) === ':') {
676
+				self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId);
677
+			} elseif (is_string($this->template_dir) || is_array($this->template_dir)) {
678
+				self::$tplCache[$hash] = new TemplateFile($file, null, $cacheId, $compileId, $this->template_dir);
679
+			} else {
680
+				throw new Exception('Unable to load "' . $file . '", check the template_dir');
681
+			}
682
+		}
683
+
684
+		return self::$tplCache[$hash];
685
+	}
686
+
687
+	/**
688
+	 * @param string $message
689
+	 * @param int    $level
690
+	 */
691
+	public function triggerError($message, $level = E_USER_NOTICE)
692
+	{
693
+		if (is_object($this->template)) {
694
+			parent::triggerError($message, $level);
695
+		}
696
+		trigger_error('Dwoo error : ' . $message, $level);
697
+	}
698 698
 }
Please login to merge, or discard this patch.
lib/Dwoo/Smarty/Processor/Adapter.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -23,23 +23,23 @@
 block discarded – undo
23 23
  */
24 24
 class Adapter extends Processor
25 25
 {
26
-    public $callback;
26
+	public $callback;
27 27
 
28
-    /**
29
-     * @param string $input
30
-     *
31
-     * @return mixed
32
-     */
33
-    public function process($input)
34
-    {
35
-        return call_user_func($this->callback, $input);
36
-    }
28
+	/**
29
+	 * @param string $input
30
+	 *
31
+	 * @return mixed
32
+	 */
33
+	public function process($input)
34
+	{
35
+		return call_user_func($this->callback, $input);
36
+	}
37 37
 
38
-    /**
39
-     * @param $callback
40
-     */
41
-    public function registerCallback($callback)
42
-    {
43
-        $this->callback = $callback;
44
-    }
38
+	/**
39
+	 * @param $callback
40
+	 */
41
+	public function registerCallback($callback)
42
+	{
43
+		$this->callback = $callback;
44
+	}
45 45
 }
46 46
\ No newline at end of file
Please login to merge, or discard this patch.
lib/Dwoo/Compilation/Exception.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -26,35 +26,35 @@
 block discarded – undo
26 26
  */
27 27
 class Exception extends DwooException
28 28
 {
29
-    protected $compiler;
30
-    protected $template;
29
+	protected $compiler;
30
+	protected $template;
31 31
 
32
-    /**
33
-     * Exception constructor.
34
-     *
35
-     * @param DwooCompiler $compiler
36
-     * @param int          $message
37
-     */
38
-    public function __construct(DwooCompiler $compiler, $message)
39
-    {
40
-        $this->compiler = $compiler;
41
-        $this->template = $compiler->getDwoo()->getTemplate();
42
-        parent::__construct('Compilation error at line ' . $compiler->getLine() . ' in "' . $this->template->getResourceName() . ':' . $this->template->getResourceIdentifier() . '" : ' . $message);
43
-    }
32
+	/**
33
+	 * Exception constructor.
34
+	 *
35
+	 * @param DwooCompiler $compiler
36
+	 * @param int          $message
37
+	 */
38
+	public function __construct(DwooCompiler $compiler, $message)
39
+	{
40
+		$this->compiler = $compiler;
41
+		$this->template = $compiler->getDwoo()->getTemplate();
42
+		parent::__construct('Compilation error at line ' . $compiler->getLine() . ' in "' . $this->template->getResourceName() . ':' . $this->template->getResourceIdentifier() . '" : ' . $message);
43
+	}
44 44
 
45
-    /**
46
-     * @return DwooCompiler
47
-     */
48
-    public function getCompiler()
49
-    {
50
-        return $this->compiler;
51
-    }
45
+	/**
46
+	 * @return DwooCompiler
47
+	 */
48
+	public function getCompiler()
49
+	{
50
+		return $this->compiler;
51
+	}
52 52
 
53
-    /**
54
-     * @return \Dwoo\ITemplate|null
55
-     */
56
-    public function getTemplate()
57
-    {
58
-        return $this->template;
59
-    }
53
+	/**
54
+	 * @return \Dwoo\ITemplate|null
55
+	 */
56
+	public function getTemplate()
57
+	{
58
+		return $this->template;
59
+	}
60 60
 }
Please login to merge, or discard this patch.
lib/Dwoo/IPluginProxy.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -23,52 +23,52 @@
 block discarded – undo
23 23
  */
24 24
 interface IPluginProxy
25 25
 {
26
-    /**
27
-     * Returns true or false to say whether the given plugin is handled by this proxy or not.
28
-     *
29
-     * @param string $name the plugin name
30
-     *
31
-     * @return bool true if the plugin is known and usable, otherwise false
32
-     */
33
-    public function handles($name);
26
+	/**
27
+	 * Returns true or false to say whether the given plugin is handled by this proxy or not.
28
+	 *
29
+	 * @param string $name the plugin name
30
+	 *
31
+	 * @return bool true if the plugin is known and usable, otherwise false
32
+	 */
33
+	public function handles($name);
34 34
 
35
-    /**
36
-     * Returns the code (as a string) to call the plugin
37
-     * (this will be executed at runtime inside the Dwoo class).
38
-     *
39
-     * @param string $name   the plugin name
40
-     * @param array  $params a parameter array, array key "*" is the rest array
41
-     *
42
-     * @return string
43
-     */
44
-    public function getCode($name, $params);
35
+	/**
36
+	 * Returns the code (as a string) to call the plugin
37
+	 * (this will be executed at runtime inside the Dwoo class).
38
+	 *
39
+	 * @param string $name   the plugin name
40
+	 * @param array  $params a parameter array, array key "*" is the rest array
41
+	 *
42
+	 * @return string
43
+	 */
44
+	public function getCode($name, $params);
45 45
 
46
-    /**
47
-     * Returns a callback to the plugin, this is used with the reflection API to
48
-     * find out about the plugin's parameter names etc.
49
-     * should you need a rest array without the possibility to edit the
50
-     * plugin's code, you can provide a callback to some
51
-     * other function with the correct parameter signature, i.e. :
52
-     * <code>
53
-     * return array($this, "callbackHelper");
54
-     * // and callbackHelper would be as such:
55
-     * public function callbackHelper(array $rest=array()){}
56
-     * </code>
57
-     *
58
-     * @param string $name the plugin name
59
-     *
60
-     * @return callback
61
-     */
62
-    public function getCallback($name);
46
+	/**
47
+	 * Returns a callback to the plugin, this is used with the reflection API to
48
+	 * find out about the plugin's parameter names etc.
49
+	 * should you need a rest array without the possibility to edit the
50
+	 * plugin's code, you can provide a callback to some
51
+	 * other function with the correct parameter signature, i.e. :
52
+	 * <code>
53
+	 * return array($this, "callbackHelper");
54
+	 * // and callbackHelper would be as such:
55
+	 * public function callbackHelper(array $rest=array()){}
56
+	 * </code>
57
+	 *
58
+	 * @param string $name the plugin name
59
+	 *
60
+	 * @return callback
61
+	 */
62
+	public function getCallback($name);
63 63
 
64
-    /**
65
-     * Returns some code that will check if the plugin is loaded and if not load it
66
-     * this is optional, if your plugins are autoloaded or whatever, just return an
67
-     * empty string.
68
-     *
69
-     * @param string $name the plugin name
70
-     *
71
-     * @return string
72
-     */
73
-    public function getLoader($name);
64
+	/**
65
+	 * Returns some code that will check if the plugin is loaded and if not load it
66
+	 * this is optional, if your plugins are autoloaded or whatever, just return an
67
+	 * empty string.
68
+	 *
69
+	 * @param string $name the plugin name
70
+	 *
71
+	 * @return string
72
+	 */
73
+	public function getLoader($name);
74 74
 }
Please login to merge, or discard this patch.
lib/Dwoo/ITemplate.php 1 patch
Indentation   +120 added lines, -120 removed lines patch added patch discarded remove patch
@@ -23,137 +23,137 @@
 block discarded – undo
23 23
  */
24 24
 interface ITemplate
25 25
 {
26
-    /**
27
-     * Returns the cache duration for this template.
28
-     * defaults to null if it was not provided
29
-     *
30
-     * @return int|null
31
-     */
32
-    public function getCacheTime();
26
+	/**
27
+	 * Returns the cache duration for this template.
28
+	 * defaults to null if it was not provided
29
+	 *
30
+	 * @return int|null
31
+	 */
32
+	public function getCacheTime();
33 33
 
34
-    /**
35
-     * Sets the cache duration for this template.
36
-     * can be used to set it after the object is created if you did not provide
37
-     * it in the constructor
38
-     *
39
-     * @param int $seconds duration of the cache validity for this template, if
40
-     *                     null it defaults to the Dwoo instance's cache time. 0 = disable and
41
-     *                     -1 = infinite cache
42
-     */
43
-    public function setCacheTime($seconds = null);
34
+	/**
35
+	 * Sets the cache duration for this template.
36
+	 * can be used to set it after the object is created if you did not provide
37
+	 * it in the constructor
38
+	 *
39
+	 * @param int $seconds duration of the cache validity for this template, if
40
+	 *                     null it defaults to the Dwoo instance's cache time. 0 = disable and
41
+	 *                     -1 = infinite cache
42
+	 */
43
+	public function setCacheTime($seconds = null);
44 44
 
45
-    /**
46
-     * Returns the cached template output file name, true if it's cache-able but not cached
47
-     * or false if it's not cached.
48
-     *
49
-     * @param Core $dwoo the dwoo instance that requests it
50
-     *
51
-     * @return string|bool
52
-     */
53
-    public function getCachedTemplate(Core $dwoo);
45
+	/**
46
+	 * Returns the cached template output file name, true if it's cache-able but not cached
47
+	 * or false if it's not cached.
48
+	 *
49
+	 * @param Core $dwoo the dwoo instance that requests it
50
+	 *
51
+	 * @return string|bool
52
+	 */
53
+	public function getCachedTemplate(Core $dwoo);
54 54
 
55
-    /**
56
-     * Caches the provided output into the cache file.
57
-     *
58
-     * @param Core   $dwoo   the dwoo instance that requests it
59
-     * @param string $output the template output
60
-     *
61
-     * @return mixed full path of the cached file or false upon failure
62
-     */
63
-    public function cache(Core $dwoo, $output);
55
+	/**
56
+	 * Caches the provided output into the cache file.
57
+	 *
58
+	 * @param Core   $dwoo   the dwoo instance that requests it
59
+	 * @param string $output the template output
60
+	 *
61
+	 * @return mixed full path of the cached file or false upon failure
62
+	 */
63
+	public function cache(Core $dwoo, $output);
64 64
 
65
-    /**
66
-     * Clears the cached template if it's older than the given time.
67
-     *
68
-     * @param Core $dwoo      the dwoo instance that was used to cache that template
69
-     * @param int  $olderThan minimum time (in seconds) required for the cache to be cleared
70
-     *
71
-     * @return bool true if the cache was not present or if it was deleted, false if it remains there
72
-     */
73
-    public function clearCache(Core $dwoo, $olderThan = - 1);
65
+	/**
66
+	 * Clears the cached template if it's older than the given time.
67
+	 *
68
+	 * @param Core $dwoo      the dwoo instance that was used to cache that template
69
+	 * @param int  $olderThan minimum time (in seconds) required for the cache to be cleared
70
+	 *
71
+	 * @return bool true if the cache was not present or if it was deleted, false if it remains there
72
+	 */
73
+	public function clearCache(Core $dwoo, $olderThan = - 1);
74 74
 
75
-    /**
76
-     * Returns the compiled template file name.
77
-     *
78
-     * @param Core      $dwoo     the dwoo instance that requests it
79
-     * @param ICompiler $compiler the compiler that must be used
80
-     *
81
-     * @return string
82
-     */
83
-    public function getCompiledTemplate(Core $dwoo, ICompiler $compiler = null);
75
+	/**
76
+	 * Returns the compiled template file name.
77
+	 *
78
+	 * @param Core      $dwoo     the dwoo instance that requests it
79
+	 * @param ICompiler $compiler the compiler that must be used
80
+	 *
81
+	 * @return string
82
+	 */
83
+	public function getCompiledTemplate(Core $dwoo, ICompiler $compiler = null);
84 84
 
85
-    /**
86
-     * Returns the template name.
87
-     *
88
-     * @return string
89
-     */
90
-    public function getName();
85
+	/**
86
+	 * Returns the template name.
87
+	 *
88
+	 * @return string
89
+	 */
90
+	public function getName();
91 91
 
92
-    /**
93
-     * Returns the resource name for this template class.
94
-     *
95
-     * @return string
96
-     */
97
-    public function getResourceName();
92
+	/**
93
+	 * Returns the resource name for this template class.
94
+	 *
95
+	 * @return string
96
+	 */
97
+	public function getResourceName();
98 98
 
99
-    /**
100
-     * Returns the resource identifier for this template or false if it has no identifier.
101
-     *
102
-     * @return string|false
103
-     */
104
-    public function getResourceIdentifier();
99
+	/**
100
+	 * Returns the resource identifier for this template or false if it has no identifier.
101
+	 *
102
+	 * @return string|false
103
+	 */
104
+	public function getResourceIdentifier();
105 105
 
106
-    /**
107
-     * Returns the template source of this template.
108
-     *
109
-     * @return string
110
-     */
111
-    public function getSource();
106
+	/**
107
+	 * Returns the template source of this template.
108
+	 *
109
+	 * @return string
110
+	 */
111
+	public function getSource();
112 112
 
113
-    /**
114
-     * Returns an unique string identifying the current version of this template,
115
-     * for example a timestamp of the last modified date or a hash of the template source.
116
-     *
117
-     * @return string
118
-     */
119
-    public function getUid();
113
+	/**
114
+	 * Returns an unique string identifying the current version of this template,
115
+	 * for example a timestamp of the last modified date or a hash of the template source.
116
+	 *
117
+	 * @return string
118
+	 */
119
+	public function getUid();
120 120
 
121
-    /**
122
-     * Returns the compiler used by this template, if it was just compiled, or null.
123
-     *
124
-     * @return ICompiler
125
-     */
126
-    public function getCompiler();
121
+	/**
122
+	 * Returns the compiler used by this template, if it was just compiled, or null.
123
+	 *
124
+	 * @return ICompiler
125
+	 */
126
+	public function getCompiler();
127 127
 
128
-    /**
129
-     * Returns some php code that will check if this template has been modified or not.
130
-     * if the function returns null, the template will be instanciated and then the Uid checked
131
-     *
132
-     * @return string
133
-     */
134
-    public function getIsModifiedCode();
128
+	/**
129
+	 * Returns some php code that will check if this template has been modified or not.
130
+	 * if the function returns null, the template will be instanciated and then the Uid checked
131
+	 *
132
+	 * @return string
133
+	 */
134
+	public function getIsModifiedCode();
135 135
 
136
-    /**
137
-     * Returns a new template object from the given resource identifier, null if no include is
138
-     * possible (resource not found), or false if include is not permitted by this resource type.
139
-     * this method should also check if $dwoo->getSecurityPolicy() is null or not and do the
140
-     * necessary permission checks if required, if the security policy prevents the template
141
-     * generation it should throw a new Security\Exception with a relevant message
142
-     *
143
-     * @param mixed     $resourceId     the resource identifier
144
-     * @param int       $cacheTime      duration of the cache validity for this template, if null it defaults to the
145
-     *                                  Dwoo instance that will render this template if null it defaults to the Dwoo
146
-     *                                  instance that will render this template
147
-     * @param string    $cacheId        the unique cache identifier of this page or anything else that makes this
148
-     *                                  template's content unique, if null it defaults to the current url makes this
149
-     *                                  template's content unique, if null it defaults to the current url
150
-     * @param string    $compileId      the unique compiled identifier, which is used to distinguish this template from
151
-     *                                  others, if null it defaults to the filename+bits of the path template from
152
-     *                                  others, if null it defaults to the filename+bits of the path
153
-     * @param ITemplate $parentTemplate the template that is requesting a new template object (through an include,
154
-     *                                  extends or any other plugin) an include, extends or any other plugin)
155
-     *
156
-     * @return ITemplate|null|false
157
-     */
158
-    public static function templateFactory(Core $dwoo, $resourceId, $cacheTime = null, $cacheId = null, $compileId = null, ITemplate $parentTemplate = null);
136
+	/**
137
+	 * Returns a new template object from the given resource identifier, null if no include is
138
+	 * possible (resource not found), or false if include is not permitted by this resource type.
139
+	 * this method should also check if $dwoo->getSecurityPolicy() is null or not and do the
140
+	 * necessary permission checks if required, if the security policy prevents the template
141
+	 * generation it should throw a new Security\Exception with a relevant message
142
+	 *
143
+	 * @param mixed     $resourceId     the resource identifier
144
+	 * @param int       $cacheTime      duration of the cache validity for this template, if null it defaults to the
145
+	 *                                  Dwoo instance that will render this template if null it defaults to the Dwoo
146
+	 *                                  instance that will render this template
147
+	 * @param string    $cacheId        the unique cache identifier of this page or anything else that makes this
148
+	 *                                  template's content unique, if null it defaults to the current url makes this
149
+	 *                                  template's content unique, if null it defaults to the current url
150
+	 * @param string    $compileId      the unique compiled identifier, which is used to distinguish this template from
151
+	 *                                  others, if null it defaults to the filename+bits of the path template from
152
+	 *                                  others, if null it defaults to the filename+bits of the path
153
+	 * @param ITemplate $parentTemplate the template that is requesting a new template object (through an include,
154
+	 *                                  extends or any other plugin) an include, extends or any other plugin)
155
+	 *
156
+	 * @return ITemplate|null|false
157
+	 */
158
+	public static function templateFactory(Core $dwoo, $resourceId, $cacheTime = null, $cacheId = null, $compileId = null, ITemplate $parentTemplate = null);
159 159
 }
Please login to merge, or discard this patch.
lib/Dwoo/Core.php 2 patches
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -549,8 +549,7 @@
 block discarded – undo
549 549
             if (!class_exists($class) && !function_exists($class)) {
550 550
                 try {
551 551
                     $this->getLoader()->loadPlugin($callback);
552
-                }
553
-                catch (Exception $e) {
552
+                } catch (Exception $e) {
554 553
                     if (strstr($callback, self::NAMESPACE_PLUGINS_FILTERS)) {
555 554
                         throw new Exception(
556 555
                             'Wrong filter name : ' . $callback . ', the "Dwoo_Filter_" prefix should 
Please login to merge, or discard this patch.
Indentation   +1738 added lines, -1738 removed lines patch added patch discarded remove patch
@@ -44,1750 +44,1750 @@
 block discarded – undo
44 44
  */
45 45
 class Core
46 46
 {
47
-    /**
48
-     * Current version number.
49
-     *
50
-     * @var string
51
-     */
52
-    const VERSION = '1.3.2';
53
-
54
-    /**
55
-     * Unique number of this dwoo release, based on version number.
56
-     * this can be used by templates classes to check whether the compiled template
57
-     * has been compiled before this release or not, so that old templates are
58
-     * recompiled automatically when Dwoo is updated
59
-     */
60
-    const RELEASE_TAG = 132;
61
-
62
-    /**
63
-     * Constants that represents all plugin types
64
-     * these are bitwise-operation-safe values to allow multiple types
65
-     * on a single plugin
66
-     *
67
-     * @var int
68
-     */
69
-    const CLASS_PLUGIN      = 1;
70
-    const FUNC_PLUGIN       = 2;
71
-    const NATIVE_PLUGIN     = 4;
72
-    const BLOCK_PLUGIN      = 8;
73
-    const COMPILABLE_PLUGIN = 16;
74
-    const CUSTOM_PLUGIN     = 32;
75
-    const SMARTY_MODIFIER   = 64;
76
-    const SMARTY_BLOCK      = 128;
77
-    const SMARTY_FUNCTION   = 256;
78
-    const PROXY_PLUGIN      = 512;
79
-    const TEMPLATE_PLUGIN   = 1024;
80
-
81
-    /**
82
-     * Constant to default namespaces of builtin plugins
83
-     *
84
-     * @var string
85
-     */
86
-    const NAMESPACE_PLUGINS_BLOCKS     = 'Dwoo\Plugins\Blocks\\';
87
-    const NAMESPACE_PLUGINS_FILTERS    = 'Dwoo\Plugins\Filters\\';
88
-    const NAMESPACE_PLUGINS_FUNCTIONS  = 'Dwoo\Plugins\Functions\\';
89
-    const NAMESPACE_PLUGINS_HELPERS    = 'Dwoo\Plugins\Helpers\\';
90
-    const NAMESPACE_PLUGINS_PROCESSORS = 'Dwoo\Plugins\Processors\\';
91
-
92
-    /**
93
-     * Character set of the template, used by string manipulation plugins.
94
-     * it must be lowercase, but setCharset() will take care of that
95
-     *
96
-     * @see setCharset
97
-     * @see getCharset
98
-     * @var string
99
-     */
100
-    protected $charset = 'UTF-8';
101
-
102
-    /**
103
-     * Global variables that are accessible through $dwoo.* in the templates.
104
-     * default values include:
105
-     * $dwoo.version - current version number
106
-     * $dwoo.ad - a Powered by Dwoo link pointing to dwoo.org
107
-     * $dwoo.now - the current time
108
-     * $dwoo.template - the current template filename
109
-     * $dwoo.charset - the character set used by the template
110
-     * on top of that, foreach and other plugins can store special values in there,
111
-     * see their documentation for more details.
112
-     *
113
-     * @var array
114
-     */
115
-    protected $globals = array();
116
-
117
-    /**
118
-     * Directory where the compiled templates are stored.
119
-     * defaults to DWOO_COMPILEDIR (= dwoo_dir/compiled by default)
120
-     *
121
-     * @var string
122
-     */
123
-    protected $compileDir;
124
-
125
-    /**
126
-     * Directory where the cached templates are stored.
127
-     * defaults to DWOO_CACHEDIR (= dwoo_dir/cache by default)
128
-     *
129
-     * @var string
130
-     */
131
-    protected $cacheDir;
132
-
133
-    /**
134
-     * Directory where the template files are stored
135
-     *
136
-     * @var array
137
-     */
138
-    protected $templateDir = array();
139
-
140
-    /**
141
-     * Defines how long (in seconds) the cached files must remain valid.
142
-     * can be overridden on a per-template basis
143
-     * -1 = never delete
144
-     * 0 = disabled
145
-     * >0 = duration in seconds
146
-     *
147
-     * @var int
148
-     */
149
-    protected $cacheTime = 0;
150
-
151
-    /**
152
-     * Security policy object.
153
-     *
154
-     * @var SecurityPolicy
155
-     */
156
-    protected $securityPolicy = null;
157
-
158
-    /**
159
-     * Stores the custom plugins callbacks.
160
-     *
161
-     * @see addPlugin
162
-     * @see removePlugin
163
-     * @var array
164
-     */
165
-    protected $plugins = array();
166
-
167
-    /**
168
-     * Stores the filter callbacks.
169
-     *
170
-     * @see addFilter
171
-     * @see removeFilter
172
-     * @var array
173
-     */
174
-    protected $filters = array();
175
-
176
-    /**
177
-     * Stores the resource types and associated
178
-     * classes / compiler classes.
179
-     *
180
-     * @var array
181
-     */
182
-    protected $resources = array(
183
-        'file'   => array(
184
-            'class'    => 'Dwoo\Template\File',
185
-            'compiler' => null,
186
-        ),
187
-        'string' => array(
188
-            'class'    => 'Dwoo\Template\Str',
189
-            'compiler' => null,
190
-        ),
191
-    );
192
-
193
-    /**
194
-     * The dwoo loader object used to load plugins by this dwoo instance.
195
-     *
196
-     * @var ILoader
197
-     */
198
-    protected $loader = null;
199
-
200
-    /**
201
-     * Currently rendered template, set to null when not-rendering.
202
-     *
203
-     * @var ITemplate
204
-     */
205
-    protected $template = null;
206
-
207
-    /**
208
-     * Stores the instances of the class plugins during template runtime.
209
-     *
210
-     * @var array
211
-     */
212
-    protected $runtimePlugins = array();
213
-
214
-    /**
215
-     * Stores the returned values during template runtime.
216
-     *
217
-     * @var array
218
-     */
219
-    protected $returnData = array();
220
-
221
-    /**
222
-     * Stores the data during template runtime.
223
-     *
224
-     * @var array
225
-     */
226
-    protected $data = array();
227
-
228
-    /**
229
-     * Stores the current scope during template runtime.
230
-     * this should ideally not be accessed directly from outside template code
231
-     *
232
-     * @var mixed
233
-     */
234
-    public $scope;
235
-
236
-    /**
237
-     * Stores the scope tree during template runtime.
238
-     *
239
-     * @var array
240
-     */
241
-    protected $scopeTree = array();
242
-
243
-    /**
244
-     * Stores the block plugins stack during template runtime.
245
-     *
246
-     * @var array
247
-     */
248
-    protected $stack = array();
249
-
250
-    /**
251
-     * Stores the current block plugin at the top of the stack during template runtime.
252
-     *
253
-     * @var BlockPlugin
254
-     */
255
-    protected $curBlock;
256
-
257
-    /**
258
-     * Stores the output buffer during template runtime.
259
-     *
260
-     * @var string
261
-     */
262
-    protected $buffer;
263
-
264
-    /**
265
-     * Stores plugin proxy.
266
-     *
267
-     * @var IPluginProxy
268
-     */
269
-    protected $pluginProxy;
270
-
271
-    /**
272
-     * Constructor, sets the cache and compile dir to the default values if not provided.
273
-     *
274
-     * @param string $compileDir path to the compiled directory, defaults to lib/compiled
275
-     * @param string $cacheDir   path to the cache directory, defaults to lib/cache
276
-     */
277
-    public function __construct($compileDir = null, $cacheDir = null)
278
-    {
279
-        if ($compileDir !== null) {
280
-            $this->setCompileDir($compileDir);
281
-        }
282
-        if ($cacheDir !== null) {
283
-            $this->setCacheDir($cacheDir);
284
-        }
285
-        $this->initGlobals();
286
-    }
287
-
288
-    /**
289
-     * Resets some runtime variables to allow a cloned object to be used to render sub-templates.
290
-     *
291
-     * @return void
292
-     */
293
-    public function __clone()
294
-    {
295
-        $this->template = null;
296
-        unset($this->data);
297
-        unset($this->returnData);
298
-    }
299
-
300
-    /**
301
-     * Returns the given template rendered using the provided data and optional compiler.
302
-     *
303
-     * @param mixed     $_tpl      template, can either be a ITemplate object (i.e. TemplateFile), a
304
-     *                             valid path to a template, or a template as a string it is recommended to
305
-     *                             provide a ITemplate as it will probably make things faster, especially if
306
-     *                             you render a template multiple times
307
-     * @param mixed     $data      the data to use, can either be a IDataProvider object (i.e. Data) or
308
-     *                             an associative array. if you're rendering the template from cache, it can be
309
-     *                             left null
310
-     * @param ICompiler $_compiler the compiler that must be used to compile the template, if left empty a default
311
-     *                             Compiler will be used
312
-     *
313
-     * @return string|void or the template output if $output is false
314
-     * @throws Exception
315
-     */
316
-    public function get($_tpl, $data = array(), $_compiler = null)
317
-    {
318
-        // a render call came from within a template, so we need a new dwoo instance in order to avoid breaking this one
319
-        if ($this->template instanceof ITemplate) {
320
-            $clone = clone $this;
321
-
322
-            return $clone->get($_tpl, $data, $_compiler);
323
-        }
324
-
325
-        // auto-create template if required
326
-        if ($_tpl instanceof ITemplate) {
327
-            // valid, skip
328
-        } elseif (is_string($_tpl)) {
329
-            $_tpl = new TemplateFile($_tpl);
330
-            $_tpl->setIncludePath($this->getTemplateDir());
331
-        } else {
332
-            throw new Exception(
333
-                'Dwoo->get\'s first argument must be a ITemplate (i.e. TemplateFile) or 
47
+	/**
48
+	 * Current version number.
49
+	 *
50
+	 * @var string
51
+	 */
52
+	const VERSION = '1.3.2';
53
+
54
+	/**
55
+	 * Unique number of this dwoo release, based on version number.
56
+	 * this can be used by templates classes to check whether the compiled template
57
+	 * has been compiled before this release or not, so that old templates are
58
+	 * recompiled automatically when Dwoo is updated
59
+	 */
60
+	const RELEASE_TAG = 132;
61
+
62
+	/**
63
+	 * Constants that represents all plugin types
64
+	 * these are bitwise-operation-safe values to allow multiple types
65
+	 * on a single plugin
66
+	 *
67
+	 * @var int
68
+	 */
69
+	const CLASS_PLUGIN      = 1;
70
+	const FUNC_PLUGIN       = 2;
71
+	const NATIVE_PLUGIN     = 4;
72
+	const BLOCK_PLUGIN      = 8;
73
+	const COMPILABLE_PLUGIN = 16;
74
+	const CUSTOM_PLUGIN     = 32;
75
+	const SMARTY_MODIFIER   = 64;
76
+	const SMARTY_BLOCK      = 128;
77
+	const SMARTY_FUNCTION   = 256;
78
+	const PROXY_PLUGIN      = 512;
79
+	const TEMPLATE_PLUGIN   = 1024;
80
+
81
+	/**
82
+	 * Constant to default namespaces of builtin plugins
83
+	 *
84
+	 * @var string
85
+	 */
86
+	const NAMESPACE_PLUGINS_BLOCKS     = 'Dwoo\Plugins\Blocks\\';
87
+	const NAMESPACE_PLUGINS_FILTERS    = 'Dwoo\Plugins\Filters\\';
88
+	const NAMESPACE_PLUGINS_FUNCTIONS  = 'Dwoo\Plugins\Functions\\';
89
+	const NAMESPACE_PLUGINS_HELPERS    = 'Dwoo\Plugins\Helpers\\';
90
+	const NAMESPACE_PLUGINS_PROCESSORS = 'Dwoo\Plugins\Processors\\';
91
+
92
+	/**
93
+	 * Character set of the template, used by string manipulation plugins.
94
+	 * it must be lowercase, but setCharset() will take care of that
95
+	 *
96
+	 * @see setCharset
97
+	 * @see getCharset
98
+	 * @var string
99
+	 */
100
+	protected $charset = 'UTF-8';
101
+
102
+	/**
103
+	 * Global variables that are accessible through $dwoo.* in the templates.
104
+	 * default values include:
105
+	 * $dwoo.version - current version number
106
+	 * $dwoo.ad - a Powered by Dwoo link pointing to dwoo.org
107
+	 * $dwoo.now - the current time
108
+	 * $dwoo.template - the current template filename
109
+	 * $dwoo.charset - the character set used by the template
110
+	 * on top of that, foreach and other plugins can store special values in there,
111
+	 * see their documentation for more details.
112
+	 *
113
+	 * @var array
114
+	 */
115
+	protected $globals = array();
116
+
117
+	/**
118
+	 * Directory where the compiled templates are stored.
119
+	 * defaults to DWOO_COMPILEDIR (= dwoo_dir/compiled by default)
120
+	 *
121
+	 * @var string
122
+	 */
123
+	protected $compileDir;
124
+
125
+	/**
126
+	 * Directory where the cached templates are stored.
127
+	 * defaults to DWOO_CACHEDIR (= dwoo_dir/cache by default)
128
+	 *
129
+	 * @var string
130
+	 */
131
+	protected $cacheDir;
132
+
133
+	/**
134
+	 * Directory where the template files are stored
135
+	 *
136
+	 * @var array
137
+	 */
138
+	protected $templateDir = array();
139
+
140
+	/**
141
+	 * Defines how long (in seconds) the cached files must remain valid.
142
+	 * can be overridden on a per-template basis
143
+	 * -1 = never delete
144
+	 * 0 = disabled
145
+	 * >0 = duration in seconds
146
+	 *
147
+	 * @var int
148
+	 */
149
+	protected $cacheTime = 0;
150
+
151
+	/**
152
+	 * Security policy object.
153
+	 *
154
+	 * @var SecurityPolicy
155
+	 */
156
+	protected $securityPolicy = null;
157
+
158
+	/**
159
+	 * Stores the custom plugins callbacks.
160
+	 *
161
+	 * @see addPlugin
162
+	 * @see removePlugin
163
+	 * @var array
164
+	 */
165
+	protected $plugins = array();
166
+
167
+	/**
168
+	 * Stores the filter callbacks.
169
+	 *
170
+	 * @see addFilter
171
+	 * @see removeFilter
172
+	 * @var array
173
+	 */
174
+	protected $filters = array();
175
+
176
+	/**
177
+	 * Stores the resource types and associated
178
+	 * classes / compiler classes.
179
+	 *
180
+	 * @var array
181
+	 */
182
+	protected $resources = array(
183
+		'file'   => array(
184
+			'class'    => 'Dwoo\Template\File',
185
+			'compiler' => null,
186
+		),
187
+		'string' => array(
188
+			'class'    => 'Dwoo\Template\Str',
189
+			'compiler' => null,
190
+		),
191
+	);
192
+
193
+	/**
194
+	 * The dwoo loader object used to load plugins by this dwoo instance.
195
+	 *
196
+	 * @var ILoader
197
+	 */
198
+	protected $loader = null;
199
+
200
+	/**
201
+	 * Currently rendered template, set to null when not-rendering.
202
+	 *
203
+	 * @var ITemplate
204
+	 */
205
+	protected $template = null;
206
+
207
+	/**
208
+	 * Stores the instances of the class plugins during template runtime.
209
+	 *
210
+	 * @var array
211
+	 */
212
+	protected $runtimePlugins = array();
213
+
214
+	/**
215
+	 * Stores the returned values during template runtime.
216
+	 *
217
+	 * @var array
218
+	 */
219
+	protected $returnData = array();
220
+
221
+	/**
222
+	 * Stores the data during template runtime.
223
+	 *
224
+	 * @var array
225
+	 */
226
+	protected $data = array();
227
+
228
+	/**
229
+	 * Stores the current scope during template runtime.
230
+	 * this should ideally not be accessed directly from outside template code
231
+	 *
232
+	 * @var mixed
233
+	 */
234
+	public $scope;
235
+
236
+	/**
237
+	 * Stores the scope tree during template runtime.
238
+	 *
239
+	 * @var array
240
+	 */
241
+	protected $scopeTree = array();
242
+
243
+	/**
244
+	 * Stores the block plugins stack during template runtime.
245
+	 *
246
+	 * @var array
247
+	 */
248
+	protected $stack = array();
249
+
250
+	/**
251
+	 * Stores the current block plugin at the top of the stack during template runtime.
252
+	 *
253
+	 * @var BlockPlugin
254
+	 */
255
+	protected $curBlock;
256
+
257
+	/**
258
+	 * Stores the output buffer during template runtime.
259
+	 *
260
+	 * @var string
261
+	 */
262
+	protected $buffer;
263
+
264
+	/**
265
+	 * Stores plugin proxy.
266
+	 *
267
+	 * @var IPluginProxy
268
+	 */
269
+	protected $pluginProxy;
270
+
271
+	/**
272
+	 * Constructor, sets the cache and compile dir to the default values if not provided.
273
+	 *
274
+	 * @param string $compileDir path to the compiled directory, defaults to lib/compiled
275
+	 * @param string $cacheDir   path to the cache directory, defaults to lib/cache
276
+	 */
277
+	public function __construct($compileDir = null, $cacheDir = null)
278
+	{
279
+		if ($compileDir !== null) {
280
+			$this->setCompileDir($compileDir);
281
+		}
282
+		if ($cacheDir !== null) {
283
+			$this->setCacheDir($cacheDir);
284
+		}
285
+		$this->initGlobals();
286
+	}
287
+
288
+	/**
289
+	 * Resets some runtime variables to allow a cloned object to be used to render sub-templates.
290
+	 *
291
+	 * @return void
292
+	 */
293
+	public function __clone()
294
+	{
295
+		$this->template = null;
296
+		unset($this->data);
297
+		unset($this->returnData);
298
+	}
299
+
300
+	/**
301
+	 * Returns the given template rendered using the provided data and optional compiler.
302
+	 *
303
+	 * @param mixed     $_tpl      template, can either be a ITemplate object (i.e. TemplateFile), a
304
+	 *                             valid path to a template, or a template as a string it is recommended to
305
+	 *                             provide a ITemplate as it will probably make things faster, especially if
306
+	 *                             you render a template multiple times
307
+	 * @param mixed     $data      the data to use, can either be a IDataProvider object (i.e. Data) or
308
+	 *                             an associative array. if you're rendering the template from cache, it can be
309
+	 *                             left null
310
+	 * @param ICompiler $_compiler the compiler that must be used to compile the template, if left empty a default
311
+	 *                             Compiler will be used
312
+	 *
313
+	 * @return string|void or the template output if $output is false
314
+	 * @throws Exception
315
+	 */
316
+	public function get($_tpl, $data = array(), $_compiler = null)
317
+	{
318
+		// a render call came from within a template, so we need a new dwoo instance in order to avoid breaking this one
319
+		if ($this->template instanceof ITemplate) {
320
+			$clone = clone $this;
321
+
322
+			return $clone->get($_tpl, $data, $_compiler);
323
+		}
324
+
325
+		// auto-create template if required
326
+		if ($_tpl instanceof ITemplate) {
327
+			// valid, skip
328
+		} elseif (is_string($_tpl)) {
329
+			$_tpl = new TemplateFile($_tpl);
330
+			$_tpl->setIncludePath($this->getTemplateDir());
331
+		} else {
332
+			throw new Exception(
333
+				'Dwoo->get\'s first argument must be a ITemplate (i.e. TemplateFile) or 
334 334
             a valid path to a template file', E_USER_NOTICE
335
-            );
336
-        }
337
-
338
-        // save the current template, enters render mode at the same time
339
-        // if another rendering is requested it will be proxied to a new Core(instance
340
-        $this->template = $_tpl;
341
-
342
-        // load data
343
-        if ($data instanceof IDataProvider) {
344
-            $this->data = $data->getData();
345
-        } elseif (is_array($data)) {
346
-            $this->data = $data;
347
-        } elseif ($data instanceof ArrayAccess) {
348
-            $this->data = $data;
349
-        } else {
350
-            throw new Exception(
351
-                'Dwoo->get/Dwoo->output\'s data argument must be a IDataProvider object (i.e. Data) or
335
+			);
336
+		}
337
+
338
+		// save the current template, enters render mode at the same time
339
+		// if another rendering is requested it will be proxied to a new Core(instance
340
+		$this->template = $_tpl;
341
+
342
+		// load data
343
+		if ($data instanceof IDataProvider) {
344
+			$this->data = $data->getData();
345
+		} elseif (is_array($data)) {
346
+			$this->data = $data;
347
+		} elseif ($data instanceof ArrayAccess) {
348
+			$this->data = $data;
349
+		} else {
350
+			throw new Exception(
351
+				'Dwoo->get/Dwoo->output\'s data argument must be a IDataProvider object (i.e. Data) or
352 352
             an associative array', E_USER_NOTICE
353
-            );
354
-        }
355
-
356
-        $this->addGlobal('template', $_tpl->getName());
357
-        $this->initRuntimeVars($_tpl);
358
-
359
-        // try to get cached template
360
-        $file        = $_tpl->getCachedTemplate($this);
361
-        $doCache     = $file === true;
362
-        $cacheLoaded = is_string($file);
363
-
364
-        if ($cacheLoaded === true) {
365
-            // cache is present, run it
366
-            ob_start();
367
-            include $file;
368
-            $this->template = null;
369
-
370
-            return ob_get_clean();
371
-        } else {
372
-            $dynamicId = uniqid();
373
-
374
-            // render template
375
-            $compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
376
-            $out              = include $compiledTemplate;
377
-
378
-            // template returned false so it needs to be recompiled
379
-            if ($out === false) {
380
-                $_tpl->forceCompilation();
381
-                $compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
382
-                $out              = include $compiledTemplate;
383
-            }
384
-
385
-            if ($doCache === true) {
386
-                $out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*' . $dynamicId . '*/ echo \'$1\'; ?>', $out);
387
-                if (!class_exists(self::NAMESPACE_PLUGINS_BLOCKS . 'PluginDynamic')) {
388
-                    $this->getLoader()->loadPlugin('PluginDynamic');
389
-                }
390
-                $out = PluginDynamic::unescape($out, $dynamicId, $compiledTemplate);
391
-            }
392
-
393
-            // process filters
394
-            foreach ($this->filters as $filter) {
395
-                if (is_array($filter) && $filter[0] instanceof Filter) {
396
-                    $out = call_user_func($filter, $out);
397
-                } else {
398
-                    $out = call_user_func($filter, $this, $out);
399
-                }
400
-            }
401
-
402
-            if ($doCache === true) {
403
-                // building cache
404
-                $file = $_tpl->cache($this, $out);
405
-
406
-                // run it from the cache to be sure dynamics are rendered
407
-                ob_start();
408
-                include $file;
409
-                // exit render mode
410
-                $this->template = null;
411
-
412
-                return ob_get_clean();
413
-            } else {
414
-                // no need to build cache
415
-                // exit render mode
416
-                $this->template = null;
417
-
418
-                return $out;
419
-            }
420
-        }
421
-    }
422
-
423
-    /**
424
-     * Registers a Global.
425
-     * New globals can be added before compiling or rendering a template
426
-     * but after, you can only update existing globals.
427
-     *
428
-     * @param string $name
429
-     * @param mixed  $value
430
-     *
431
-     * @return $this
432
-     * @throws Exception
433
-     */
434
-    public function addGlobal($name, $value)
435
-    {
436
-        if (null === $this->globals) {
437
-            $this->initGlobals();
438
-        }
439
-
440
-        $this->globals[$name] = $value;
441
-
442
-        return $this;
443
-    }
444
-
445
-    /**
446
-     * Gets the registered Globals.
447
-     *
448
-     * @return array
449
-     */
450
-    public function getGlobals()
451
-    {
452
-        return $this->globals;
453
-    }
454
-
455
-    /**
456
-     * Re-initializes the globals array before each template run.
457
-     * this method is only callede once when the Dwoo object is created
458
-     *
459
-     * @return void
460
-     */
461
-    protected function initGlobals()
462
-    {
463
-        $this->globals = array(
464
-            'version' => self::VERSION,
465
-            'ad'      => '<a href="http://dwoo.org/">Powered by Dwoo</a>',
466
-            'now'     => $_SERVER['REQUEST_TIME'],
467
-            'charset' => $this->getCharset(),
468
-        );
469
-    }
470
-
471
-    /**
472
-     * Re-initializes the runtime variables before each template run.
473
-     * override this method to inject data in the globals array if needed, this
474
-     * method is called before each template execution
475
-     *
476
-     * @param ITemplate $tpl the template that is going to be rendered
477
-     *
478
-     * @return void
479
-     */
480
-    protected function initRuntimeVars(ITemplate $tpl)
481
-    {
482
-        $this->runtimePlugins = array();
483
-        $this->scope          = &$this->data;
484
-        $this->scopeTree      = array();
485
-        $this->stack          = array();
486
-        $this->curBlock       = null;
487
-        $this->buffer         = '';
488
-        $this->returnData     = array();
489
-    }
490
-
491
-    /**
492
-     * Adds a custom plugin that is not in one of the plugin directories.
493
-     *
494
-     * @param string   $name       the plugin name to be used in the templates
495
-     * @param callback $callback   the plugin callback, either a function name,
496
-     *                             a class name or an array containing an object
497
-     *                             or class name and a method name
498
-     * @param bool     $compilable if set to true, the plugin is assumed to be compilable
499
-     *
500
-     * @return void
501
-     * @throws Exception
502
-     */
503
-    public function addPlugin($name, $callback, $compilable = false)
504
-    {
505
-        $compilable = $compilable ? self::COMPILABLE_PLUGIN : 0;
506
-        if (is_array($callback)) {
507
-            if (is_subclass_of(is_object($callback[0]) ? get_class($callback[0]) : $callback[0], 'Dwoo\Block\Plugin')) {
508
-                $this->plugins[$name] = array(
509
-                    'type'     => self::BLOCK_PLUGIN | $compilable,
510
-                    'callback' => $callback,
511
-                    'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0])
512
-                );
513
-            } else {
514
-                $this->plugins[$name] = array(
515
-                    'type'     => self::CLASS_PLUGIN | $compilable,
516
-                    'callback' => $callback,
517
-                    'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]),
518
-                    'function' => $callback[1]
519
-                );
520
-            }
521
-        } elseif (is_string($callback)) {
522
-            if (class_exists($callback)) {
523
-                if (is_subclass_of($callback, 'Dwoo\Block\Plugin')) {
524
-                    $this->plugins[$name] = array(
525
-                        'type'     => self::BLOCK_PLUGIN | $compilable,
526
-                        'callback' => $callback,
527
-                        'class'    => $callback
528
-                    );
529
-                } else {
530
-                    $this->plugins[$name] = array(
531
-                        'type'     => self::CLASS_PLUGIN | $compilable,
532
-                        'callback' => $callback,
533
-                        'class'    => $callback,
534
-                        'function' => ($compilable ? 'compile' : 'process')
535
-                    );
536
-                }
537
-            } elseif (function_exists($callback)) {
538
-                $this->plugins[$name] = array(
539
-                    'type'     => self::FUNC_PLUGIN | $compilable,
540
-                    'callback' => $callback
541
-                );
542
-            } else {
543
-                throw new Exception(
544
-                    'Callback could not be processed correctly, please check that the function/class 
353
+			);
354
+		}
355
+
356
+		$this->addGlobal('template', $_tpl->getName());
357
+		$this->initRuntimeVars($_tpl);
358
+
359
+		// try to get cached template
360
+		$file        = $_tpl->getCachedTemplate($this);
361
+		$doCache     = $file === true;
362
+		$cacheLoaded = is_string($file);
363
+
364
+		if ($cacheLoaded === true) {
365
+			// cache is present, run it
366
+			ob_start();
367
+			include $file;
368
+			$this->template = null;
369
+
370
+			return ob_get_clean();
371
+		} else {
372
+			$dynamicId = uniqid();
373
+
374
+			// render template
375
+			$compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
376
+			$out              = include $compiledTemplate;
377
+
378
+			// template returned false so it needs to be recompiled
379
+			if ($out === false) {
380
+				$_tpl->forceCompilation();
381
+				$compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
382
+				$out              = include $compiledTemplate;
383
+			}
384
+
385
+			if ($doCache === true) {
386
+				$out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*' . $dynamicId . '*/ echo \'$1\'; ?>', $out);
387
+				if (!class_exists(self::NAMESPACE_PLUGINS_BLOCKS . 'PluginDynamic')) {
388
+					$this->getLoader()->loadPlugin('PluginDynamic');
389
+				}
390
+				$out = PluginDynamic::unescape($out, $dynamicId, $compiledTemplate);
391
+			}
392
+
393
+			// process filters
394
+			foreach ($this->filters as $filter) {
395
+				if (is_array($filter) && $filter[0] instanceof Filter) {
396
+					$out = call_user_func($filter, $out);
397
+				} else {
398
+					$out = call_user_func($filter, $this, $out);
399
+				}
400
+			}
401
+
402
+			if ($doCache === true) {
403
+				// building cache
404
+				$file = $_tpl->cache($this, $out);
405
+
406
+				// run it from the cache to be sure dynamics are rendered
407
+				ob_start();
408
+				include $file;
409
+				// exit render mode
410
+				$this->template = null;
411
+
412
+				return ob_get_clean();
413
+			} else {
414
+				// no need to build cache
415
+				// exit render mode
416
+				$this->template = null;
417
+
418
+				return $out;
419
+			}
420
+		}
421
+	}
422
+
423
+	/**
424
+	 * Registers a Global.
425
+	 * New globals can be added before compiling or rendering a template
426
+	 * but after, you can only update existing globals.
427
+	 *
428
+	 * @param string $name
429
+	 * @param mixed  $value
430
+	 *
431
+	 * @return $this
432
+	 * @throws Exception
433
+	 */
434
+	public function addGlobal($name, $value)
435
+	{
436
+		if (null === $this->globals) {
437
+			$this->initGlobals();
438
+		}
439
+
440
+		$this->globals[$name] = $value;
441
+
442
+		return $this;
443
+	}
444
+
445
+	/**
446
+	 * Gets the registered Globals.
447
+	 *
448
+	 * @return array
449
+	 */
450
+	public function getGlobals()
451
+	{
452
+		return $this->globals;
453
+	}
454
+
455
+	/**
456
+	 * Re-initializes the globals array before each template run.
457
+	 * this method is only callede once when the Dwoo object is created
458
+	 *
459
+	 * @return void
460
+	 */
461
+	protected function initGlobals()
462
+	{
463
+		$this->globals = array(
464
+			'version' => self::VERSION,
465
+			'ad'      => '<a href="http://dwoo.org/">Powered by Dwoo</a>',
466
+			'now'     => $_SERVER['REQUEST_TIME'],
467
+			'charset' => $this->getCharset(),
468
+		);
469
+	}
470
+
471
+	/**
472
+	 * Re-initializes the runtime variables before each template run.
473
+	 * override this method to inject data in the globals array if needed, this
474
+	 * method is called before each template execution
475
+	 *
476
+	 * @param ITemplate $tpl the template that is going to be rendered
477
+	 *
478
+	 * @return void
479
+	 */
480
+	protected function initRuntimeVars(ITemplate $tpl)
481
+	{
482
+		$this->runtimePlugins = array();
483
+		$this->scope          = &$this->data;
484
+		$this->scopeTree      = array();
485
+		$this->stack          = array();
486
+		$this->curBlock       = null;
487
+		$this->buffer         = '';
488
+		$this->returnData     = array();
489
+	}
490
+
491
+	/**
492
+	 * Adds a custom plugin that is not in one of the plugin directories.
493
+	 *
494
+	 * @param string   $name       the plugin name to be used in the templates
495
+	 * @param callback $callback   the plugin callback, either a function name,
496
+	 *                             a class name or an array containing an object
497
+	 *                             or class name and a method name
498
+	 * @param bool     $compilable if set to true, the plugin is assumed to be compilable
499
+	 *
500
+	 * @return void
501
+	 * @throws Exception
502
+	 */
503
+	public function addPlugin($name, $callback, $compilable = false)
504
+	{
505
+		$compilable = $compilable ? self::COMPILABLE_PLUGIN : 0;
506
+		if (is_array($callback)) {
507
+			if (is_subclass_of(is_object($callback[0]) ? get_class($callback[0]) : $callback[0], 'Dwoo\Block\Plugin')) {
508
+				$this->plugins[$name] = array(
509
+					'type'     => self::BLOCK_PLUGIN | $compilable,
510
+					'callback' => $callback,
511
+					'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0])
512
+				);
513
+			} else {
514
+				$this->plugins[$name] = array(
515
+					'type'     => self::CLASS_PLUGIN | $compilable,
516
+					'callback' => $callback,
517
+					'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]),
518
+					'function' => $callback[1]
519
+				);
520
+			}
521
+		} elseif (is_string($callback)) {
522
+			if (class_exists($callback)) {
523
+				if (is_subclass_of($callback, 'Dwoo\Block\Plugin')) {
524
+					$this->plugins[$name] = array(
525
+						'type'     => self::BLOCK_PLUGIN | $compilable,
526
+						'callback' => $callback,
527
+						'class'    => $callback
528
+					);
529
+				} else {
530
+					$this->plugins[$name] = array(
531
+						'type'     => self::CLASS_PLUGIN | $compilable,
532
+						'callback' => $callback,
533
+						'class'    => $callback,
534
+						'function' => ($compilable ? 'compile' : 'process')
535
+					);
536
+				}
537
+			} elseif (function_exists($callback)) {
538
+				$this->plugins[$name] = array(
539
+					'type'     => self::FUNC_PLUGIN | $compilable,
540
+					'callback' => $callback
541
+				);
542
+			} else {
543
+				throw new Exception(
544
+					'Callback could not be processed correctly, please check that the function/class 
545 545
                 you used exists'
546
-                );
547
-            }
548
-        } elseif ($callback instanceof Closure) {
549
-            $this->plugins[$name] = array(
550
-                'type'     => self::FUNC_PLUGIN | $compilable,
551
-                'callback' => $callback
552
-            );
553
-        } else {
554
-            throw new Exception(
555
-                'Callback could not be processed correctly, please check that the function/class you 
546
+				);
547
+			}
548
+		} elseif ($callback instanceof Closure) {
549
+			$this->plugins[$name] = array(
550
+				'type'     => self::FUNC_PLUGIN | $compilable,
551
+				'callback' => $callback
552
+			);
553
+		} else {
554
+			throw new Exception(
555
+				'Callback could not be processed correctly, please check that the function/class you 
556 556
             used exists'
557
-            );
558
-        }
559
-    }
560
-
561
-    /**
562
-     * Removes a custom plugin.
563
-     *
564
-     * @param string $name the plugin name
565
-     *
566
-     * @return void
567
-     */
568
-    public function removePlugin($name)
569
-    {
570
-        if (isset($this->plugins[$name])) {
571
-            unset($this->plugins[$name]);
572
-        }
573
-    }
574
-
575
-    /**
576
-     * Adds a filter to this Dwoo instance, it will be used to filter the output of all the templates rendered by this
577
-     * instance.
578
-     *
579
-     * @param mixed $callback a callback or a filter name if it is autoloaded from a plugin directory
580
-     * @param bool  $autoload if true, the first parameter must be a filter name from one of the plugin directories
581
-     *
582
-     * @return void
583
-     * @throws Exception
584
-     */
585
-    public function addFilter($callback, $autoload = false)
586
-    {
587
-        if ($autoload) {
588
-            $class = self::NAMESPACE_PLUGINS_FILTERS . self::toCamelCase($callback);
589
-            if (!class_exists($class) && !function_exists($class)) {
590
-                try {
591
-                    $this->getLoader()->loadPlugin($callback);
592
-                }
593
-                catch (Exception $e) {
594
-                    if (strstr($callback, self::NAMESPACE_PLUGINS_FILTERS)) {
595
-                        throw new Exception(
596
-                            'Wrong filter name : ' . $callback . ', the "Dwoo_Filter_" prefix should 
557
+			);
558
+		}
559
+	}
560
+
561
+	/**
562
+	 * Removes a custom plugin.
563
+	 *
564
+	 * @param string $name the plugin name
565
+	 *
566
+	 * @return void
567
+	 */
568
+	public function removePlugin($name)
569
+	{
570
+		if (isset($this->plugins[$name])) {
571
+			unset($this->plugins[$name]);
572
+		}
573
+	}
574
+
575
+	/**
576
+	 * Adds a filter to this Dwoo instance, it will be used to filter the output of all the templates rendered by this
577
+	 * instance.
578
+	 *
579
+	 * @param mixed $callback a callback or a filter name if it is autoloaded from a plugin directory
580
+	 * @param bool  $autoload if true, the first parameter must be a filter name from one of the plugin directories
581
+	 *
582
+	 * @return void
583
+	 * @throws Exception
584
+	 */
585
+	public function addFilter($callback, $autoload = false)
586
+	{
587
+		if ($autoload) {
588
+			$class = self::NAMESPACE_PLUGINS_FILTERS . self::toCamelCase($callback);
589
+			if (!class_exists($class) && !function_exists($class)) {
590
+				try {
591
+					$this->getLoader()->loadPlugin($callback);
592
+				}
593
+				catch (Exception $e) {
594
+					if (strstr($callback, self::NAMESPACE_PLUGINS_FILTERS)) {
595
+						throw new Exception(
596
+							'Wrong filter name : ' . $callback . ', the "Dwoo_Filter_" prefix should 
597 597
                         not be used, please only use "' . str_replace('Dwoo_Filter_', '', $callback) . '"'
598
-                        );
599
-                    } else {
600
-                        throw new Exception(
601
-                            'Wrong filter name : ' . $callback . ', when using autoload the filter must
598
+						);
599
+					} else {
600
+						throw new Exception(
601
+							'Wrong filter name : ' . $callback . ', when using autoload the filter must
602 602
                          be in one of your plugin dir as "name.php" containig a class or function named
603 603
                          "Dwoo_Filter_name"'
604
-                        );
605
-                    }
606
-                }
607
-            }
608
-
609
-            if (class_exists($class)) {
610
-                $callback = array(new $class($this), 'process');
611
-            } elseif (function_exists($class)) {
612
-                $callback = $class;
613
-            } else {
614
-                throw new Exception(
615
-                    'Wrong filter name : ' . $callback . ', when using autoload the filter must be in
604
+						);
605
+					}
606
+				}
607
+			}
608
+
609
+			if (class_exists($class)) {
610
+				$callback = array(new $class($this), 'process');
611
+			} elseif (function_exists($class)) {
612
+				$callback = $class;
613
+			} else {
614
+				throw new Exception(
615
+					'Wrong filter name : ' . $callback . ', when using autoload the filter must be in
616 616
                 one of your plugin dir as "name.php" containig a class or function named "Dwoo_Filter_name"'
617
-                );
618
-            }
619
-
620
-            $this->filters[] = $callback;
621
-        } else {
622
-            $this->filters[] = $callback;
623
-        }
624
-    }
625
-
626
-    /**
627
-     * Removes a filter.
628
-     *
629
-     * @param mixed $callback callback or filter name if it was autoloaded
630
-     *
631
-     * @return void
632
-     */
633
-    public function removeFilter($callback)
634
-    {
635
-        if (($index = array_search(self::NAMESPACE_PLUGINS_FILTERS. 'Filter' . self::toCamelCase($callback), $this->filters,
636
-                true)) !==
637
-            false) {
638
-            unset($this->filters[$index]);
639
-        } elseif (($index = array_search($callback, $this->filters, true)) !== false) {
640
-            unset($this->filters[$index]);
641
-        } else {
642
-            $class = self::NAMESPACE_PLUGINS_FILTERS . 'Filter' . $callback;
643
-            foreach ($this->filters as $index => $filter) {
644
-                if (is_array($filter) && $filter[0] instanceof $class) {
645
-                    unset($this->filters[$index]);
646
-                    break;
647
-                }
648
-            }
649
-        }
650
-    }
651
-
652
-    /**
653
-     * Adds a resource or overrides a default one.
654
-     *
655
-     * @param string   $name            the resource name
656
-     * @param string   $class           the resource class (which must implement ITemplate)
657
-     * @param callback $compilerFactory the compiler factory callback, a function that must return a compiler instance
658
-     *                                  used to compile this resource, if none is provided. by default it will produce
659
-     *                                  a Compiler object
660
-     *
661
-     * @return void
662
-     * @throws Exception
663
-     */
664
-    public function addResource($name, $class, $compilerFactory = null)
665
-    {
666
-        if (strlen($name) < 2) {
667
-            throw new Exception('Resource names must be at least two-character long to avoid conflicts with Windows paths');
668
-        }
669
-
670
-        if (!class_exists($class)) {
671
-            throw new Exception(sprintf('Resource class %s does not exist', $class));
672
-        }
673
-
674
-        $interfaces = class_implements($class);
675
-        if (in_array('Dwoo\ITemplate', $interfaces) === false) {
676
-            throw new Exception('Resource class must implement ITemplate');
677
-        }
678
-
679
-        $this->resources[$name] = array(
680
-            'class'    => $class,
681
-            'compiler' => $compilerFactory
682
-        );
683
-    }
684
-
685
-    /**
686
-     * Removes a custom resource.
687
-     *
688
-     * @param string $name the resource name
689
-     *
690
-     * @return void
691
-     */
692
-    public function removeResource($name)
693
-    {
694
-        unset($this->resources[$name]);
695
-        if ($name === 'file') {
696
-            $this->resources['file'] = array(
697
-                'class'    => 'Dwoo\Template\File',
698
-                'compiler' => null
699
-            );
700
-        }
701
-    }
702
-
703
-    /**
704
-     * Sets the loader object to use to load plugins.
705
-     *
706
-     * @param ILoader $loader loader
707
-     *
708
-     * @return void
709
-     */
710
-    public function setLoader(ILoader $loader)
711
-    {
712
-        $this->loader = $loader;
713
-    }
714
-
715
-    /**
716
-     * Returns the current loader object or a default one if none is currently found.
717
-     *
718
-     * @return ILoader|Loader
719
-     */
720
-    public function getLoader()
721
-    {
722
-        if ($this->loader === null) {
723
-            $this->loader = new Loader($this->getCompileDir());
724
-        }
725
-
726
-        return $this->loader;
727
-    }
728
-
729
-    /**
730
-     * Returns the custom plugins loaded.
731
-     * Used by the ITemplate classes to pass the custom plugins to their ICompiler instance.
732
-     *
733
-     * @return array
734
-     */
735
-    public function getCustomPlugins()
736
-    {
737
-        return $this->plugins;
738
-    }
739
-
740
-    /**
741
-     * Return a specified custom plugin loaded by his name.
742
-     * Used by the compiler, for executing a Closure.
743
-     *
744
-     * @param string $name
745
-     *
746
-     * @return mixed|null
747
-     */
748
-    public function getCustomPlugin($name)
749
-    {
750
-        if (isset($this->plugins[$name])) {
751
-            return $this->plugins[$name]['callback'];
752
-        }
753
-
754
-        return null;
755
-    }
756
-
757
-    /**
758
-     * Returns the cache directory with a trailing DIRECTORY_SEPARATOR.
759
-     *
760
-     * @return string
761
-     */
762
-    public function getCacheDir()
763
-    {
764
-        if ($this->cacheDir === null) {
765
-            $this->setCacheDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR);
766
-        }
767
-
768
-        return $this->cacheDir;
769
-    }
770
-
771
-    /**
772
-     * Sets the cache directory and automatically appends a DIRECTORY_SEPARATOR.
773
-     *
774
-     * @param string $dir the cache directory
775
-     *
776
-     * @return void
777
-     * @throws Exception
778
-     */
779
-    public function setCacheDir($dir)
780
-    {
781
-        $this->cacheDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
782
-        if (is_writable($this->cacheDir) === false) {
783
-            throw new Exception('The cache directory must be writable, chmod "' . $this->cacheDir . '" to make it writable');
784
-        }
785
-    }
786
-
787
-    /**
788
-     * Returns the compile directory with a trailing DIRECTORY_SEPARATOR.
789
-     *
790
-     * @return string
791
-     */
792
-    public function getCompileDir()
793
-    {
794
-        if ($this->compileDir === null) {
795
-            $this->setCompileDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR);
796
-        }
797
-
798
-        return $this->compileDir;
799
-    }
800
-
801
-    /**
802
-     * Sets the compile directory and automatically appends a DIRECTORY_SEPARATOR.
803
-     *
804
-     * @param string $dir the compile directory
805
-     *
806
-     * @return void
807
-     * @throws Exception
808
-     */
809
-    public function setCompileDir($dir)
810
-    {
811
-        $this->compileDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
812
-        if (is_writable($this->compileDir) === false) {
813
-            throw new Exception('The compile directory must be writable, chmod "' . $this->compileDir . '" to make it writable');
814
-        }
815
-    }
816
-
817
-    /**
818
-     * Returns an array of the template directory with a trailing DIRECTORY_SEPARATOR
819
-     *
820
-     * @return array
821
-     */
822
-    public function getTemplateDir()
823
-    {
824
-        return $this->templateDir;
825
-    }
826
-
827
-    /**
828
-     * sets the template directory and automatically appends a DIRECTORY_SEPARATOR
829
-     * template directory is stored in an array
830
-     *
831
-     * @param string $dir
832
-     *
833
-     * @throws Exception
834
-     */
835
-    public function setTemplateDir($dir)
836
-    {
837
-        $tmpDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
838
-        if (is_dir($tmpDir) === false) {
839
-            throw new Exception('The template directory: "' . $tmpDir . '" does not exists, create the directory or specify an other location !');
840
-        }
841
-        $this->templateDir[] = $tmpDir;
842
-    }
843
-
844
-    /**
845
-     * Returns the default cache time that is used with templates that do not have a cache time set.
846
-     *
847
-     * @return int the duration in seconds
848
-     */
849
-    public function getCacheTime()
850
-    {
851
-        return $this->cacheTime;
852
-    }
853
-
854
-    /**
855
-     * Sets the default cache time to use with templates that do not have a cache time set.
856
-     *
857
-     * @param int $seconds the duration in seconds
858
-     *
859
-     * @return void
860
-     */
861
-    public function setCacheTime($seconds)
862
-    {
863
-        $this->cacheTime = (int)$seconds;
864
-    }
865
-
866
-    /**
867
-     * Returns the character set used by the string manipulation plugins.
868
-     * the charset is automatically lowercased
869
-     *
870
-     * @return string
871
-     */
872
-    public function getCharset()
873
-    {
874
-        return $this->charset;
875
-    }
876
-
877
-    /**
878
-     * Sets the character set used by the string manipulation plugins.
879
-     * the charset will be automatically lowercased
880
-     *
881
-     * @param string $charset the character set
882
-     *
883
-     * @return void
884
-     */
885
-    public function setCharset($charset)
886
-    {
887
-        $this->charset = strtolower((string)$charset);
888
-    }
889
-
890
-    /**
891
-     * Returns the current template being rendered, when applicable, or null.
892
-     *
893
-     * @return ITemplate|null
894
-     */
895
-    public function getTemplate()
896
-    {
897
-        return $this->template;
898
-    }
899
-
900
-    /**
901
-     * Sets the current template being rendered.
902
-     *
903
-     * @param ITemplate $tpl template object
904
-     *
905
-     * @return void
906
-     */
907
-    public function setTemplate(ITemplate $tpl)
908
-    {
909
-        $this->template = $tpl;
910
-    }
911
-
912
-    /**
913
-     * Sets the default compiler factory function for the given resource name.
914
-     * a compiler factory must return a ICompiler object pre-configured to fit your needs
915
-     *
916
-     * @param string   $resourceName    the resource name (i.e. file, string)
917
-     * @param callback $compilerFactory the compiler factory callback
918
-     *
919
-     * @return void
920
-     */
921
-    public function setDefaultCompilerFactory($resourceName, $compilerFactory)
922
-    {
923
-        $this->resources[$resourceName]['compiler'] = $compilerFactory;
924
-    }
925
-
926
-    /**
927
-     * Returns the default compiler factory function for the given resource name.
928
-     *
929
-     * @param string $resourceName the resource name
930
-     *
931
-     * @return callback the compiler factory callback
932
-     */
933
-    public function getDefaultCompilerFactory($resourceName)
934
-    {
935
-        return $this->resources[$resourceName]['compiler'];
936
-    }
937
-
938
-    /**
939
-     * Sets the security policy object to enforce some php security settings.
940
-     * use this if untrusted persons can modify templates
941
-     *
942
-     * @param SecurityPolicy $policy the security policy object
943
-     *
944
-     * @return void
945
-     */
946
-    public function setSecurityPolicy(SecurityPolicy $policy = null)
947
-    {
948
-        $this->securityPolicy = $policy;
949
-    }
950
-
951
-    /**
952
-     * Returns the current security policy object or null by default.
953
-     *
954
-     * @return SecurityPolicy|null the security policy object if any
955
-     */
956
-    public function getSecurityPolicy()
957
-    {
958
-        return $this->securityPolicy;
959
-    }
960
-
961
-    /**
962
-     * Sets the object that must be used as a plugin proxy when plugin can't be found
963
-     * by dwoo's loader.
964
-     *
965
-     * @param IPluginProxy $pluginProxy the proxy object
966
-     *
967
-     * @return void
968
-     */
969
-    public function setPluginProxy(IPluginProxy $pluginProxy)
970
-    {
971
-        $this->pluginProxy = $pluginProxy;
972
-    }
973
-
974
-    /**
975
-     * Returns the current plugin proxy object or null by default.
976
-     *
977
-     * @return IPluginProxy
978
-     */
979
-    public function getPluginProxy()
980
-    {
981
-        return $this->pluginProxy;
982
-    }
983
-
984
-    /**
985
-     * Checks whether the given template is cached or not.
986
-     *
987
-     * @param ITemplate $tpl the template object
988
-     *
989
-     * @return bool
990
-     */
991
-    public function isCached(ITemplate $tpl)
992
-    {
993
-        return is_string($tpl->getCachedTemplate($this));
994
-    }
995
-
996
-    /**
997
-     * Clear templates inside the compiled directory.
998
-     *
999
-     * @return int
1000
-     */
1001
-    public function clearCompiled()
1002
-    {
1003
-        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCompileDir()), \RecursiveIteratorIterator::SELF_FIRST);
1004
-        $count    = 0;
1005
-        foreach ($iterator as $file) {
1006
-            if ($file->isFile()) {
1007
-                $count += unlink($file->__toString()) ? 1 : 0;
1008
-            }
1009
-        }
1010
-
1011
-        return $count;
1012
-    }
1013
-
1014
-    /**
1015
-     * Clears the cached templates if they are older than the given time.
1016
-     *
1017
-     * @param int $olderThan minimum time (in seconds) required for a cached template to be cleared
1018
-     *
1019
-     * @return int the amount of templates cleared
1020
-     */
1021
-    public function clearCache($olderThan = - 1)
1022
-    {
1023
-        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCacheDir()), \RecursiveIteratorIterator::SELF_FIRST);
1024
-        $expired  = time() - $olderThan;
1025
-        $count    = 0;
1026
-        foreach ($iterator as $file) {
1027
-            if ($file->isFile() && $file->getCTime() < $expired) {
1028
-                $count += unlink((string)$file) ? 1 : 0;
1029
-            }
1030
-        }
1031
-
1032
-        return $count;
1033
-    }
1034
-
1035
-    /**
1036
-     * Fetches a template object of the given resource.
1037
-     *
1038
-     * @param string    $resourceName   the resource name (i.e. file, string)
1039
-     * @param string    $resourceId     the resource identifier (i.e. file path)
1040
-     * @param int       $cacheTime      the cache time setting for this resource
1041
-     * @param string    $cacheId        the unique cache identifier
1042
-     * @param string    $compileId      the unique compiler identifier
1043
-     * @param ITemplate $parentTemplate the parent template
1044
-     *
1045
-     * @return ITemplate
1046
-     * @throws Exception
1047
-     */
1048
-    public function templateFactory($resourceName, $resourceId, $cacheTime = null, $cacheId = null, $compileId = null, ITemplate $parentTemplate = null)
1049
-    {
1050
-        if (isset($this->resources[$resourceName])) {
1051
-            /**
1052
-             * Interface ITemplate
1053
-             *
1054
-             * @var ITemplate $class
1055
-             */
1056
-            $class = $this->resources[$resourceName]['class'];
1057
-
1058
-            return $class::templateFactory($this, $resourceId, $cacheTime, $cacheId, $compileId, $parentTemplate);
1059
-        }
1060
-
1061
-        throw new Exception('Unknown resource type : ' . $resourceName);
1062
-    }
1063
-
1064
-    /**
1065
-     * Checks if the input is an array or arrayaccess object, optionally it can also check if it's
1066
-     * empty.
1067
-     *
1068
-     * @param mixed $value        the variable to check
1069
-     * @param bool  $checkIsEmpty if true, the function will also check if the array|arrayaccess is empty,
1070
-     *                            and return true only if it's not empty
1071
-     *
1072
-     * @return int|bool true if it's an array|arrayaccess (or the item count if $checkIsEmpty is true) or false if it's
1073
-     *                  not an array|arrayaccess (or 0 if $checkIsEmpty is true)
1074
-     */
1075
-    public function isArray($value, $checkIsEmpty = false)
1076
-    {
1077
-        if (is_array($value) === true || $value instanceof ArrayAccess) {
1078
-            if ($checkIsEmpty === false) {
1079
-                return true;
1080
-            }
1081
-
1082
-            return $this->count($value);
1083
-        }
1084
-
1085
-        return false;
1086
-    }
1087
-
1088
-    /**
1089
-     * Checks if the input is an array or a traversable object, optionally it can also check if it's
1090
-     * empty.
1091
-     *
1092
-     * @param mixed $value        the variable to check
1093
-     * @param bool  $checkIsEmpty if true, the function will also check if the array|traversable is empty,
1094
-     *                            and return true only if it's not empty
1095
-     *
1096
-     * @return int|bool true if it's an array|traversable (or the item count if $checkIsEmpty is true) or false if it's
1097
-     *                  not an array|traversable (or 0 if $checkIsEmpty is true)
1098
-     */
1099
-    public function isTraversable($value, $checkIsEmpty = false)
1100
-    {
1101
-        if (is_array($value) === true) {
1102
-            if ($checkIsEmpty === false) {
1103
-                return true;
1104
-            } else {
1105
-                return count($value) > 0;
1106
-            }
1107
-        } elseif ($value instanceof Traversable) {
1108
-            if ($checkIsEmpty === false) {
1109
-                return true;
1110
-            } else {
1111
-                return $this->count($value);
1112
-            }
1113
-        }
1114
-
1115
-        return false;
1116
-    }
1117
-
1118
-    /**
1119
-     * Counts an array or arrayaccess/traversable object.
1120
-     *
1121
-     * @param mixed $value the value to count
1122
-     *
1123
-     * @return int|bool the count for arrays and objects that implement countable, true for other objects that don't,
1124
-     *                  and 0 for empty elements
1125
-     */
1126
-    public function count($value)
1127
-    {
1128
-        if (is_array($value) === true || $value instanceof Countable) {
1129
-            return count($value);
1130
-        } elseif ($value instanceof ArrayAccess) {
1131
-            if ($value->offsetExists(0)) {
1132
-                return true;
1133
-            }
1134
-        } elseif ($value instanceof Iterator) {
1135
-            $value->rewind();
1136
-            if ($value->valid()) {
1137
-                return true;
1138
-            }
1139
-        } elseif ($value instanceof Traversable) {
1140
-            foreach ($value as $dummy) {
1141
-                return true;
1142
-            }
1143
-        }
1144
-
1145
-        return 0;
1146
-    }
1147
-
1148
-    /**
1149
-     * Triggers a dwoo error.
1150
-     *
1151
-     * @param string $message the error message
1152
-     * @param int    $level   the error level, one of the PHP's E_* constants
1153
-     *
1154
-     * @return void
1155
-     */
1156
-    public function triggerError($message, $level = E_USER_NOTICE)
1157
-    {
1158
-        if (!($tplIdentifier = $this->template->getResourceIdentifier())) {
1159
-            $tplIdentifier = $this->template->getResourceName();
1160
-        }
1161
-        trigger_error('Dwoo error (in ' . $tplIdentifier . ') : ' . $message, $level);
1162
-    }
1163
-
1164
-    /**
1165
-     * Adds a block to the block stack.
1166
-     *
1167
-     * @param string $blockName the block name (without Dwoo_Plugin_ prefix)
1168
-     * @param array  $args      the arguments to be passed to the block's init() function
1169
-     *
1170
-     * @return BlockPlugin the newly created block
1171
-     */
1172
-    public function addStack($blockName, array $args = array())
1173
-    {
1174
-        if (isset($this->plugins[$blockName])) {
1175
-            $class = $this->plugins[$blockName]['class'];
1176
-        } else {
1177
-            $class = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . self::toCamelCase($blockName);
1178
-        }
1179
-
1180
-        if ($this->curBlock !== null) {
1181
-            $this->curBlock->buffer(ob_get_contents());
1182
-            ob_clean();
1183
-        } else {
1184
-            $this->buffer .= ob_get_contents();
1185
-            ob_clean();
1186
-        }
1187
-
1188
-        $block = new $class($this);
1189
-
1190
-        call_user_func_array(array($block, 'init'), $args);
1191
-
1192
-        $this->stack[] = $this->curBlock = $block;
1193
-
1194
-        return $block;
1195
-    }
1196
-
1197
-    /**
1198
-     * Removes the plugin at the top of the block stack.
1199
-     * Calls the block buffer() function, followed by a call to end() and finally a call to process()
1200
-     *
1201
-     * @return void
1202
-     */
1203
-    public function delStack()
1204
-    {
1205
-        $args = func_get_args();
1206
-
1207
-        $this->curBlock->buffer(ob_get_contents());
1208
-        ob_clean();
1209
-
1210
-        call_user_func_array(array($this->curBlock, 'end'), $args);
1211
-
1212
-        $tmp = array_pop($this->stack);
1213
-
1214
-        if (count($this->stack) > 0) {
1215
-            $this->curBlock = end($this->stack);
1216
-            $this->curBlock->buffer($tmp->process());
1217
-        } else {
1218
-            if ($this->buffer !== '') {
1219
-                echo $this->buffer;
1220
-                $this->buffer = '';
1221
-            }
1222
-            $this->curBlock = null;
1223
-            echo $tmp->process();
1224
-        }
1225
-
1226
-        unset($tmp);
1227
-    }
1228
-
1229
-    /**
1230
-     * Returns the parent block of the given block.
1231
-     *
1232
-     * @param BlockPlugin $block the block class plugin
1233
-     *
1234
-     * @return BlockPlugin|false if the given block isn't in the stack
1235
-     */
1236
-    public function getParentBlock(BlockPlugin $block)
1237
-    {
1238
-        $index = array_search($block, $this->stack, true);
1239
-        if ($index !== false && $index > 0) {
1240
-            return $this->stack[$index - 1];
1241
-        }
1242
-
1243
-        return false;
1244
-    }
1245
-
1246
-    /**
1247
-     * Finds the closest block of the given type, starting at the top of the stack.
1248
-     *
1249
-     * @param string $type the type of plugin you want to find
1250
-     *
1251
-     * @return BlockPlugin|false if no plugin of such type is in the stack
1252
-     */
1253
-    public function findBlock($type)
1254
-    {
1255
-        if (isset($this->plugins[$type])) {
1256
-            $type = $this->plugins[$type]['class'];
1257
-        } else {
1258
-            $type = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin_' . str_replace(self::NAMESPACE_PLUGINS_BLOCKS.'Plugin',
1259
-                    '', $type);
1260
-        }
1261
-
1262
-        $keys = array_keys($this->stack);
1263
-        while (($key = array_pop($keys)) !== false) {
1264
-            if ($this->stack[$key] instanceof $type) {
1265
-                return $this->stack[$key];
1266
-            }
1267
-        }
1268
-
1269
-        return false;
1270
-    }
1271
-
1272
-    /**
1273
-     * Returns a Plugin of the given class.
1274
-     * this is so a single instance of every class plugin is created at each template run,
1275
-     * allowing class plugins to have "per-template-run" static variables
1276
-     *
1277
-     * @param string $class the class name
1278
-     *
1279
-     * @return mixed an object of the given class
1280
-     */
1281
-    public function getObjectPlugin($class)
1282
-    {
1283
-        if (isset($this->runtimePlugins[$class])) {
1284
-            return $this->runtimePlugins[$class];
1285
-        }
1286
-
1287
-        return $this->runtimePlugins[$class] = new $class($this);
1288
-    }
1289
-
1290
-    /**
1291
-     * Calls the process() method of the given class-plugin name.
1292
-     *
1293
-     * @param string $plugName the class plugin name (without Dwoo_Plugin_ prefix)
1294
-     * @param array  $params   an array of parameters to send to the process() method
1295
-     *
1296
-     * @return string the process() return value
1297
-     */
1298
-    public function classCall($plugName, array $params = array())
1299
-    {
1300
-        $class  = self::toCamelCase($plugName);
1301
-        $plugin = $this->getObjectPlugin($class);
1302
-
1303
-        return call_user_func_array(array($plugin, 'process'), $params);
1304
-    }
1305
-
1306
-    /**
1307
-     * Calls a php function.
1308
-     *
1309
-     * @param string $callback the function to call
1310
-     * @param array  $params   an array of parameters to send to the function
1311
-     *
1312
-     * @return mixed the return value of the called function
1313
-     */
1314
-    public function arrayMap($callback, array $params)
1315
-    {
1316
-        if ($params[0] === $this) {
1317
-            $addThis = true;
1318
-            array_shift($params);
1319
-        }
1320
-        if ((is_array($params[0]) || ($params[0] instanceof Iterator && $params[0] instanceof ArrayAccess))) {
1321
-            if (empty($params[0])) {
1322
-                return $params[0];
1323
-            }
1324
-
1325
-            // array map
1326
-            $out = array();
1327
-            $cnt = count($params);
1328
-
1329
-            if (isset($addThis)) {
1330
-                array_unshift($params, $this);
1331
-                $items = $params[1];
1332
-                $keys  = array_keys($items);
1333
-
1334
-                if (is_string($callback) === false) {
1335
-                    while (($i = array_shift($keys)) !== null) {
1336
-                        $out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1337
-                    }
1338
-                } elseif ($cnt === 1) {
1339
-                    while (($i = array_shift($keys)) !== null) {
1340
-                        $out[] = $callback($this, $items[$i]);
1341
-                    }
1342
-                } elseif ($cnt === 2) {
1343
-                    while (($i = array_shift($keys)) !== null) {
1344
-                        $out[] = $callback($this, $items[$i], $params[2]);
1345
-                    }
1346
-                } elseif ($cnt === 3) {
1347
-                    while (($i = array_shift($keys)) !== null) {
1348
-                        $out[] = $callback($this, $items[$i], $params[2], $params[3]);
1349
-                    }
1350
-                } else {
1351
-                    while (($i = array_shift($keys)) !== null) {
1352
-                        $out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1353
-                    }
1354
-                }
1355
-            } else {
1356
-                $items = $params[0];
1357
-                $keys  = array_keys($items);
1358
-
1359
-                if (is_string($callback) === false) {
1360
-                    while (($i = array_shift($keys)) !== null) {
1361
-                        $out[] = call_user_func_array($callback, array($items[$i]) + $params);
1362
-                    }
1363
-                } elseif ($cnt === 1) {
1364
-                    while (($i = array_shift($keys)) !== null) {
1365
-                        $out[] = $callback($items[$i]);
1366
-                    }
1367
-                } elseif ($cnt === 2) {
1368
-                    while (($i = array_shift($keys)) !== null) {
1369
-                        $out[] = $callback($items[$i], $params[1]);
1370
-                    }
1371
-                } elseif ($cnt === 3) {
1372
-                    while (($i = array_shift($keys)) !== null) {
1373
-                        $out[] = $callback($items[$i], $params[1], $params[2]);
1374
-                    }
1375
-                } elseif ($cnt === 4) {
1376
-                    while (($i = array_shift($keys)) !== null) {
1377
-                        $out[] = $callback($items[$i], $params[1], $params[2], $params[3]);
1378
-                    }
1379
-                } else {
1380
-                    while (($i = array_shift($keys)) !== null) {
1381
-                        $out[] = call_user_func_array($callback, array($items[$i]) + $params);
1382
-                    }
1383
-                }
1384
-            }
1385
-
1386
-            return $out;
1387
-        } else {
1388
-            return $params[0];
1389
-        }
1390
-    }
1391
-
1392
-    /**
1393
-     * Reads a variable into the given data array.
1394
-     *
1395
-     * @param string $varstr   the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1396
-     * @param mixed  $data     the data array or object to read from
1397
-     * @param bool   $safeRead if true, the function will check whether the index exists to prevent any notices from
1398
-     *                         being output
1399
-     *
1400
-     * @return mixed
1401
-     */
1402
-    public function readVarInto($varstr, $data, $safeRead = false)
1403
-    {
1404
-        if ($data === null) {
1405
-            return null;
1406
-        }
1407
-
1408
-        if (is_array($varstr) === false) {
1409
-            preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1410
-        } else {
1411
-            $m = $varstr;
1412
-        }
1413
-        unset($varstr);
1414
-
1415
-        while (list($k, $sep) = each($m[1])) {
1416
-            if ($sep === '.' || $sep === '[' || $sep === '') {
1417
-                // strip enclosing quotes if present
1418
-                $m[2][$k] = preg_replace('#^(["\']?)(.*?)\1$#', '$2', $m[2][$k]);
1419
-
1420
-                if ((is_array($data) || $data instanceof ArrayAccess) && ($safeRead === false || isset($data[$m[2][$k]]))) {
1421
-                    $data = $data[$m[2][$k]];
1422
-                } else {
1423
-                    return null;
1424
-                }
1425
-            } else {
1426
-                if (is_object($data) && ($safeRead === false || isset($data->{$m[2][$k]}))) {
1427
-                    $data = $data->{$m[2][$k]};
1428
-                } else {
1429
-                    return null;
1430
-                }
1431
-            }
1432
-        }
1433
-
1434
-        return $data;
1435
-    }
1436
-
1437
-    /**
1438
-     * Reads a variable into the parent scope.
1439
-     *
1440
-     * @param int    $parentLevels the amount of parent levels to go from the current scope
1441
-     * @param string $varstr       the variable string, using dwoo variable syntax (i.e.
1442
-     *                             "var.subvar[subsubvar]->property")
1443
-     *
1444
-     * @return mixed
1445
-     */
1446
-    public function readParentVar($parentLevels, $varstr = null)
1447
-    {
1448
-        $tree = $this->scopeTree;
1449
-        $cur  = $this->data;
1450
-
1451
-        while ($parentLevels -- !== 0) {
1452
-            array_pop($tree);
1453
-        }
1454
-
1455
-        while (($i = array_shift($tree)) !== null) {
1456
-            if (is_object($cur)) {
1457
-                $cur = $cur->{$i};
1458
-            } else {
1459
-                $cur = $cur[$i];
1460
-            }
1461
-        }
1462
-
1463
-        if ($varstr !== null) {
1464
-            return $this->readVarInto($varstr, $cur);
1465
-        } else {
1466
-            return $cur;
1467
-        }
1468
-    }
1469
-
1470
-    /**
1471
-     * Reads a variable into the current scope.
1472
-     *
1473
-     * @param string $varstr the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1474
-     *
1475
-     * @return mixed
1476
-     */
1477
-    public function readVar($varstr)
1478
-    {
1479
-        if (is_array($varstr) === true) {
1480
-            $m = $varstr;
1481
-            unset($varstr);
1482
-        } else {
1483
-            if (strstr($varstr, '.') === false && strstr($varstr, '[') === false && strstr($varstr, '->') === false) {
1484
-                if ($varstr === 'dwoo') {
1485
-                    return $this->getGlobals();
1486
-                } elseif ($varstr === '__' || $varstr === '_root') {
1487
-                    return $this->data;
1488
-                } elseif ($varstr === '_' || $varstr === '_parent') {
1489
-                    $varstr = '.' . $varstr;
1490
-                    $tree   = $this->scopeTree;
1491
-                    $cur    = $this->data;
1492
-                    array_pop($tree);
1493
-
1494
-                    while (($i = array_shift($tree)) !== null) {
1495
-                        if (is_object($cur)) {
1496
-                            $cur = $cur->{$i};
1497
-                        } else {
1498
-                            $cur = $cur[$i];
1499
-                        }
1500
-                    }
1501
-
1502
-                    return $cur;
1503
-                }
1504
-
1505
-                $cur = $this->scope;
1506
-
1507
-                if (isset($cur[$varstr])) {
1508
-                    return $cur[$varstr];
1509
-                } else {
1510
-                    return null;
1511
-                }
1512
-            }
1513
-
1514
-            if (substr($varstr, 0, 1) === '.') {
1515
-                $varstr = 'dwoo' . $varstr;
1516
-            }
1517
-
1518
-            preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1519
-        }
1520
-
1521
-        $i = $m[2][0];
1522
-        if ($i === 'dwoo') {
1523
-            $cur = $this->getGlobals();
1524
-            array_shift($m[2]);
1525
-            array_shift($m[1]);
1526
-            switch ($m[2][0]) {
1527
-            case 'get':
1528
-                $cur = $_GET;
1529
-                break;
1530
-            case 'post':
1531
-                $cur = $_POST;
1532
-                break;
1533
-            case 'session':
1534
-                $cur = $_SESSION;
1535
-                break;
1536
-            case 'cookies':
1537
-            case 'cookie':
1538
-                $cur = $_COOKIE;
1539
-                break;
1540
-            case 'server':
1541
-                $cur = $_SERVER;
1542
-                break;
1543
-            case 'env':
1544
-                $cur = $_ENV;
1545
-                break;
1546
-            case 'request':
1547
-                $cur = $_REQUEST;
1548
-                break;
1549
-            case 'const':
1550
-                array_shift($m[2]);
1551
-                if (defined($m[2][0])) {
1552
-                    return constant($m[2][0]);
1553
-                } else {
1554
-                    return null;
1555
-                }
1556
-            }
1557
-            if ($cur !== $this->getGlobals()) {
1558
-                array_shift($m[2]);
1559
-                array_shift($m[1]);
1560
-            }
1561
-        } elseif ($i === '__' || $i === '_root') {
1562
-            $cur = $this->data;
1563
-            array_shift($m[2]);
1564
-            array_shift($m[1]);
1565
-        } elseif ($i === '_' || $i === '_parent') {
1566
-            $tree = $this->scopeTree;
1567
-            $cur  = $this->data;
1568
-
1569
-            while (true) {
1570
-                array_pop($tree);
1571
-                array_shift($m[2]);
1572
-                array_shift($m[1]);
1573
-                if (current($m[2]) === '_' || current($m[2]) === '_parent') {
1574
-                    continue;
1575
-                }
1576
-
1577
-                while (($i = array_shift($tree)) !== null) {
1578
-                    if (is_object($cur)) {
1579
-                        $cur = $cur->{$i};
1580
-                    } else {
1581
-                        $cur = $cur[$i];
1582
-                    }
1583
-                }
1584
-                break;
1585
-            }
1586
-        } else {
1587
-            $cur = $this->scope;
1588
-        }
1589
-
1590
-        while (list($k, $sep) = each($m[1])) {
1591
-            if ($sep === '.' || $sep === '[' || $sep === '') {
1592
-                if ((is_array($cur) || $cur instanceof ArrayAccess) && isset($cur[$m[2][$k]])) {
1593
-                    $cur = $cur[$m[2][$k]];
1594
-                } else {
1595
-                    return null;
1596
-                }
1597
-            } elseif ($sep === '->') {
1598
-                if (is_object($cur)) {
1599
-                    $cur = $cur->{$m[2][$k]};
1600
-                } else {
1601
-                    return null;
1602
-                }
1603
-            } else {
1604
-                return null;
1605
-            }
1606
-        }
1607
-
1608
-        return $cur;
1609
-    }
1610
-
1611
-    /**
1612
-     * Assign the value to the given variable.
1613
-     *
1614
-     * @param mixed  $value the value to assign
1615
-     * @param string $scope the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1616
-     *
1617
-     * @return bool true if assigned correctly or false if a problem occured while parsing the var string
1618
-     */
1619
-    public function assignInScope($value, $scope)
1620
-    {
1621
-        if (!is_string($scope)) {
1622
-            $this->triggerError('Assignments must be done into strings, (' . gettype($scope) . ') ' . var_export($scope, true) . ' given', E_USER_ERROR);
1623
-        }
1624
-        if (strstr($scope, '.') === false && strstr($scope, '->') === false) {
1625
-            $this->scope[$scope] = $value;
1626
-        } else {
1627
-            // TODO handle _root/_parent scopes ?
1628
-            preg_match_all('#(\[|->|\.)?([^.[\]-]+)\]?#i', $scope, $m);
1629
-
1630
-            $cur  = &$this->scope;
1631
-            $last = array(
1632
-                array_pop($m[1]),
1633
-                array_pop($m[2])
1634
-            );
1635
-
1636
-            while (list($k, $sep) = each($m[1])) {
1637
-                if ($sep === '.' || $sep === '[' || $sep === '') {
1638
-                    if (is_array($cur) === false) {
1639
-                        $cur = array();
1640
-                    }
1641
-                    $cur = &$cur[$m[2][$k]];
1642
-                } elseif ($sep === '->') {
1643
-                    if (is_object($cur) === false) {
1644
-                        $cur = new stdClass();
1645
-                    }
1646
-                    $cur = &$cur->{$m[2][$k]};
1647
-                } else {
1648
-                    return false;
1649
-                }
1650
-            }
1651
-
1652
-            if ($last[0] === '.' || $last[0] === '[' || $last[0] === '') {
1653
-                if (is_array($cur) === false) {
1654
-                    $cur = array();
1655
-                }
1656
-                $cur[$last[1]] = $value;
1657
-            } elseif ($last[0] === '->') {
1658
-                if (is_object($cur) === false) {
1659
-                    $cur = new stdClass();
1660
-                }
1661
-                $cur->{$last[1]} = $value;
1662
-            } else {
1663
-                return false;
1664
-            }
1665
-        }
1666
-    }
1667
-
1668
-    /**
1669
-     * Sets the scope to the given scope string or array.
1670
-     *
1671
-     * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1672
-     * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1673
-     *
1674
-     * @return array the current scope tree
1675
-     */
1676
-    public function setScope($scope, $absolute = false)
1677
-    {
1678
-        $old = $this->scopeTree;
1679
-
1680
-        if (is_string($scope) === true) {
1681
-            $scope = explode('.', $scope);
1682
-        }
1683
-
1684
-        if ($absolute === true) {
1685
-            $this->scope     = &$this->data;
1686
-            $this->scopeTree = array();
1687
-        }
1688
-
1689
-        while (($bit = array_shift($scope)) !== null) {
1690
-            if ($bit === '_' || $bit === '_parent') {
1691
-                array_pop($this->scopeTree);
1692
-                $this->scope = &$this->data;
1693
-                $cnt         = count($this->scopeTree);
1694
-                for ($i = 0; $i < $cnt; ++ $i) {
1695
-                    $this->scope = &$this->scope[$this->scopeTree[$i]];
1696
-                }
1697
-            } elseif ($bit === '__' || $bit === '_root') {
1698
-                $this->scope     = &$this->data;
1699
-                $this->scopeTree = array();
1700
-            } elseif (isset($this->scope[$bit])) {
1701
-                if ($this->scope instanceof ArrayAccess) {
1702
-                    $tmp         = $this->scope[$bit];
1703
-                    $this->scope = &$tmp;
1704
-                } else {
1705
-                    $this->scope = &$this->scope[$bit];
1706
-                }
1707
-                $this->scopeTree[] = $bit;
1708
-            } else {
1709
-                unset($this->scope);
1710
-                $this->scope = null;
1711
-            }
1712
-        }
1713
-
1714
-        return $old;
1715
-    }
1716
-
1717
-    /**
1718
-     * Returns the entire data array.
1719
-     *
1720
-     * @return array
1721
-     */
1722
-    public function getData()
1723
-    {
1724
-        return $this->data;
1725
-    }
1726
-
1727
-    /**
1728
-     * Sets a return value for the currently running template.
1729
-     *
1730
-     * @param string $name  var name
1731
-     * @param mixed  $value var value
1732
-     *
1733
-     * @return void
1734
-     */
1735
-    public function setReturnValue($name, $value)
1736
-    {
1737
-        $this->returnData[$name] = $value;
1738
-    }
1739
-
1740
-    /**
1741
-     * Retrieves the return values set by the template.
1742
-     *
1743
-     * @return array
1744
-     */
1745
-    public function getReturnValues()
1746
-    {
1747
-        return $this->returnData;
1748
-    }
1749
-
1750
-    /**
1751
-     * Returns a reference to the current scope.
1752
-     *
1753
-     * @return mixed
1754
-     */
1755
-    public function &getScope()
1756
-    {
1757
-        return $this->scope;
1758
-    }
1759
-
1760
-    /**
1761
-     * Redirects all calls to unexisting to plugin proxy.
1762
-     *
1763
-     * @param string $method the method name
1764
-     * @param array  $args   array of arguments
1765
-     *
1766
-     * @return mixed
1767
-     * @throws Exception
1768
-     */
1769
-    public function __call($method, $args)
1770
-    {
1771
-        $proxy = $this->getPluginProxy();
1772
-        if (!$proxy) {
1773
-            throw new Exception('Call to undefined method ' . __CLASS__ . '::' . $method . '()');
1774
-        }
1775
-
1776
-        return call_user_func_array($proxy->getCallback($method), $args);
1777
-    }
1778
-
1779
-    /**
1780
-     * Convert plugin name from `auto_escape` to `AutoEscape`.
1781
-     * @param string $input
1782
-     * @param string $separator
1783
-     *
1784
-     * @return mixed
1785
-     */
1786
-    public static function toCamelCase($input, $separator = '_')
1787
-    {
1788
-        return join(array_map('ucfirst', explode($separator, $input)));
1789
-
1790
-        // TODO >= PHP5.4.32
1791
-        //return str_replace($separator, '', ucwords($input, $separator));
1792
-    }
617
+				);
618
+			}
619
+
620
+			$this->filters[] = $callback;
621
+		} else {
622
+			$this->filters[] = $callback;
623
+		}
624
+	}
625
+
626
+	/**
627
+	 * Removes a filter.
628
+	 *
629
+	 * @param mixed $callback callback or filter name if it was autoloaded
630
+	 *
631
+	 * @return void
632
+	 */
633
+	public function removeFilter($callback)
634
+	{
635
+		if (($index = array_search(self::NAMESPACE_PLUGINS_FILTERS. 'Filter' . self::toCamelCase($callback), $this->filters,
636
+				true)) !==
637
+			false) {
638
+			unset($this->filters[$index]);
639
+		} elseif (($index = array_search($callback, $this->filters, true)) !== false) {
640
+			unset($this->filters[$index]);
641
+		} else {
642
+			$class = self::NAMESPACE_PLUGINS_FILTERS . 'Filter' . $callback;
643
+			foreach ($this->filters as $index => $filter) {
644
+				if (is_array($filter) && $filter[0] instanceof $class) {
645
+					unset($this->filters[$index]);
646
+					break;
647
+				}
648
+			}
649
+		}
650
+	}
651
+
652
+	/**
653
+	 * Adds a resource or overrides a default one.
654
+	 *
655
+	 * @param string   $name            the resource name
656
+	 * @param string   $class           the resource class (which must implement ITemplate)
657
+	 * @param callback $compilerFactory the compiler factory callback, a function that must return a compiler instance
658
+	 *                                  used to compile this resource, if none is provided. by default it will produce
659
+	 *                                  a Compiler object
660
+	 *
661
+	 * @return void
662
+	 * @throws Exception
663
+	 */
664
+	public function addResource($name, $class, $compilerFactory = null)
665
+	{
666
+		if (strlen($name) < 2) {
667
+			throw new Exception('Resource names must be at least two-character long to avoid conflicts with Windows paths');
668
+		}
669
+
670
+		if (!class_exists($class)) {
671
+			throw new Exception(sprintf('Resource class %s does not exist', $class));
672
+		}
673
+
674
+		$interfaces = class_implements($class);
675
+		if (in_array('Dwoo\ITemplate', $interfaces) === false) {
676
+			throw new Exception('Resource class must implement ITemplate');
677
+		}
678
+
679
+		$this->resources[$name] = array(
680
+			'class'    => $class,
681
+			'compiler' => $compilerFactory
682
+		);
683
+	}
684
+
685
+	/**
686
+	 * Removes a custom resource.
687
+	 *
688
+	 * @param string $name the resource name
689
+	 *
690
+	 * @return void
691
+	 */
692
+	public function removeResource($name)
693
+	{
694
+		unset($this->resources[$name]);
695
+		if ($name === 'file') {
696
+			$this->resources['file'] = array(
697
+				'class'    => 'Dwoo\Template\File',
698
+				'compiler' => null
699
+			);
700
+		}
701
+	}
702
+
703
+	/**
704
+	 * Sets the loader object to use to load plugins.
705
+	 *
706
+	 * @param ILoader $loader loader
707
+	 *
708
+	 * @return void
709
+	 */
710
+	public function setLoader(ILoader $loader)
711
+	{
712
+		$this->loader = $loader;
713
+	}
714
+
715
+	/**
716
+	 * Returns the current loader object or a default one if none is currently found.
717
+	 *
718
+	 * @return ILoader|Loader
719
+	 */
720
+	public function getLoader()
721
+	{
722
+		if ($this->loader === null) {
723
+			$this->loader = new Loader($this->getCompileDir());
724
+		}
725
+
726
+		return $this->loader;
727
+	}
728
+
729
+	/**
730
+	 * Returns the custom plugins loaded.
731
+	 * Used by the ITemplate classes to pass the custom plugins to their ICompiler instance.
732
+	 *
733
+	 * @return array
734
+	 */
735
+	public function getCustomPlugins()
736
+	{
737
+		return $this->plugins;
738
+	}
739
+
740
+	/**
741
+	 * Return a specified custom plugin loaded by his name.
742
+	 * Used by the compiler, for executing a Closure.
743
+	 *
744
+	 * @param string $name
745
+	 *
746
+	 * @return mixed|null
747
+	 */
748
+	public function getCustomPlugin($name)
749
+	{
750
+		if (isset($this->plugins[$name])) {
751
+			return $this->plugins[$name]['callback'];
752
+		}
753
+
754
+		return null;
755
+	}
756
+
757
+	/**
758
+	 * Returns the cache directory with a trailing DIRECTORY_SEPARATOR.
759
+	 *
760
+	 * @return string
761
+	 */
762
+	public function getCacheDir()
763
+	{
764
+		if ($this->cacheDir === null) {
765
+			$this->setCacheDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR);
766
+		}
767
+
768
+		return $this->cacheDir;
769
+	}
770
+
771
+	/**
772
+	 * Sets the cache directory and automatically appends a DIRECTORY_SEPARATOR.
773
+	 *
774
+	 * @param string $dir the cache directory
775
+	 *
776
+	 * @return void
777
+	 * @throws Exception
778
+	 */
779
+	public function setCacheDir($dir)
780
+	{
781
+		$this->cacheDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
782
+		if (is_writable($this->cacheDir) === false) {
783
+			throw new Exception('The cache directory must be writable, chmod "' . $this->cacheDir . '" to make it writable');
784
+		}
785
+	}
786
+
787
+	/**
788
+	 * Returns the compile directory with a trailing DIRECTORY_SEPARATOR.
789
+	 *
790
+	 * @return string
791
+	 */
792
+	public function getCompileDir()
793
+	{
794
+		if ($this->compileDir === null) {
795
+			$this->setCompileDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR);
796
+		}
797
+
798
+		return $this->compileDir;
799
+	}
800
+
801
+	/**
802
+	 * Sets the compile directory and automatically appends a DIRECTORY_SEPARATOR.
803
+	 *
804
+	 * @param string $dir the compile directory
805
+	 *
806
+	 * @return void
807
+	 * @throws Exception
808
+	 */
809
+	public function setCompileDir($dir)
810
+	{
811
+		$this->compileDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
812
+		if (is_writable($this->compileDir) === false) {
813
+			throw new Exception('The compile directory must be writable, chmod "' . $this->compileDir . '" to make it writable');
814
+		}
815
+	}
816
+
817
+	/**
818
+	 * Returns an array of the template directory with a trailing DIRECTORY_SEPARATOR
819
+	 *
820
+	 * @return array
821
+	 */
822
+	public function getTemplateDir()
823
+	{
824
+		return $this->templateDir;
825
+	}
826
+
827
+	/**
828
+	 * sets the template directory and automatically appends a DIRECTORY_SEPARATOR
829
+	 * template directory is stored in an array
830
+	 *
831
+	 * @param string $dir
832
+	 *
833
+	 * @throws Exception
834
+	 */
835
+	public function setTemplateDir($dir)
836
+	{
837
+		$tmpDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
838
+		if (is_dir($tmpDir) === false) {
839
+			throw new Exception('The template directory: "' . $tmpDir . '" does not exists, create the directory or specify an other location !');
840
+		}
841
+		$this->templateDir[] = $tmpDir;
842
+	}
843
+
844
+	/**
845
+	 * Returns the default cache time that is used with templates that do not have a cache time set.
846
+	 *
847
+	 * @return int the duration in seconds
848
+	 */
849
+	public function getCacheTime()
850
+	{
851
+		return $this->cacheTime;
852
+	}
853
+
854
+	/**
855
+	 * Sets the default cache time to use with templates that do not have a cache time set.
856
+	 *
857
+	 * @param int $seconds the duration in seconds
858
+	 *
859
+	 * @return void
860
+	 */
861
+	public function setCacheTime($seconds)
862
+	{
863
+		$this->cacheTime = (int)$seconds;
864
+	}
865
+
866
+	/**
867
+	 * Returns the character set used by the string manipulation plugins.
868
+	 * the charset is automatically lowercased
869
+	 *
870
+	 * @return string
871
+	 */
872
+	public function getCharset()
873
+	{
874
+		return $this->charset;
875
+	}
876
+
877
+	/**
878
+	 * Sets the character set used by the string manipulation plugins.
879
+	 * the charset will be automatically lowercased
880
+	 *
881
+	 * @param string $charset the character set
882
+	 *
883
+	 * @return void
884
+	 */
885
+	public function setCharset($charset)
886
+	{
887
+		$this->charset = strtolower((string)$charset);
888
+	}
889
+
890
+	/**
891
+	 * Returns the current template being rendered, when applicable, or null.
892
+	 *
893
+	 * @return ITemplate|null
894
+	 */
895
+	public function getTemplate()
896
+	{
897
+		return $this->template;
898
+	}
899
+
900
+	/**
901
+	 * Sets the current template being rendered.
902
+	 *
903
+	 * @param ITemplate $tpl template object
904
+	 *
905
+	 * @return void
906
+	 */
907
+	public function setTemplate(ITemplate $tpl)
908
+	{
909
+		$this->template = $tpl;
910
+	}
911
+
912
+	/**
913
+	 * Sets the default compiler factory function for the given resource name.
914
+	 * a compiler factory must return a ICompiler object pre-configured to fit your needs
915
+	 *
916
+	 * @param string   $resourceName    the resource name (i.e. file, string)
917
+	 * @param callback $compilerFactory the compiler factory callback
918
+	 *
919
+	 * @return void
920
+	 */
921
+	public function setDefaultCompilerFactory($resourceName, $compilerFactory)
922
+	{
923
+		$this->resources[$resourceName]['compiler'] = $compilerFactory;
924
+	}
925
+
926
+	/**
927
+	 * Returns the default compiler factory function for the given resource name.
928
+	 *
929
+	 * @param string $resourceName the resource name
930
+	 *
931
+	 * @return callback the compiler factory callback
932
+	 */
933
+	public function getDefaultCompilerFactory($resourceName)
934
+	{
935
+		return $this->resources[$resourceName]['compiler'];
936
+	}
937
+
938
+	/**
939
+	 * Sets the security policy object to enforce some php security settings.
940
+	 * use this if untrusted persons can modify templates
941
+	 *
942
+	 * @param SecurityPolicy $policy the security policy object
943
+	 *
944
+	 * @return void
945
+	 */
946
+	public function setSecurityPolicy(SecurityPolicy $policy = null)
947
+	{
948
+		$this->securityPolicy = $policy;
949
+	}
950
+
951
+	/**
952
+	 * Returns the current security policy object or null by default.
953
+	 *
954
+	 * @return SecurityPolicy|null the security policy object if any
955
+	 */
956
+	public function getSecurityPolicy()
957
+	{
958
+		return $this->securityPolicy;
959
+	}
960
+
961
+	/**
962
+	 * Sets the object that must be used as a plugin proxy when plugin can't be found
963
+	 * by dwoo's loader.
964
+	 *
965
+	 * @param IPluginProxy $pluginProxy the proxy object
966
+	 *
967
+	 * @return void
968
+	 */
969
+	public function setPluginProxy(IPluginProxy $pluginProxy)
970
+	{
971
+		$this->pluginProxy = $pluginProxy;
972
+	}
973
+
974
+	/**
975
+	 * Returns the current plugin proxy object or null by default.
976
+	 *
977
+	 * @return IPluginProxy
978
+	 */
979
+	public function getPluginProxy()
980
+	{
981
+		return $this->pluginProxy;
982
+	}
983
+
984
+	/**
985
+	 * Checks whether the given template is cached or not.
986
+	 *
987
+	 * @param ITemplate $tpl the template object
988
+	 *
989
+	 * @return bool
990
+	 */
991
+	public function isCached(ITemplate $tpl)
992
+	{
993
+		return is_string($tpl->getCachedTemplate($this));
994
+	}
995
+
996
+	/**
997
+	 * Clear templates inside the compiled directory.
998
+	 *
999
+	 * @return int
1000
+	 */
1001
+	public function clearCompiled()
1002
+	{
1003
+		$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCompileDir()), \RecursiveIteratorIterator::SELF_FIRST);
1004
+		$count    = 0;
1005
+		foreach ($iterator as $file) {
1006
+			if ($file->isFile()) {
1007
+				$count += unlink($file->__toString()) ? 1 : 0;
1008
+			}
1009
+		}
1010
+
1011
+		return $count;
1012
+	}
1013
+
1014
+	/**
1015
+	 * Clears the cached templates if they are older than the given time.
1016
+	 *
1017
+	 * @param int $olderThan minimum time (in seconds) required for a cached template to be cleared
1018
+	 *
1019
+	 * @return int the amount of templates cleared
1020
+	 */
1021
+	public function clearCache($olderThan = - 1)
1022
+	{
1023
+		$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCacheDir()), \RecursiveIteratorIterator::SELF_FIRST);
1024
+		$expired  = time() - $olderThan;
1025
+		$count    = 0;
1026
+		foreach ($iterator as $file) {
1027
+			if ($file->isFile() && $file->getCTime() < $expired) {
1028
+				$count += unlink((string)$file) ? 1 : 0;
1029
+			}
1030
+		}
1031
+
1032
+		return $count;
1033
+	}
1034
+
1035
+	/**
1036
+	 * Fetches a template object of the given resource.
1037
+	 *
1038
+	 * @param string    $resourceName   the resource name (i.e. file, string)
1039
+	 * @param string    $resourceId     the resource identifier (i.e. file path)
1040
+	 * @param int       $cacheTime      the cache time setting for this resource
1041
+	 * @param string    $cacheId        the unique cache identifier
1042
+	 * @param string    $compileId      the unique compiler identifier
1043
+	 * @param ITemplate $parentTemplate the parent template
1044
+	 *
1045
+	 * @return ITemplate
1046
+	 * @throws Exception
1047
+	 */
1048
+	public function templateFactory($resourceName, $resourceId, $cacheTime = null, $cacheId = null, $compileId = null, ITemplate $parentTemplate = null)
1049
+	{
1050
+		if (isset($this->resources[$resourceName])) {
1051
+			/**
1052
+			 * Interface ITemplate
1053
+			 *
1054
+			 * @var ITemplate $class
1055
+			 */
1056
+			$class = $this->resources[$resourceName]['class'];
1057
+
1058
+			return $class::templateFactory($this, $resourceId, $cacheTime, $cacheId, $compileId, $parentTemplate);
1059
+		}
1060
+
1061
+		throw new Exception('Unknown resource type : ' . $resourceName);
1062
+	}
1063
+
1064
+	/**
1065
+	 * Checks if the input is an array or arrayaccess object, optionally it can also check if it's
1066
+	 * empty.
1067
+	 *
1068
+	 * @param mixed $value        the variable to check
1069
+	 * @param bool  $checkIsEmpty if true, the function will also check if the array|arrayaccess is empty,
1070
+	 *                            and return true only if it's not empty
1071
+	 *
1072
+	 * @return int|bool true if it's an array|arrayaccess (or the item count if $checkIsEmpty is true) or false if it's
1073
+	 *                  not an array|arrayaccess (or 0 if $checkIsEmpty is true)
1074
+	 */
1075
+	public function isArray($value, $checkIsEmpty = false)
1076
+	{
1077
+		if (is_array($value) === true || $value instanceof ArrayAccess) {
1078
+			if ($checkIsEmpty === false) {
1079
+				return true;
1080
+			}
1081
+
1082
+			return $this->count($value);
1083
+		}
1084
+
1085
+		return false;
1086
+	}
1087
+
1088
+	/**
1089
+	 * Checks if the input is an array or a traversable object, optionally it can also check if it's
1090
+	 * empty.
1091
+	 *
1092
+	 * @param mixed $value        the variable to check
1093
+	 * @param bool  $checkIsEmpty if true, the function will also check if the array|traversable is empty,
1094
+	 *                            and return true only if it's not empty
1095
+	 *
1096
+	 * @return int|bool true if it's an array|traversable (or the item count if $checkIsEmpty is true) or false if it's
1097
+	 *                  not an array|traversable (or 0 if $checkIsEmpty is true)
1098
+	 */
1099
+	public function isTraversable($value, $checkIsEmpty = false)
1100
+	{
1101
+		if (is_array($value) === true) {
1102
+			if ($checkIsEmpty === false) {
1103
+				return true;
1104
+			} else {
1105
+				return count($value) > 0;
1106
+			}
1107
+		} elseif ($value instanceof Traversable) {
1108
+			if ($checkIsEmpty === false) {
1109
+				return true;
1110
+			} else {
1111
+				return $this->count($value);
1112
+			}
1113
+		}
1114
+
1115
+		return false;
1116
+	}
1117
+
1118
+	/**
1119
+	 * Counts an array or arrayaccess/traversable object.
1120
+	 *
1121
+	 * @param mixed $value the value to count
1122
+	 *
1123
+	 * @return int|bool the count for arrays and objects that implement countable, true for other objects that don't,
1124
+	 *                  and 0 for empty elements
1125
+	 */
1126
+	public function count($value)
1127
+	{
1128
+		if (is_array($value) === true || $value instanceof Countable) {
1129
+			return count($value);
1130
+		} elseif ($value instanceof ArrayAccess) {
1131
+			if ($value->offsetExists(0)) {
1132
+				return true;
1133
+			}
1134
+		} elseif ($value instanceof Iterator) {
1135
+			$value->rewind();
1136
+			if ($value->valid()) {
1137
+				return true;
1138
+			}
1139
+		} elseif ($value instanceof Traversable) {
1140
+			foreach ($value as $dummy) {
1141
+				return true;
1142
+			}
1143
+		}
1144
+
1145
+		return 0;
1146
+	}
1147
+
1148
+	/**
1149
+	 * Triggers a dwoo error.
1150
+	 *
1151
+	 * @param string $message the error message
1152
+	 * @param int    $level   the error level, one of the PHP's E_* constants
1153
+	 *
1154
+	 * @return void
1155
+	 */
1156
+	public function triggerError($message, $level = E_USER_NOTICE)
1157
+	{
1158
+		if (!($tplIdentifier = $this->template->getResourceIdentifier())) {
1159
+			$tplIdentifier = $this->template->getResourceName();
1160
+		}
1161
+		trigger_error('Dwoo error (in ' . $tplIdentifier . ') : ' . $message, $level);
1162
+	}
1163
+
1164
+	/**
1165
+	 * Adds a block to the block stack.
1166
+	 *
1167
+	 * @param string $blockName the block name (without Dwoo_Plugin_ prefix)
1168
+	 * @param array  $args      the arguments to be passed to the block's init() function
1169
+	 *
1170
+	 * @return BlockPlugin the newly created block
1171
+	 */
1172
+	public function addStack($blockName, array $args = array())
1173
+	{
1174
+		if (isset($this->plugins[$blockName])) {
1175
+			$class = $this->plugins[$blockName]['class'];
1176
+		} else {
1177
+			$class = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . self::toCamelCase($blockName);
1178
+		}
1179
+
1180
+		if ($this->curBlock !== null) {
1181
+			$this->curBlock->buffer(ob_get_contents());
1182
+			ob_clean();
1183
+		} else {
1184
+			$this->buffer .= ob_get_contents();
1185
+			ob_clean();
1186
+		}
1187
+
1188
+		$block = new $class($this);
1189
+
1190
+		call_user_func_array(array($block, 'init'), $args);
1191
+
1192
+		$this->stack[] = $this->curBlock = $block;
1193
+
1194
+		return $block;
1195
+	}
1196
+
1197
+	/**
1198
+	 * Removes the plugin at the top of the block stack.
1199
+	 * Calls the block buffer() function, followed by a call to end() and finally a call to process()
1200
+	 *
1201
+	 * @return void
1202
+	 */
1203
+	public function delStack()
1204
+	{
1205
+		$args = func_get_args();
1206
+
1207
+		$this->curBlock->buffer(ob_get_contents());
1208
+		ob_clean();
1209
+
1210
+		call_user_func_array(array($this->curBlock, 'end'), $args);
1211
+
1212
+		$tmp = array_pop($this->stack);
1213
+
1214
+		if (count($this->stack) > 0) {
1215
+			$this->curBlock = end($this->stack);
1216
+			$this->curBlock->buffer($tmp->process());
1217
+		} else {
1218
+			if ($this->buffer !== '') {
1219
+				echo $this->buffer;
1220
+				$this->buffer = '';
1221
+			}
1222
+			$this->curBlock = null;
1223
+			echo $tmp->process();
1224
+		}
1225
+
1226
+		unset($tmp);
1227
+	}
1228
+
1229
+	/**
1230
+	 * Returns the parent block of the given block.
1231
+	 *
1232
+	 * @param BlockPlugin $block the block class plugin
1233
+	 *
1234
+	 * @return BlockPlugin|false if the given block isn't in the stack
1235
+	 */
1236
+	public function getParentBlock(BlockPlugin $block)
1237
+	{
1238
+		$index = array_search($block, $this->stack, true);
1239
+		if ($index !== false && $index > 0) {
1240
+			return $this->stack[$index - 1];
1241
+		}
1242
+
1243
+		return false;
1244
+	}
1245
+
1246
+	/**
1247
+	 * Finds the closest block of the given type, starting at the top of the stack.
1248
+	 *
1249
+	 * @param string $type the type of plugin you want to find
1250
+	 *
1251
+	 * @return BlockPlugin|false if no plugin of such type is in the stack
1252
+	 */
1253
+	public function findBlock($type)
1254
+	{
1255
+		if (isset($this->plugins[$type])) {
1256
+			$type = $this->plugins[$type]['class'];
1257
+		} else {
1258
+			$type = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin_' . str_replace(self::NAMESPACE_PLUGINS_BLOCKS.'Plugin',
1259
+					'', $type);
1260
+		}
1261
+
1262
+		$keys = array_keys($this->stack);
1263
+		while (($key = array_pop($keys)) !== false) {
1264
+			if ($this->stack[$key] instanceof $type) {
1265
+				return $this->stack[$key];
1266
+			}
1267
+		}
1268
+
1269
+		return false;
1270
+	}
1271
+
1272
+	/**
1273
+	 * Returns a Plugin of the given class.
1274
+	 * this is so a single instance of every class plugin is created at each template run,
1275
+	 * allowing class plugins to have "per-template-run" static variables
1276
+	 *
1277
+	 * @param string $class the class name
1278
+	 *
1279
+	 * @return mixed an object of the given class
1280
+	 */
1281
+	public function getObjectPlugin($class)
1282
+	{
1283
+		if (isset($this->runtimePlugins[$class])) {
1284
+			return $this->runtimePlugins[$class];
1285
+		}
1286
+
1287
+		return $this->runtimePlugins[$class] = new $class($this);
1288
+	}
1289
+
1290
+	/**
1291
+	 * Calls the process() method of the given class-plugin name.
1292
+	 *
1293
+	 * @param string $plugName the class plugin name (without Dwoo_Plugin_ prefix)
1294
+	 * @param array  $params   an array of parameters to send to the process() method
1295
+	 *
1296
+	 * @return string the process() return value
1297
+	 */
1298
+	public function classCall($plugName, array $params = array())
1299
+	{
1300
+		$class  = self::toCamelCase($plugName);
1301
+		$plugin = $this->getObjectPlugin($class);
1302
+
1303
+		return call_user_func_array(array($plugin, 'process'), $params);
1304
+	}
1305
+
1306
+	/**
1307
+	 * Calls a php function.
1308
+	 *
1309
+	 * @param string $callback the function to call
1310
+	 * @param array  $params   an array of parameters to send to the function
1311
+	 *
1312
+	 * @return mixed the return value of the called function
1313
+	 */
1314
+	public function arrayMap($callback, array $params)
1315
+	{
1316
+		if ($params[0] === $this) {
1317
+			$addThis = true;
1318
+			array_shift($params);
1319
+		}
1320
+		if ((is_array($params[0]) || ($params[0] instanceof Iterator && $params[0] instanceof ArrayAccess))) {
1321
+			if (empty($params[0])) {
1322
+				return $params[0];
1323
+			}
1324
+
1325
+			// array map
1326
+			$out = array();
1327
+			$cnt = count($params);
1328
+
1329
+			if (isset($addThis)) {
1330
+				array_unshift($params, $this);
1331
+				$items = $params[1];
1332
+				$keys  = array_keys($items);
1333
+
1334
+				if (is_string($callback) === false) {
1335
+					while (($i = array_shift($keys)) !== null) {
1336
+						$out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1337
+					}
1338
+				} elseif ($cnt === 1) {
1339
+					while (($i = array_shift($keys)) !== null) {
1340
+						$out[] = $callback($this, $items[$i]);
1341
+					}
1342
+				} elseif ($cnt === 2) {
1343
+					while (($i = array_shift($keys)) !== null) {
1344
+						$out[] = $callback($this, $items[$i], $params[2]);
1345
+					}
1346
+				} elseif ($cnt === 3) {
1347
+					while (($i = array_shift($keys)) !== null) {
1348
+						$out[] = $callback($this, $items[$i], $params[2], $params[3]);
1349
+					}
1350
+				} else {
1351
+					while (($i = array_shift($keys)) !== null) {
1352
+						$out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1353
+					}
1354
+				}
1355
+			} else {
1356
+				$items = $params[0];
1357
+				$keys  = array_keys($items);
1358
+
1359
+				if (is_string($callback) === false) {
1360
+					while (($i = array_shift($keys)) !== null) {
1361
+						$out[] = call_user_func_array($callback, array($items[$i]) + $params);
1362
+					}
1363
+				} elseif ($cnt === 1) {
1364
+					while (($i = array_shift($keys)) !== null) {
1365
+						$out[] = $callback($items[$i]);
1366
+					}
1367
+				} elseif ($cnt === 2) {
1368
+					while (($i = array_shift($keys)) !== null) {
1369
+						$out[] = $callback($items[$i], $params[1]);
1370
+					}
1371
+				} elseif ($cnt === 3) {
1372
+					while (($i = array_shift($keys)) !== null) {
1373
+						$out[] = $callback($items[$i], $params[1], $params[2]);
1374
+					}
1375
+				} elseif ($cnt === 4) {
1376
+					while (($i = array_shift($keys)) !== null) {
1377
+						$out[] = $callback($items[$i], $params[1], $params[2], $params[3]);
1378
+					}
1379
+				} else {
1380
+					while (($i = array_shift($keys)) !== null) {
1381
+						$out[] = call_user_func_array($callback, array($items[$i]) + $params);
1382
+					}
1383
+				}
1384
+			}
1385
+
1386
+			return $out;
1387
+		} else {
1388
+			return $params[0];
1389
+		}
1390
+	}
1391
+
1392
+	/**
1393
+	 * Reads a variable into the given data array.
1394
+	 *
1395
+	 * @param string $varstr   the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1396
+	 * @param mixed  $data     the data array or object to read from
1397
+	 * @param bool   $safeRead if true, the function will check whether the index exists to prevent any notices from
1398
+	 *                         being output
1399
+	 *
1400
+	 * @return mixed
1401
+	 */
1402
+	public function readVarInto($varstr, $data, $safeRead = false)
1403
+	{
1404
+		if ($data === null) {
1405
+			return null;
1406
+		}
1407
+
1408
+		if (is_array($varstr) === false) {
1409
+			preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1410
+		} else {
1411
+			$m = $varstr;
1412
+		}
1413
+		unset($varstr);
1414
+
1415
+		while (list($k, $sep) = each($m[1])) {
1416
+			if ($sep === '.' || $sep === '[' || $sep === '') {
1417
+				// strip enclosing quotes if present
1418
+				$m[2][$k] = preg_replace('#^(["\']?)(.*?)\1$#', '$2', $m[2][$k]);
1419
+
1420
+				if ((is_array($data) || $data instanceof ArrayAccess) && ($safeRead === false || isset($data[$m[2][$k]]))) {
1421
+					$data = $data[$m[2][$k]];
1422
+				} else {
1423
+					return null;
1424
+				}
1425
+			} else {
1426
+				if (is_object($data) && ($safeRead === false || isset($data->{$m[2][$k]}))) {
1427
+					$data = $data->{$m[2][$k]};
1428
+				} else {
1429
+					return null;
1430
+				}
1431
+			}
1432
+		}
1433
+
1434
+		return $data;
1435
+	}
1436
+
1437
+	/**
1438
+	 * Reads a variable into the parent scope.
1439
+	 *
1440
+	 * @param int    $parentLevels the amount of parent levels to go from the current scope
1441
+	 * @param string $varstr       the variable string, using dwoo variable syntax (i.e.
1442
+	 *                             "var.subvar[subsubvar]->property")
1443
+	 *
1444
+	 * @return mixed
1445
+	 */
1446
+	public function readParentVar($parentLevels, $varstr = null)
1447
+	{
1448
+		$tree = $this->scopeTree;
1449
+		$cur  = $this->data;
1450
+
1451
+		while ($parentLevels -- !== 0) {
1452
+			array_pop($tree);
1453
+		}
1454
+
1455
+		while (($i = array_shift($tree)) !== null) {
1456
+			if (is_object($cur)) {
1457
+				$cur = $cur->{$i};
1458
+			} else {
1459
+				$cur = $cur[$i];
1460
+			}
1461
+		}
1462
+
1463
+		if ($varstr !== null) {
1464
+			return $this->readVarInto($varstr, $cur);
1465
+		} else {
1466
+			return $cur;
1467
+		}
1468
+	}
1469
+
1470
+	/**
1471
+	 * Reads a variable into the current scope.
1472
+	 *
1473
+	 * @param string $varstr the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1474
+	 *
1475
+	 * @return mixed
1476
+	 */
1477
+	public function readVar($varstr)
1478
+	{
1479
+		if (is_array($varstr) === true) {
1480
+			$m = $varstr;
1481
+			unset($varstr);
1482
+		} else {
1483
+			if (strstr($varstr, '.') === false && strstr($varstr, '[') === false && strstr($varstr, '->') === false) {
1484
+				if ($varstr === 'dwoo') {
1485
+					return $this->getGlobals();
1486
+				} elseif ($varstr === '__' || $varstr === '_root') {
1487
+					return $this->data;
1488
+				} elseif ($varstr === '_' || $varstr === '_parent') {
1489
+					$varstr = '.' . $varstr;
1490
+					$tree   = $this->scopeTree;
1491
+					$cur    = $this->data;
1492
+					array_pop($tree);
1493
+
1494
+					while (($i = array_shift($tree)) !== null) {
1495
+						if (is_object($cur)) {
1496
+							$cur = $cur->{$i};
1497
+						} else {
1498
+							$cur = $cur[$i];
1499
+						}
1500
+					}
1501
+
1502
+					return $cur;
1503
+				}
1504
+
1505
+				$cur = $this->scope;
1506
+
1507
+				if (isset($cur[$varstr])) {
1508
+					return $cur[$varstr];
1509
+				} else {
1510
+					return null;
1511
+				}
1512
+			}
1513
+
1514
+			if (substr($varstr, 0, 1) === '.') {
1515
+				$varstr = 'dwoo' . $varstr;
1516
+			}
1517
+
1518
+			preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1519
+		}
1520
+
1521
+		$i = $m[2][0];
1522
+		if ($i === 'dwoo') {
1523
+			$cur = $this->getGlobals();
1524
+			array_shift($m[2]);
1525
+			array_shift($m[1]);
1526
+			switch ($m[2][0]) {
1527
+			case 'get':
1528
+				$cur = $_GET;
1529
+				break;
1530
+			case 'post':
1531
+				$cur = $_POST;
1532
+				break;
1533
+			case 'session':
1534
+				$cur = $_SESSION;
1535
+				break;
1536
+			case 'cookies':
1537
+			case 'cookie':
1538
+				$cur = $_COOKIE;
1539
+				break;
1540
+			case 'server':
1541
+				$cur = $_SERVER;
1542
+				break;
1543
+			case 'env':
1544
+				$cur = $_ENV;
1545
+				break;
1546
+			case 'request':
1547
+				$cur = $_REQUEST;
1548
+				break;
1549
+			case 'const':
1550
+				array_shift($m[2]);
1551
+				if (defined($m[2][0])) {
1552
+					return constant($m[2][0]);
1553
+				} else {
1554
+					return null;
1555
+				}
1556
+			}
1557
+			if ($cur !== $this->getGlobals()) {
1558
+				array_shift($m[2]);
1559
+				array_shift($m[1]);
1560
+			}
1561
+		} elseif ($i === '__' || $i === '_root') {
1562
+			$cur = $this->data;
1563
+			array_shift($m[2]);
1564
+			array_shift($m[1]);
1565
+		} elseif ($i === '_' || $i === '_parent') {
1566
+			$tree = $this->scopeTree;
1567
+			$cur  = $this->data;
1568
+
1569
+			while (true) {
1570
+				array_pop($tree);
1571
+				array_shift($m[2]);
1572
+				array_shift($m[1]);
1573
+				if (current($m[2]) === '_' || current($m[2]) === '_parent') {
1574
+					continue;
1575
+				}
1576
+
1577
+				while (($i = array_shift($tree)) !== null) {
1578
+					if (is_object($cur)) {
1579
+						$cur = $cur->{$i};
1580
+					} else {
1581
+						$cur = $cur[$i];
1582
+					}
1583
+				}
1584
+				break;
1585
+			}
1586
+		} else {
1587
+			$cur = $this->scope;
1588
+		}
1589
+
1590
+		while (list($k, $sep) = each($m[1])) {
1591
+			if ($sep === '.' || $sep === '[' || $sep === '') {
1592
+				if ((is_array($cur) || $cur instanceof ArrayAccess) && isset($cur[$m[2][$k]])) {
1593
+					$cur = $cur[$m[2][$k]];
1594
+				} else {
1595
+					return null;
1596
+				}
1597
+			} elseif ($sep === '->') {
1598
+				if (is_object($cur)) {
1599
+					$cur = $cur->{$m[2][$k]};
1600
+				} else {
1601
+					return null;
1602
+				}
1603
+			} else {
1604
+				return null;
1605
+			}
1606
+		}
1607
+
1608
+		return $cur;
1609
+	}
1610
+
1611
+	/**
1612
+	 * Assign the value to the given variable.
1613
+	 *
1614
+	 * @param mixed  $value the value to assign
1615
+	 * @param string $scope the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1616
+	 *
1617
+	 * @return bool true if assigned correctly or false if a problem occured while parsing the var string
1618
+	 */
1619
+	public function assignInScope($value, $scope)
1620
+	{
1621
+		if (!is_string($scope)) {
1622
+			$this->triggerError('Assignments must be done into strings, (' . gettype($scope) . ') ' . var_export($scope, true) . ' given', E_USER_ERROR);
1623
+		}
1624
+		if (strstr($scope, '.') === false && strstr($scope, '->') === false) {
1625
+			$this->scope[$scope] = $value;
1626
+		} else {
1627
+			// TODO handle _root/_parent scopes ?
1628
+			preg_match_all('#(\[|->|\.)?([^.[\]-]+)\]?#i', $scope, $m);
1629
+
1630
+			$cur  = &$this->scope;
1631
+			$last = array(
1632
+				array_pop($m[1]),
1633
+				array_pop($m[2])
1634
+			);
1635
+
1636
+			while (list($k, $sep) = each($m[1])) {
1637
+				if ($sep === '.' || $sep === '[' || $sep === '') {
1638
+					if (is_array($cur) === false) {
1639
+						$cur = array();
1640
+					}
1641
+					$cur = &$cur[$m[2][$k]];
1642
+				} elseif ($sep === '->') {
1643
+					if (is_object($cur) === false) {
1644
+						$cur = new stdClass();
1645
+					}
1646
+					$cur = &$cur->{$m[2][$k]};
1647
+				} else {
1648
+					return false;
1649
+				}
1650
+			}
1651
+
1652
+			if ($last[0] === '.' || $last[0] === '[' || $last[0] === '') {
1653
+				if (is_array($cur) === false) {
1654
+					$cur = array();
1655
+				}
1656
+				$cur[$last[1]] = $value;
1657
+			} elseif ($last[0] === '->') {
1658
+				if (is_object($cur) === false) {
1659
+					$cur = new stdClass();
1660
+				}
1661
+				$cur->{$last[1]} = $value;
1662
+			} else {
1663
+				return false;
1664
+			}
1665
+		}
1666
+	}
1667
+
1668
+	/**
1669
+	 * Sets the scope to the given scope string or array.
1670
+	 *
1671
+	 * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1672
+	 * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1673
+	 *
1674
+	 * @return array the current scope tree
1675
+	 */
1676
+	public function setScope($scope, $absolute = false)
1677
+	{
1678
+		$old = $this->scopeTree;
1679
+
1680
+		if (is_string($scope) === true) {
1681
+			$scope = explode('.', $scope);
1682
+		}
1683
+
1684
+		if ($absolute === true) {
1685
+			$this->scope     = &$this->data;
1686
+			$this->scopeTree = array();
1687
+		}
1688
+
1689
+		while (($bit = array_shift($scope)) !== null) {
1690
+			if ($bit === '_' || $bit === '_parent') {
1691
+				array_pop($this->scopeTree);
1692
+				$this->scope = &$this->data;
1693
+				$cnt         = count($this->scopeTree);
1694
+				for ($i = 0; $i < $cnt; ++ $i) {
1695
+					$this->scope = &$this->scope[$this->scopeTree[$i]];
1696
+				}
1697
+			} elseif ($bit === '__' || $bit === '_root') {
1698
+				$this->scope     = &$this->data;
1699
+				$this->scopeTree = array();
1700
+			} elseif (isset($this->scope[$bit])) {
1701
+				if ($this->scope instanceof ArrayAccess) {
1702
+					$tmp         = $this->scope[$bit];
1703
+					$this->scope = &$tmp;
1704
+				} else {
1705
+					$this->scope = &$this->scope[$bit];
1706
+				}
1707
+				$this->scopeTree[] = $bit;
1708
+			} else {
1709
+				unset($this->scope);
1710
+				$this->scope = null;
1711
+			}
1712
+		}
1713
+
1714
+		return $old;
1715
+	}
1716
+
1717
+	/**
1718
+	 * Returns the entire data array.
1719
+	 *
1720
+	 * @return array
1721
+	 */
1722
+	public function getData()
1723
+	{
1724
+		return $this->data;
1725
+	}
1726
+
1727
+	/**
1728
+	 * Sets a return value for the currently running template.
1729
+	 *
1730
+	 * @param string $name  var name
1731
+	 * @param mixed  $value var value
1732
+	 *
1733
+	 * @return void
1734
+	 */
1735
+	public function setReturnValue($name, $value)
1736
+	{
1737
+		$this->returnData[$name] = $value;
1738
+	}
1739
+
1740
+	/**
1741
+	 * Retrieves the return values set by the template.
1742
+	 *
1743
+	 * @return array
1744
+	 */
1745
+	public function getReturnValues()
1746
+	{
1747
+		return $this->returnData;
1748
+	}
1749
+
1750
+	/**
1751
+	 * Returns a reference to the current scope.
1752
+	 *
1753
+	 * @return mixed
1754
+	 */
1755
+	public function &getScope()
1756
+	{
1757
+		return $this->scope;
1758
+	}
1759
+
1760
+	/**
1761
+	 * Redirects all calls to unexisting to plugin proxy.
1762
+	 *
1763
+	 * @param string $method the method name
1764
+	 * @param array  $args   array of arguments
1765
+	 *
1766
+	 * @return mixed
1767
+	 * @throws Exception
1768
+	 */
1769
+	public function __call($method, $args)
1770
+	{
1771
+		$proxy = $this->getPluginProxy();
1772
+		if (!$proxy) {
1773
+			throw new Exception('Call to undefined method ' . __CLASS__ . '::' . $method . '()');
1774
+		}
1775
+
1776
+		return call_user_func_array($proxy->getCallback($method), $args);
1777
+	}
1778
+
1779
+	/**
1780
+	 * Convert plugin name from `auto_escape` to `AutoEscape`.
1781
+	 * @param string $input
1782
+	 * @param string $separator
1783
+	 *
1784
+	 * @return mixed
1785
+	 */
1786
+	public static function toCamelCase($input, $separator = '_')
1787
+	{
1788
+		return join(array_map('ucfirst', explode($separator, $input)));
1789
+
1790
+		// TODO >= PHP5.4.32
1791
+		//return str_replace($separator, '', ucwords($input, $separator));
1792
+	}
1793 1793
 }
Please login to merge, or discard this patch.
lib/Dwoo/Filter.php 1 patch
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -23,30 +23,30 @@
 block discarded – undo
23 23
  */
24 24
 abstract class Filter
25 25
 {
26
-    /**
27
-     * The dwoo instance that runs this filter.
28
-     *
29
-     * @var Core
30
-     */
31
-    protected $dwoo;
26
+	/**
27
+	 * The dwoo instance that runs this filter.
28
+	 *
29
+	 * @var Core
30
+	 */
31
+	protected $dwoo;
32 32
 
33
-    /**
34
-     * Constructor, if you override it, call parent::__construct($dwoo); or assign
35
-     * the dwoo instance yourself if you need it.
36
-     *
37
-     * @param Core $dwoo the dwoo instance that runs this plugin
38
-     */
39
-    public function __construct(Core $dwoo)
40
-    {
41
-        $this->dwoo = $dwoo;
42
-    }
33
+	/**
34
+	 * Constructor, if you override it, call parent::__construct($dwoo); or assign
35
+	 * the dwoo instance yourself if you need it.
36
+	 *
37
+	 * @param Core $dwoo the dwoo instance that runs this plugin
38
+	 */
39
+	public function __construct(Core $dwoo)
40
+	{
41
+		$this->dwoo = $dwoo;
42
+	}
43 43
 
44
-    /**
45
-     * Processes the input and returns it filtered.
46
-     *
47
-     * @param string $input the template to process
48
-     *
49
-     * @return string
50
-     */
51
-    abstract public function process($input);
44
+	/**
45
+	 * Processes the input and returns it filtered.
46
+	 *
47
+	 * @param string $input the template to process
48
+	 *
49
+	 * @return string
50
+	 */
51
+	abstract public function process($input);
52 52
 }
Please login to merge, or discard this patch.
lib/Dwoo/ILoader.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -23,15 +23,15 @@
 block discarded – undo
23 23
  */
24 24
 interface ILoader
25 25
 {
26
-    /**
27
-     * Loads a plugin file.
28
-     * the second parameter is used to avoid permanent rehashing when using php functions,
29
-     * however this means that if you have add a plugin that overrides a php function you have
30
-     * to delete the classpath.cache file(s) by hand to force a rehash of the plugins
31
-     *
32
-     * @param string $class       the plugin name, without the `Plugin` prefix
33
-     * @param bool   $forceRehash if true, the class path caches will be rebuilt if the plugin is not found, in case it
34
-     *                            has just been added, defaults to true
35
-     */
36
-    public function loadPlugin($class, $forceRehash = true);
26
+	/**
27
+	 * Loads a plugin file.
28
+	 * the second parameter is used to avoid permanent rehashing when using php functions,
29
+	 * however this means that if you have add a plugin that overrides a php function you have
30
+	 * to delete the classpath.cache file(s) by hand to force a rehash of the plugins
31
+	 *
32
+	 * @param string $class       the plugin name, without the `Plugin` prefix
33
+	 * @param bool   $forceRehash if true, the class path caches will be rebuilt if the plugin is not found, in case it
34
+	 *                            has just been added, defaults to true
35
+	 */
36
+	public function loadPlugin($class, $forceRehash = true);
37 37
 }
Please login to merge, or discard this patch.
lib/Dwoo/ICompilable.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -26,6 +26,6 @@
 block discarded – undo
26 26
  */
27 27
 interface ICompilable
28 28
 {
29
-    // this replaces the process function
30
-    //public static function compile(Compiler $compiler, $arg, $arg, ...);
29
+	// this replaces the process function
30
+	//public static function compile(Compiler $compiler, $arg, $arg, ...);
31 31
 }
Please login to merge, or discard this patch.