Completed
Branch master (b65d76)
by David
04:29
created
lib/Dwoo/Adapters/ZendFramework/PluginProxy.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -46,7 +46,7 @@
 block discarded – undo
46 46
     /**
47 47
      * Dwoo_Adapters_ZendFramework_PluginProxy's constructor.
48 48
      *
49
-     * @param Zend_View_Interface $view
49
+     * @param Dwoo_Adapters_ZendFramework_View $view
50 50
      */
51 51
     public function __construct(Zend_View_Interface $view)
52 52
     {
Please login to merge, or discard this patch.
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -36,88 +36,88 @@
 block discarded – undo
36 36
  */
37 37
 class Dwoo_Adapters_ZendFramework_PluginProxy implements IPluginProxy
38 38
 {
39
-    /**
40
-     * reference to the zend view owning this proxy.
41
-     *
42
-     * @var Zend_View_Interface
43
-     */
44
-    public $view;
39
+	/**
40
+	 * reference to the zend view owning this proxy.
41
+	 *
42
+	 * @var Zend_View_Interface
43
+	 */
44
+	public $view;
45 45
 
46
-    /**
47
-     * Dwoo_Adapters_ZendFramework_PluginProxy's constructor.
48
-     *
49
-     * @param Zend_View_Interface $view
50
-     */
51
-    public function __construct(Zend_View_Interface $view)
52
-    {
53
-        $this->view = $view;
54
-    }
46
+	/**
47
+	 * Dwoo_Adapters_ZendFramework_PluginProxy's constructor.
48
+	 *
49
+	 * @param Zend_View_Interface $view
50
+	 */
51
+	public function __construct(Zend_View_Interface $view)
52
+	{
53
+		$this->view = $view;
54
+	}
55 55
 
56
-    /**
57
-     * Called from Dwoo_Compiler to check if the requested plugin is available.
58
-     *
59
-     * @param string $name
60
-     *
61
-     * @return bool
62
-     */
63
-    public function handles($name)
64
-    {
65
-        try {
66
-            $this->view->getHelper($name);
67
-        } catch (Zend_Loader_PluginLoader_Exception $e) {
68
-            return false;
69
-        }
56
+	/**
57
+	 * Called from Dwoo_Compiler to check if the requested plugin is available.
58
+	 *
59
+	 * @param string $name
60
+	 *
61
+	 * @return bool
62
+	 */
63
+	public function handles($name)
64
+	{
65
+		try {
66
+			$this->view->getHelper($name);
67
+		} catch (Zend_Loader_PluginLoader_Exception $e) {
68
+			return false;
69
+		}
70 70
 
71
-        return true;
72
-    }
71
+		return true;
72
+	}
73 73
 
74
-    /**
75
-     * returns the code (as a string) to call the plugin
76
-     * (this will be executed at runtime inside the Dwoo class).
77
-     *
78
-     * @param string $name   the plugin name
79
-     * @param array  $params a parameter array, array key "*" is the rest array
80
-     *
81
-     * @return string
82
-     */
83
-    public function getCode($name, $params)
84
-    {
85
-        return '$this->getPluginProxy()->view->'.$name.'('.Compiler::implode_r($params).')';
86
-    }
74
+	/**
75
+	 * returns the code (as a string) to call the plugin
76
+	 * (this will be executed at runtime inside the Dwoo class).
77
+	 *
78
+	 * @param string $name   the plugin name
79
+	 * @param array  $params a parameter array, array key "*" is the rest array
80
+	 *
81
+	 * @return string
82
+	 */
83
+	public function getCode($name, $params)
84
+	{
85
+		return '$this->getPluginProxy()->view->'.$name.'('.Compiler::implode_r($params).')';
86
+	}
87 87
 
88
-    /**
89
-     * returns a callback to the plugin, this is used with the reflection API to
90
-     * find out about the plugin's parameter names etc.
91
-     *
92
-     * should you need a rest array (i.e. for ZendFramework helpers) without the
93
-     * possibility to edit the plugin's code, you can provide a callback to some
94
-     * other function with the correct parameter signature, i.e. :
95
-     * <code>
96
-     * return array($this, "callbackHelper");
97
-     * // and callbackHelper would be as such:
98
-     * public function callbackHelper(array $rest=array()){}
99
-     * </code>
100
-     *
101
-     * @param string $name the plugin name
102
-     *
103
-     * @return callback
104
-     */
105
-    public function getCallback($name)
106
-    {
107
-        return array($this->view->getHelper($name), $name);
108
-    }
88
+	/**
89
+	 * returns a callback to the plugin, this is used with the reflection API to
90
+	 * find out about the plugin's parameter names etc.
91
+	 *
92
+	 * should you need a rest array (i.e. for ZendFramework helpers) without the
93
+	 * possibility to edit the plugin's code, you can provide a callback to some
94
+	 * other function with the correct parameter signature, i.e. :
95
+	 * <code>
96
+	 * return array($this, "callbackHelper");
97
+	 * // and callbackHelper would be as such:
98
+	 * public function callbackHelper(array $rest=array()){}
99
+	 * </code>
100
+	 *
101
+	 * @param string $name the plugin name
102
+	 *
103
+	 * @return callback
104
+	 */
105
+	public function getCallback($name)
106
+	{
107
+		return array($this->view->getHelper($name), $name);
108
+	}
109 109
 
110
-    /**
111
-     * returns some code that will check if the plugin is loaded and if not load it
112
-     * this is optional, if your plugins are autoloaded or whatever, just return an
113
-     * empty string.
114
-     *
115
-     * @param string $name the plugin name
116
-     *
117
-     * @return string
118
-     */
119
-    public function getLoader($name)
120
-    {
121
-        return '';
122
-    }
110
+	/**
111
+	 * returns some code that will check if the plugin is loaded and if not load it
112
+	 * this is optional, if your plugins are autoloaded or whatever, just return an
113
+	 * empty string.
114
+	 *
115
+	 * @param string $name the plugin name
116
+	 *
117
+	 * @return string
118
+	 */
119
+	public function getLoader($name)
120
+	{
121
+		return '';
122
+	}
123 123
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/ZendFramework/View.php 2 patches
Doc Comments   -2 removed lines patch added patch discarded remove patch
@@ -83,7 +83,6 @@  discard block
 block discarded – undo
83 83
      *  - type class name or object for engine, dataProvider or compiler
84 84
      *  - any set* method (compileDir for setCompileDir ...)
85 85
      *
86
-     * @param array $options
87 86
      *
88 87
      * @return Dwoo_Adapters_ZendFramework_View
89 88
      */
@@ -437,7 +436,6 @@  discard block
 block discarded – undo
437 436
      * Processes a view script and outputs it. Output is then
438 437
      * passed through filters.
439 438
      *
440
-     * @param string $name The script script name to process
441 439
      *
442 440
      * @return string The script output
443 441
      */
Please login to merge, or discard this patch.
Indentation   +503 added lines, -503 removed lines patch added patch discarded remove patch
@@ -16,507 +16,507 @@
 block discarded – undo
16 16
  */
17 17
 class Dwoo_Adapters_ZendFramework_View extends Zend_View_Abstract
18 18
 {
19
-    /**
20
-     * @var Core
21
-     */
22
-    protected $_engine = null;
23
-
24
-    /**
25
-     * @var Dwoo_Data
26
-     */
27
-    protected $_dataProvider = null;
28
-
29
-    /**
30
-     * @var Dwoo_Compiler
31
-     */
32
-    protected $_compiler = null;
33
-
34
-    /**
35
-     * Changing Filter's scope to play nicely.
36
-     *
37
-     * @var array
38
-     */
39
-    protected $_filter = array();
40
-
41
-    /**
42
-     * @var string
43
-     */
44
-    protected $_templateFileClass = 'Dwoo_Template_File';
45
-
46
-    /**
47
-     * @var array
48
-     */
49
-    protected $_templateFileSettings = array();
50
-
51
-    /**
52
-     * @var Dwoo_IPluginProxy
53
-     */
54
-    protected $_pluginProxy = null;
55
-
56
-    /**
57
-     * Constructor method.
58
-     * See setOptions for $opt details.
59
-     *
60
-     * @see setOptions
61
-     *
62
-     * @param array|Zend_Config List of options or Zend_Config instance
63
-     */
64
-    public function __construct($opt = array())
65
-    {
66
-        if (is_array($opt)) {
67
-            $this->setOptions($opt);
68
-        } elseif ($opt instanceof Zend_Config) {
69
-            $this->setConfig($opt);
70
-        }
71
-
72
-        $this->init();
73
-    }
74
-
75
-    /**
76
-     * Set object state from options array
77
-     *  - engine        = engine class name|engine object|array of options for engine
78
-     *  - dataProvider  = data provider class name|data provider object|array of options for data provider
79
-     *  - compiler      = compiler class name|compiler object|array of options for compiler
80
-     *  - templateFile  =.
81
-     *
82
-     *  Array of options:
83
-     *  - type class name or object for engine, dataProvider or compiler
84
-     *  - any set* method (compileDir for setCompileDir ...)
85
-     *
86
-     * @param array $options
87
-     *
88
-     * @return Dwoo_Adapters_ZendFramework_View
89
-     */
90
-    public function setOptions(array $opt = array())
91
-    {
92
-        // Making sure that everything is loaded.
93
-        $classes = array('engine', 'dataProvider', 'compiler');
94
-
95
-        // Setting options to Dwoo objects...
96
-        foreach ($opt as $type => $settings) {
97
-            if (!method_exists($this, 'set'.$type)) {
98
-                throw new Dwoo_Exception("Unknown type $type");
99
-            }
100
-
101
-            if (is_string($settings) || is_object($settings)) {
102
-                call_user_func(array($this, 'set'.$type), $settings);
103
-            } elseif (is_array($settings)) {
104
-                // Set requested class
105
-                if (array_key_exists('type', $settings)) {
106
-                    call_user_func(array($this, 'set'.$type), $settings['type']);
107
-                }
108
-
109
-                if (in_array($type, $classes)) {
110
-                    // Call get so that the class is initialized
111
-                    $rel = call_user_func(array($this, 'get'.$type));
112
-
113
-                    // Call set*() methods so that all the settings are set.
114
-                    foreach ($settings as $method => $value) {
115
-                        if (method_exists($rel, 'set'.$method)) {
116
-                            call_user_func(array($rel, 'set'.$method), $value);
117
-                        }
118
-                    }
119
-                } elseif ('templateFile' == $type) {
120
-                    // Remember the settings for the templateFile
121
-                    $this->_templateFileSettings = $settings;
122
-                }
123
-            }
124
-        }
125
-    }
126
-
127
-    /**
128
-     * Set object state from Zend_Config object.
129
-     *
130
-     * @param Zend_Config $config
131
-     *
132
-     * @return Dwoo_Adapters_ZendFramework_View
133
-     */
134
-    public function setConfig(Zend_Config $config)
135
-    {
136
-        return $this->setOptions($config->toArray());
137
-    }
138
-
139
-    /**
140
-     * Called before template rendering.
141
-     *
142
-     * Binds plugin proxy to the Dwoo.
143
-     *
144
-     * @see Dwoo_Adapters_ZendFramework_View::getPluginProxy();
145
-     * @see Dwoo_Core::setPluginProxy();
146
-     */
147
-    protected function preRender()
148
-    {
149
-        $this->getEngine()->setPluginProxy($this->getPluginProxy());
150
-    }
151
-
152
-    /**
153
-     * Wraper for Dwoo_Data::__set()
154
-     * allows to assign variables using the object syntax.
155
-     *
156
-     * @see Dwoo_Data::__set()
157
-     *
158
-     * @param string $name  the variable name
159
-     * @param string $value the value to assign to it
160
-     */
161
-    public function __set($name, $value)
162
-    {
163
-        $this->getDataProvider()->__set($name, $value);
164
-    }
165
-
166
-    /**
167
-     * Sraper for Dwoo_Data::__get() allows to read variables using the object
168
-     * syntax.
169
-     *
170
-     * @see Dwoo_Data::__get()
171
-     *
172
-     * @param string $name the variable name
173
-     *
174
-     * @return mixed
175
-     */
176
-    public function __get($name)
177
-    {
178
-        return $this->getDataProvider()->__get($name);
179
-    }
180
-
181
-    /**
182
-     * Wraper for Dwoo_Data::__isset()
183
-     * supports calls to isset($dwooData->var).
184
-     *
185
-     * @see Dwoo_Data::__isset()
186
-     *
187
-     * @param string $name the variable name
188
-     */
189
-    public function __isset($name)
190
-    {
191
-        return $this->getDataProvider()->__isset($name);
192
-    }
193
-
194
-    /**
195
-     * Wraper for Dwoo_Data::_unset()
196
-     * supports unsetting variables using the object syntax.
197
-     *
198
-     * @see Dwoo_Data::__unset()
199
-     *
200
-     * @param string $name the variable name
201
-     */
202
-    public function __unset($name)
203
-    {
204
-        $this->getDataProvider()->__unset($name);
205
-    }
206
-
207
-    /**
208
-     * Catches clone request and clones data provider.
209
-     */
210
-    public function __clone()
211
-    {
212
-        $this->setDataProvider(clone $this->getDataProvider());
213
-    }
214
-
215
-    /**
216
-     * Returns plugin proxy interface.
217
-     *
218
-     * @return Dwoo_IPluginProxy
219
-     */
220
-    public function getPluginProxy()
221
-    {
222
-        if (!$this->_pluginProxy) {
223
-            $this->_pluginProxy = new Dwoo_Adapters_ZendFramework_PluginProxy($this);
224
-        }
225
-
226
-        return $this->_pluginProxy;
227
-    }
228
-
229
-    /**
230
-     * Sets plugin proxy.
231
-     *
232
-     * @param Dwoo_IPluginProxy
233
-     *
234
-     * @return Dwoo_Adapters_ZendFramework_View
235
-     */
236
-    public function setPluginProxy(Dwoo_IPluginProxy $pluginProxy)
237
-    {
238
-        $this->_pluginProxy = $pluginProxy;
239
-
240
-        return $this;
241
-    }
242
-
243
-    /**
244
-     * Sets template engine.
245
-     *
246
-     * @param string|Dwoo Object or name of the class
247
-     */
248
-    public function setEngine($engine)
249
-    {
250
-        // if param given as an object
251
-        if ($engine instanceof Dwoo_Core) {
252
-            $this->_engine = $engine;
253
-        } elseif (is_subclass_of($engine, 'Dwoo') || 'Dwoo' === $engine) {
254
-            $this->_engine = new $engine();
255
-        } else {
256
-            throw new Dwoo_Exception('Custom engine must be a subclass of Dwoo');
257
-        }
258
-    }
259
-
260
-    /**
261
-     * Return the Dwoo template engine object.
262
-     *
263
-     * @return Dwoo
264
-     */
265
-    public function getEngine()
266
-    {
267
-        if (null === $this->_engine) {
268
-            $this->_engine = new Dwoo_Adapters_ZendFramework_Dwoo();
269
-        }
270
-
271
-        return $this->_engine;
272
-    }
273
-
274
-    /**
275
-     * Sets Dwoo data object.
276
-     *
277
-     * @param string|Dwoo_Data Object or name of the class
278
-     */
279
-    public function setDataProvider($data)
280
-    {
281
-        if ($data instanceof Dwoo_IDataProvider) {
282
-            $this->_dataProvider = $data;
283
-        } elseif (is_subclass_of($data, 'Dwoo_Data') || 'Dwoo_Data' == $data) {
284
-            $this->_dataProvider = new $data();
285
-        } else {
286
-            throw new Dwoo_Exception('Custom data provider must be a subclass of Dwoo_Data or instance of Dwoo_IDataProvider');
287
-        }
288
-    }
289
-
290
-    /**
291
-     * Return the Dwoo data object.
292
-     *
293
-     * @return Dwoo_Data
294
-     */
295
-    public function getDataProvider()
296
-    {
297
-        if (null === $this->_dataProvider) {
298
-            $this->_dataProvider = new Dwoo_Data();
299
-
300
-            // Satisfy Zend_View_Abstract wishes to access this unexisting property
301
-            // by setting it to empty array (see Zend_View_Abstract::_filter)
302
-            $this->_dataProvider->_filter = array();
303
-        }
304
-
305
-        return $this->_dataProvider;
306
-    }
307
-
308
-    /**
309
-     * Sets Dwoo compiler.
310
-     *
311
-     * @param string|Dwoo_Compiler Object or name of the class
312
-     */
313
-    public function setCompiler($compiler)
314
-    {
315
-
316
-        // if param given as an object
317
-        if ($compiler instanceof Dwoo_ICompiler) {
318
-            $this->_compiler = $compiler;
319
-        }
320
-        // if param given as a string
321
-        elseif (is_subclass_of($compiler, 'Dwoo_Compiler') || 'Dwoo_Compiler' == $compiler) {
322
-            $this->_compiler = new $compiler();
323
-        } else {
324
-            throw new Dwoo_Exception('Custom compiler must be a subclass of Dwoo_Compiler or instance of Dwoo_ICompiler');
325
-        }
326
-    }
327
-
328
-    /**
329
-     * Return the Dwoo compiler object.
330
-     *
331
-     * @return Dwoo_Compiler
332
-     */
333
-    public function getCompiler()
334
-    {
335
-        if (null === $this->_compiler) {
336
-            $this->_compiler = Dwoo_Compiler::compilerFactory();
337
-        }
338
-
339
-        return $this->_compiler;
340
-    }
341
-
342
-    /**
343
-     * Initializes Dwoo_ITemplate type of class and sets properties from _templateFileSettings.
344
-     *
345
-     * @param string Dwoo_ITemplate $template
346
-     *
347
-     * @return Dwoo_ITemplate
348
-     */
349
-    public function getTemplateFile($template)
350
-    {
351
-        $templateFileClass = $this->_templateFileClass;
352
-
353
-        $dwooTemplateFile = new $templateFileClass($template);
354
-
355
-        if (!($dwooTemplateFile instanceof Dwoo_ITemplate)) {
356
-            throw new Dwoo_Exception('Custom templateFile class must be a subclass of Dwoo_ITemplate');
357
-        }
358
-
359
-        foreach ($this->_templateFileSettings as $method => $value) {
360
-            if (method_exists($dwooTemplateFile, 'set'.$method)) {
361
-                call_user_func(array($dwooTemplateFile, 'set'.$method), $value);
362
-            }
363
-        }
364
-
365
-        return $dwooTemplateFile;
366
-    }
367
-
368
-    /**
369
-     * Dwoo_ITemplate type of class.
370
-     *
371
-     * @param string Name of the class
372
-     */
373
-    public function setTemplateFile($tempateFileClass)
374
-    {
375
-        $this->_templateFileClass = $tempateFileClass;
376
-    }
377
-
378
-    /**
379
-     * Passes data to Dwoo_Data object.
380
-     *
381
-     * @see Dwoo_Data::assign()
382
-     *
383
-     * @param array|string $name
384
-     * @param mixed        $val
385
-     *
386
-     * @return Dwoo_Adapters_ZendFramework_View
387
-     */
388
-    public function assign($name, $val = null)
389
-    {
390
-        $this->getDataProvider()->assign($name, $val);
391
-
392
-        return $this;
393
-    }
394
-
395
-    /**
396
-     * Return list of all assigned variables.
397
-     *
398
-     * @return array
399
-     */
400
-    public function getVars()
401
-    {
402
-        return $this->getDataProvider()->getData();
403
-    }
404
-
405
-    /**
406
-     * Clear all assigned variables.
407
-     *
408
-     * Clears all variables assigned to Zend_View either via {@link assign()} or
409
-     * property overloading ({@link __get()}/{@link __set()}).
410
-     *
411
-     * @return Dwoo_Adapters_ZendFramework_View
412
-     */
413
-    public function clearVars()
414
-    {
415
-        $this->getDataProvider()->clear();
416
-
417
-        return $this;
418
-    }
419
-
420
-    /**
421
-     * Wraper for parent's render method so preRender method
422
-     * can be called (that will bind the plugin proxy to the
423
-     * engine.
424
-     *
425
-     * @see Zend_View_Abstract::render
426
-     *
427
-     * @return string The script output
428
-     */
429
-    public function render($name)
430
-    {
431
-        $this->preRender();
432
-
433
-        return parent::render($name);
434
-    }
435
-
436
-    /**
437
-     * Processes a view script and outputs it. Output is then
438
-     * passed through filters.
439
-     *
440
-     * @param string $name The script script name to process
441
-     *
442
-     * @return string The script output
443
-     */
444
-    public function _run()
445
-    {
446
-        echo $this->_engine->get(
447
-            $this->getTemplateFile(func_get_arg(0)),
448
-            $this->getDataProvider(),
449
-            $this->getCompiler()
450
-        );
451
-    }
452
-
453
-    /**
454
-     * Add plugin path.
455
-     *
456
-     * @param string $dir Directory
457
-     *
458
-     * @return Dwoo_Adapters_ZendFramework_View
459
-     */
460
-    public function addPluginDir($dir)
461
-    {
462
-        $this->getEngine()->getLoader()->addDirectory($dir);
463
-
464
-        return $this;
465
-    }
466
-
467
-    /**
468
-     * Set compile path.
469
-     *
470
-     * @param string $dir Directory
471
-     *
472
-     * @return Dwoo_Adapters_ZendFramework_View
473
-     */
474
-    public function setCompileDir($dir)
475
-    {
476
-        $this->getEngine()->setCompileDir($dir);
477
-
478
-        return $this;
479
-    }
480
-
481
-    /**
482
-     * Set cache path.
483
-     *
484
-     * @param string $dir Directory
485
-     *
486
-     * @return Dwoo_Adapters_ZendFramework_View
487
-     */
488
-    public function setCacheDir($dir)
489
-    {
490
-        $this->getEngine()->setCacheDir($dir);
491
-
492
-        return $this;
493
-    }
494
-
495
-    /**
496
-     * Set cache lifetime.
497
-     *
498
-     * @param string $seconds Lifetime in seconds
499
-     *
500
-     * @return Dwoo_Adapters_ZendFramework_View
501
-     */
502
-    public function setCacheLifetime($seconds)
503
-    {
504
-        $this->getEngine()->setCacheTime($seconds);
505
-
506
-        return $this;
507
-    }
508
-
509
-    /**
510
-     * Set charset.
511
-     *
512
-     * @param string $charset
513
-     *
514
-     * @return Dwoo_Adapters_ZendFramework_View
515
-     */
516
-    public function setCharset($charset)
517
-    {
518
-        $this->_engine->setCharset($charset);
519
-
520
-        return $this;
521
-    }
19
+	/**
20
+	 * @var Core
21
+	 */
22
+	protected $_engine = null;
23
+
24
+	/**
25
+	 * @var Dwoo_Data
26
+	 */
27
+	protected $_dataProvider = null;
28
+
29
+	/**
30
+	 * @var Dwoo_Compiler
31
+	 */
32
+	protected $_compiler = null;
33
+
34
+	/**
35
+	 * Changing Filter's scope to play nicely.
36
+	 *
37
+	 * @var array
38
+	 */
39
+	protected $_filter = array();
40
+
41
+	/**
42
+	 * @var string
43
+	 */
44
+	protected $_templateFileClass = 'Dwoo_Template_File';
45
+
46
+	/**
47
+	 * @var array
48
+	 */
49
+	protected $_templateFileSettings = array();
50
+
51
+	/**
52
+	 * @var Dwoo_IPluginProxy
53
+	 */
54
+	protected $_pluginProxy = null;
55
+
56
+	/**
57
+	 * Constructor method.
58
+	 * See setOptions for $opt details.
59
+	 *
60
+	 * @see setOptions
61
+	 *
62
+	 * @param array|Zend_Config List of options or Zend_Config instance
63
+	 */
64
+	public function __construct($opt = array())
65
+	{
66
+		if (is_array($opt)) {
67
+			$this->setOptions($opt);
68
+		} elseif ($opt instanceof Zend_Config) {
69
+			$this->setConfig($opt);
70
+		}
71
+
72
+		$this->init();
73
+	}
74
+
75
+	/**
76
+	 * Set object state from options array
77
+	 *  - engine        = engine class name|engine object|array of options for engine
78
+	 *  - dataProvider  = data provider class name|data provider object|array of options for data provider
79
+	 *  - compiler      = compiler class name|compiler object|array of options for compiler
80
+	 *  - templateFile  =.
81
+	 *
82
+	 *  Array of options:
83
+	 *  - type class name or object for engine, dataProvider or compiler
84
+	 *  - any set* method (compileDir for setCompileDir ...)
85
+	 *
86
+	 * @param array $options
87
+	 *
88
+	 * @return Dwoo_Adapters_ZendFramework_View
89
+	 */
90
+	public function setOptions(array $opt = array())
91
+	{
92
+		// Making sure that everything is loaded.
93
+		$classes = array('engine', 'dataProvider', 'compiler');
94
+
95
+		// Setting options to Dwoo objects...
96
+		foreach ($opt as $type => $settings) {
97
+			if (!method_exists($this, 'set'.$type)) {
98
+				throw new Dwoo_Exception("Unknown type $type");
99
+			}
100
+
101
+			if (is_string($settings) || is_object($settings)) {
102
+				call_user_func(array($this, 'set'.$type), $settings);
103
+			} elseif (is_array($settings)) {
104
+				// Set requested class
105
+				if (array_key_exists('type', $settings)) {
106
+					call_user_func(array($this, 'set'.$type), $settings['type']);
107
+				}
108
+
109
+				if (in_array($type, $classes)) {
110
+					// Call get so that the class is initialized
111
+					$rel = call_user_func(array($this, 'get'.$type));
112
+
113
+					// Call set*() methods so that all the settings are set.
114
+					foreach ($settings as $method => $value) {
115
+						if (method_exists($rel, 'set'.$method)) {
116
+							call_user_func(array($rel, 'set'.$method), $value);
117
+						}
118
+					}
119
+				} elseif ('templateFile' == $type) {
120
+					// Remember the settings for the templateFile
121
+					$this->_templateFileSettings = $settings;
122
+				}
123
+			}
124
+		}
125
+	}
126
+
127
+	/**
128
+	 * Set object state from Zend_Config object.
129
+	 *
130
+	 * @param Zend_Config $config
131
+	 *
132
+	 * @return Dwoo_Adapters_ZendFramework_View
133
+	 */
134
+	public function setConfig(Zend_Config $config)
135
+	{
136
+		return $this->setOptions($config->toArray());
137
+	}
138
+
139
+	/**
140
+	 * Called before template rendering.
141
+	 *
142
+	 * Binds plugin proxy to the Dwoo.
143
+	 *
144
+	 * @see Dwoo_Adapters_ZendFramework_View::getPluginProxy();
145
+	 * @see Dwoo_Core::setPluginProxy();
146
+	 */
147
+	protected function preRender()
148
+	{
149
+		$this->getEngine()->setPluginProxy($this->getPluginProxy());
150
+	}
151
+
152
+	/**
153
+	 * Wraper for Dwoo_Data::__set()
154
+	 * allows to assign variables using the object syntax.
155
+	 *
156
+	 * @see Dwoo_Data::__set()
157
+	 *
158
+	 * @param string $name  the variable name
159
+	 * @param string $value the value to assign to it
160
+	 */
161
+	public function __set($name, $value)
162
+	{
163
+		$this->getDataProvider()->__set($name, $value);
164
+	}
165
+
166
+	/**
167
+	 * Sraper for Dwoo_Data::__get() allows to read variables using the object
168
+	 * syntax.
169
+	 *
170
+	 * @see Dwoo_Data::__get()
171
+	 *
172
+	 * @param string $name the variable name
173
+	 *
174
+	 * @return mixed
175
+	 */
176
+	public function __get($name)
177
+	{
178
+		return $this->getDataProvider()->__get($name);
179
+	}
180
+
181
+	/**
182
+	 * Wraper for Dwoo_Data::__isset()
183
+	 * supports calls to isset($dwooData->var).
184
+	 *
185
+	 * @see Dwoo_Data::__isset()
186
+	 *
187
+	 * @param string $name the variable name
188
+	 */
189
+	public function __isset($name)
190
+	{
191
+		return $this->getDataProvider()->__isset($name);
192
+	}
193
+
194
+	/**
195
+	 * Wraper for Dwoo_Data::_unset()
196
+	 * supports unsetting variables using the object syntax.
197
+	 *
198
+	 * @see Dwoo_Data::__unset()
199
+	 *
200
+	 * @param string $name the variable name
201
+	 */
202
+	public function __unset($name)
203
+	{
204
+		$this->getDataProvider()->__unset($name);
205
+	}
206
+
207
+	/**
208
+	 * Catches clone request and clones data provider.
209
+	 */
210
+	public function __clone()
211
+	{
212
+		$this->setDataProvider(clone $this->getDataProvider());
213
+	}
214
+
215
+	/**
216
+	 * Returns plugin proxy interface.
217
+	 *
218
+	 * @return Dwoo_IPluginProxy
219
+	 */
220
+	public function getPluginProxy()
221
+	{
222
+		if (!$this->_pluginProxy) {
223
+			$this->_pluginProxy = new Dwoo_Adapters_ZendFramework_PluginProxy($this);
224
+		}
225
+
226
+		return $this->_pluginProxy;
227
+	}
228
+
229
+	/**
230
+	 * Sets plugin proxy.
231
+	 *
232
+	 * @param Dwoo_IPluginProxy
233
+	 *
234
+	 * @return Dwoo_Adapters_ZendFramework_View
235
+	 */
236
+	public function setPluginProxy(Dwoo_IPluginProxy $pluginProxy)
237
+	{
238
+		$this->_pluginProxy = $pluginProxy;
239
+
240
+		return $this;
241
+	}
242
+
243
+	/**
244
+	 * Sets template engine.
245
+	 *
246
+	 * @param string|Dwoo Object or name of the class
247
+	 */
248
+	public function setEngine($engine)
249
+	{
250
+		// if param given as an object
251
+		if ($engine instanceof Dwoo_Core) {
252
+			$this->_engine = $engine;
253
+		} elseif (is_subclass_of($engine, 'Dwoo') || 'Dwoo' === $engine) {
254
+			$this->_engine = new $engine();
255
+		} else {
256
+			throw new Dwoo_Exception('Custom engine must be a subclass of Dwoo');
257
+		}
258
+	}
259
+
260
+	/**
261
+	 * Return the Dwoo template engine object.
262
+	 *
263
+	 * @return Dwoo
264
+	 */
265
+	public function getEngine()
266
+	{
267
+		if (null === $this->_engine) {
268
+			$this->_engine = new Dwoo_Adapters_ZendFramework_Dwoo();
269
+		}
270
+
271
+		return $this->_engine;
272
+	}
273
+
274
+	/**
275
+	 * Sets Dwoo data object.
276
+	 *
277
+	 * @param string|Dwoo_Data Object or name of the class
278
+	 */
279
+	public function setDataProvider($data)
280
+	{
281
+		if ($data instanceof Dwoo_IDataProvider) {
282
+			$this->_dataProvider = $data;
283
+		} elseif (is_subclass_of($data, 'Dwoo_Data') || 'Dwoo_Data' == $data) {
284
+			$this->_dataProvider = new $data();
285
+		} else {
286
+			throw new Dwoo_Exception('Custom data provider must be a subclass of Dwoo_Data or instance of Dwoo_IDataProvider');
287
+		}
288
+	}
289
+
290
+	/**
291
+	 * Return the Dwoo data object.
292
+	 *
293
+	 * @return Dwoo_Data
294
+	 */
295
+	public function getDataProvider()
296
+	{
297
+		if (null === $this->_dataProvider) {
298
+			$this->_dataProvider = new Dwoo_Data();
299
+
300
+			// Satisfy Zend_View_Abstract wishes to access this unexisting property
301
+			// by setting it to empty array (see Zend_View_Abstract::_filter)
302
+			$this->_dataProvider->_filter = array();
303
+		}
304
+
305
+		return $this->_dataProvider;
306
+	}
307
+
308
+	/**
309
+	 * Sets Dwoo compiler.
310
+	 *
311
+	 * @param string|Dwoo_Compiler Object or name of the class
312
+	 */
313
+	public function setCompiler($compiler)
314
+	{
315
+
316
+		// if param given as an object
317
+		if ($compiler instanceof Dwoo_ICompiler) {
318
+			$this->_compiler = $compiler;
319
+		}
320
+		// if param given as a string
321
+		elseif (is_subclass_of($compiler, 'Dwoo_Compiler') || 'Dwoo_Compiler' == $compiler) {
322
+			$this->_compiler = new $compiler();
323
+		} else {
324
+			throw new Dwoo_Exception('Custom compiler must be a subclass of Dwoo_Compiler or instance of Dwoo_ICompiler');
325
+		}
326
+	}
327
+
328
+	/**
329
+	 * Return the Dwoo compiler object.
330
+	 *
331
+	 * @return Dwoo_Compiler
332
+	 */
333
+	public function getCompiler()
334
+	{
335
+		if (null === $this->_compiler) {
336
+			$this->_compiler = Dwoo_Compiler::compilerFactory();
337
+		}
338
+
339
+		return $this->_compiler;
340
+	}
341
+
342
+	/**
343
+	 * Initializes Dwoo_ITemplate type of class and sets properties from _templateFileSettings.
344
+	 *
345
+	 * @param string Dwoo_ITemplate $template
346
+	 *
347
+	 * @return Dwoo_ITemplate
348
+	 */
349
+	public function getTemplateFile($template)
350
+	{
351
+		$templateFileClass = $this->_templateFileClass;
352
+
353
+		$dwooTemplateFile = new $templateFileClass($template);
354
+
355
+		if (!($dwooTemplateFile instanceof Dwoo_ITemplate)) {
356
+			throw new Dwoo_Exception('Custom templateFile class must be a subclass of Dwoo_ITemplate');
357
+		}
358
+
359
+		foreach ($this->_templateFileSettings as $method => $value) {
360
+			if (method_exists($dwooTemplateFile, 'set'.$method)) {
361
+				call_user_func(array($dwooTemplateFile, 'set'.$method), $value);
362
+			}
363
+		}
364
+
365
+		return $dwooTemplateFile;
366
+	}
367
+
368
+	/**
369
+	 * Dwoo_ITemplate type of class.
370
+	 *
371
+	 * @param string Name of the class
372
+	 */
373
+	public function setTemplateFile($tempateFileClass)
374
+	{
375
+		$this->_templateFileClass = $tempateFileClass;
376
+	}
377
+
378
+	/**
379
+	 * Passes data to Dwoo_Data object.
380
+	 *
381
+	 * @see Dwoo_Data::assign()
382
+	 *
383
+	 * @param array|string $name
384
+	 * @param mixed        $val
385
+	 *
386
+	 * @return Dwoo_Adapters_ZendFramework_View
387
+	 */
388
+	public function assign($name, $val = null)
389
+	{
390
+		$this->getDataProvider()->assign($name, $val);
391
+
392
+		return $this;
393
+	}
394
+
395
+	/**
396
+	 * Return list of all assigned variables.
397
+	 *
398
+	 * @return array
399
+	 */
400
+	public function getVars()
401
+	{
402
+		return $this->getDataProvider()->getData();
403
+	}
404
+
405
+	/**
406
+	 * Clear all assigned variables.
407
+	 *
408
+	 * Clears all variables assigned to Zend_View either via {@link assign()} or
409
+	 * property overloading ({@link __get()}/{@link __set()}).
410
+	 *
411
+	 * @return Dwoo_Adapters_ZendFramework_View
412
+	 */
413
+	public function clearVars()
414
+	{
415
+		$this->getDataProvider()->clear();
416
+
417
+		return $this;
418
+	}
419
+
420
+	/**
421
+	 * Wraper for parent's render method so preRender method
422
+	 * can be called (that will bind the plugin proxy to the
423
+	 * engine.
424
+	 *
425
+	 * @see Zend_View_Abstract::render
426
+	 *
427
+	 * @return string The script output
428
+	 */
429
+	public function render($name)
430
+	{
431
+		$this->preRender();
432
+
433
+		return parent::render($name);
434
+	}
435
+
436
+	/**
437
+	 * Processes a view script and outputs it. Output is then
438
+	 * passed through filters.
439
+	 *
440
+	 * @param string $name The script script name to process
441
+	 *
442
+	 * @return string The script output
443
+	 */
444
+	public function _run()
445
+	{
446
+		echo $this->_engine->get(
447
+			$this->getTemplateFile(func_get_arg(0)),
448
+			$this->getDataProvider(),
449
+			$this->getCompiler()
450
+		);
451
+	}
452
+
453
+	/**
454
+	 * Add plugin path.
455
+	 *
456
+	 * @param string $dir Directory
457
+	 *
458
+	 * @return Dwoo_Adapters_ZendFramework_View
459
+	 */
460
+	public function addPluginDir($dir)
461
+	{
462
+		$this->getEngine()->getLoader()->addDirectory($dir);
463
+
464
+		return $this;
465
+	}
466
+
467
+	/**
468
+	 * Set compile path.
469
+	 *
470
+	 * @param string $dir Directory
471
+	 *
472
+	 * @return Dwoo_Adapters_ZendFramework_View
473
+	 */
474
+	public function setCompileDir($dir)
475
+	{
476
+		$this->getEngine()->setCompileDir($dir);
477
+
478
+		return $this;
479
+	}
480
+
481
+	/**
482
+	 * Set cache path.
483
+	 *
484
+	 * @param string $dir Directory
485
+	 *
486
+	 * @return Dwoo_Adapters_ZendFramework_View
487
+	 */
488
+	public function setCacheDir($dir)
489
+	{
490
+		$this->getEngine()->setCacheDir($dir);
491
+
492
+		return $this;
493
+	}
494
+
495
+	/**
496
+	 * Set cache lifetime.
497
+	 *
498
+	 * @param string $seconds Lifetime in seconds
499
+	 *
500
+	 * @return Dwoo_Adapters_ZendFramework_View
501
+	 */
502
+	public function setCacheLifetime($seconds)
503
+	{
504
+		$this->getEngine()->setCacheTime($seconds);
505
+
506
+		return $this;
507
+	}
508
+
509
+	/**
510
+	 * Set charset.
511
+	 *
512
+	 * @param string $charset
513
+	 *
514
+	 * @return Dwoo_Adapters_ZendFramework_View
515
+	 */
516
+	public function setCharset($charset)
517
+	{
518
+		$this->_engine->setCharset($charset);
519
+
520
+		return $this;
521
+	}
522 522
 }
Please login to merge, or discard this patch.
lib/Dwoo/Compiler.php 5 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
     /**
278 278
      * Returns the left and right template delimiters.
279 279
      *
280
-     * @return array containing the left and the right delimiters
280
+     * @return string[] containing the left and the right delimiters
281 281
      */
282 282
     public function getDelimiters()
283 283
     {
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
      * Adds a preprocessor to the compiler, it will be called
363 363
      * before the template is compiled.
364 364
      *
365
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
365
+     * @param string $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
366 366
      *                        true
367 367
      * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else
368 368
      *                        you must provide a valid callback
@@ -1321,7 +1321,7 @@  discard block
 block discarded – undo
1321 1321
      *
1322 1322
      * @param array $params parameter array
1323 1323
      *
1324
-     * @return array tokens
1324
+     * @return Compiler tokens
1325 1325
      */
1326 1326
     public function getParamTokens(array $params)
1327 1327
     {
Please login to merge, or discard this patch.
Indentation   +3590 added lines, -3590 removed lines patch added patch discarded remove patch
@@ -31,3596 +31,3596 @@
 block discarded – undo
31 31
  */
32 32
 class Compiler implements ICompiler
33 33
 {
34
-    /**
35
-     * Constant that represents a php opening tag.
36
-     * use it in case it needs to be adjusted
37
-     *
38
-     * @var string
39
-     */
40
-    const PHP_OPEN = '<?php ';
41
-
42
-    /**
43
-     * Constant that represents a php closing tag.
44
-     * use it in case it needs to be adjusted
45
-     *
46
-     * @var string
47
-     */
48
-    const PHP_CLOSE = '?>';
49
-
50
-    /**
51
-     * Boolean flag to enable or disable debugging output.
52
-     *
53
-     * @var bool
54
-     */
55
-    public $debug = false;
56
-
57
-    /**
58
-     * Left script delimiter.
59
-     *
60
-     * @var string
61
-     */
62
-    protected $ld = '{';
63
-
64
-    /**
65
-     * Left script delimiter with escaped regex meta characters.
66
-     *
67
-     * @var string
68
-     */
69
-    protected $ldr = '\\{';
70
-
71
-    /**
72
-     * Right script delimiter.
73
-     *
74
-     * @var string
75
-     */
76
-    protected $rd = '}';
77
-
78
-    /**
79
-     * Right script delimiter with escaped regex meta characters.
80
-     *
81
-     * @var string
82
-     */
83
-    protected $rdr = '\\}';
84
-
85
-    /**
86
-     * Defines whether the nested comments should be parsed as nested or not.
87
-     * defaults to false (classic block comment parsing as in all languages)
88
-     *
89
-     * @var bool
90
-     */
91
-    protected $allowNestedComments = false;
92
-
93
-    /**
94
-     * Defines whether opening and closing tags can contain spaces before valid data or not.
95
-     * turn to true if you want to be sloppy with the syntax, but when set to false it allows
96
-     * to skip javascript and css tags as long as they are in the form "{ something", which is
97
-     * nice. default is false.
98
-     *
99
-     * @var bool
100
-     */
101
-    protected $allowLooseOpenings = false;
102
-
103
-    /**
104
-     * Defines whether the compiler will automatically html-escape variables or not.
105
-     * default is false
106
-     *
107
-     * @var bool
108
-     */
109
-    protected $autoEscape = false;
110
-
111
-    /**
112
-     * Security policy object.
113
-     *
114
-     * @var SecurityPolicy
115
-     */
116
-    protected $securityPolicy;
117
-
118
-    /**
119
-     * Stores the custom plugins registered with this compiler.
120
-     *
121
-     * @var array
122
-     */
123
-    protected $customPlugins = array();
124
-
125
-    /**
126
-     * Stores the template plugins registered with this compiler.
127
-     *
128
-     * @var array
129
-     */
130
-    protected $templatePlugins = array();
131
-
132
-    /**
133
-     * Stores the pre- and post-processors callbacks.
134
-     *
135
-     * @var array
136
-     */
137
-    protected $processors = array('pre' => array(), 'post' => array());
138
-
139
-    /**
140
-     * Stores a list of plugins that are used in the currently compiled
141
-     * template, and that are not compilable. these plugins will be loaded
142
-     * during the template's runtime if required.
143
-     * it is a 1D array formatted as key:pluginName value:pluginType
144
-     *
145
-     * @var array
146
-     */
147
-    protected $usedPlugins;
148
-
149
-    /**
150
-     * Stores the template undergoing compilation.
151
-     *
152
-     * @var string
153
-     */
154
-    protected $template;
155
-
156
-    /**
157
-     * Stores the current pointer position inside the template.
158
-     *
159
-     * @var int
160
-     */
161
-    protected $pointer;
162
-
163
-    /**
164
-     * Stores the current line count inside the template for debugging purposes.
165
-     *
166
-     * @var int
167
-     */
168
-    protected $line;
169
-
170
-    /**
171
-     * Stores the current template source while compiling it.
172
-     *
173
-     * @var string
174
-     */
175
-    protected $templateSource;
176
-
177
-    /**
178
-     * Stores the data within which the scope moves.
179
-     *
180
-     * @var array
181
-     */
182
-    protected $data;
183
-
184
-    /**
185
-     * Variable scope of the compiler, set to null if
186
-     * it can not be resolved to a static string (i.e. if some
187
-     * plugin defines a new scope based on a variable array key).
188
-     *
189
-     * @var mixed
190
-     */
191
-    protected $scope;
192
-
193
-    /**
194
-     * Variable scope tree, that allows to rebuild the current
195
-     * scope if required, i.e. when going to a parent level.
196
-     *
197
-     * @var array
198
-     */
199
-    protected $scopeTree;
200
-
201
-    /**
202
-     * Block plugins stack, accessible through some methods.
203
-     *
204
-     * @see findBlock
205
-     * @see getCurrentBlock
206
-     * @see addBlock
207
-     * @see addCustomBlock
208
-     * @see injectBlock
209
-     * @see removeBlock
210
-     * @see removeTopBlock
211
-     * @var array
212
-     */
213
-    protected $stack = array();
214
-
215
-    /**
216
-     * Current block at the top of the block plugins stack,
217
-     * accessible through getCurrentBlock.
218
-     *
219
-     * @see getCurrentBlock
220
-     * @var array
221
-     */
222
-    protected $curBlock;
223
-
224
-    /**
225
-     * Current dwoo object that uses this compiler, or null.
226
-     *
227
-     * @var Core
228
-     */
229
-    public $dwoo;
230
-
231
-    /**
232
-     * Holds an instance of this class, used by getInstance when you don't
233
-     * provide a custom compiler in order to save resources.
234
-     *
235
-     * @var Compiler
236
-     */
237
-    protected static $instance;
238
-
239
-    /**
240
-     * Token types.
241
-     *
242
-     * @var int
243
-     */
244
-    const T_UNQUOTED_STRING = 1;
245
-    const T_NUMERIC         = 2;
246
-    const T_NULL            = 4;
247
-    const T_BOOL            = 8;
248
-    const T_MATH            = 16;
249
-    const T_BREAKCHAR       = 32;
250
-
251
-    /**
252
-     * Compiler constructor.
253
-     * saves the created instance so that child templates get the same one
254
-     */
255
-    public function __construct()
256
-    {
257
-        self::$instance = $this;
258
-    }
259
-
260
-    /**
261
-     * Sets the delimiters to use in the templates.
262
-     * delimiters can be multi-character strings but should not be one of those as they will
263
-     * make it very hard to work with templates or might even break the compiler entirely : "\", "$", "|", ":" and
264
-     * finally "#" only if you intend to use config-vars with the #var# syntax.
265
-     *
266
-     * @param string $left  left delimiter
267
-     * @param string $right right delimiter
268
-     */
269
-    public function setDelimiters($left, $right)
270
-    {
271
-        $this->ld  = $left;
272
-        $this->rd  = $right;
273
-        $this->ldr = preg_quote($left, '/');
274
-        $this->rdr = preg_quote($right, '/');
275
-    }
276
-
277
-    /**
278
-     * Returns the left and right template delimiters.
279
-     *
280
-     * @return array containing the left and the right delimiters
281
-     */
282
-    public function getDelimiters()
283
-    {
284
-        return array($this->ld, $this->rd);
285
-    }
286
-
287
-    /**
288
-     * Sets the way to handle nested comments, if set to true
289
-     * {* foo {* some other *} comment *} will be stripped correctly.
290
-     * if false it will remove {* foo {* some other *} and leave "comment *}" alone,
291
-     * this is the default behavior
292
-     *
293
-     * @param bool $allow allow nested comments or not, defaults to true (but the default internal value is false)
294
-     */
295
-    public function setNestedCommentsHandling($allow = true)
296
-    {
297
-        $this->allowNestedComments = (bool)$allow;
298
-    }
299
-
300
-    /**
301
-     * Returns the nested comments handling setting.
302
-     *
303
-     * @see    setNestedCommentsHandling
304
-     * @return bool true if nested comments are allowed
305
-     */
306
-    public function getNestedCommentsHandling()
307
-    {
308
-        return $this->allowNestedComments;
309
-    }
310
-
311
-    /**
312
-     * Sets the tag openings handling strictness, if set to true, template tags can
313
-     * contain spaces before the first function/string/variable such as { $foo} is valid.
314
-     * if set to false (default setting), { $foo} is invalid but that is however a good thing
315
-     * as it allows css (i.e. #foo { color:red; }) to be parsed silently without triggering
316
-     * an error, same goes for javascript.
317
-     *
318
-     * @param bool $allow true to allow loose handling, false to restore default setting
319
-     */
320
-    public function setLooseOpeningHandling($allow = false)
321
-    {
322
-        $this->allowLooseOpenings = (bool)$allow;
323
-    }
324
-
325
-    /**
326
-     * Returns the tag openings handling strictness setting.
327
-     *
328
-     * @see    setLooseOpeningHandling
329
-     * @return bool true if loose tags are allowed
330
-     */
331
-    public function getLooseOpeningHandling()
332
-    {
333
-        return $this->allowLooseOpenings;
334
-    }
335
-
336
-    /**
337
-     * Changes the auto escape setting.
338
-     * if enabled, the compiler will automatically html-escape variables,
339
-     * unless they are passed through the safe function such as {$var|safe}
340
-     * or {safe $var}
341
-     * default setting is disabled/false
342
-     *
343
-     * @param bool $enabled set to true to enable, false to disable
344
-     */
345
-    public function setAutoEscape($enabled)
346
-    {
347
-        $this->autoEscape = (bool)$enabled;
348
-    }
349
-
350
-    /**
351
-     * Returns the auto escape setting.
352
-     * default setting is disabled/false
353
-     *
354
-     * @return bool
355
-     */
356
-    public function getAutoEscape()
357
-    {
358
-        return $this->autoEscape;
359
-    }
360
-
361
-    /**
362
-     * Adds a preprocessor to the compiler, it will be called
363
-     * before the template is compiled.
364
-     *
365
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
366
-     *                        true
367
-     * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else
368
-     *                        you must provide a valid callback
369
-     */
370
-    public function addPreProcessor($callback, $autoload = false)
371
-    {
372
-        if ($autoload) {
373
-            $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', Core::toCamelCase($callback));
374
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . $name;
375
-
376
-            if (class_exists($class)) {
377
-                $callback = array(new $class($this), 'process');
378
-            } elseif (function_exists($class)) {
379
-                $callback = $class;
380
-            } else {
381
-                $callback = array('autoload' => true, 'class' => $class, 'name' => $name);
382
-            }
383
-
384
-            $this->processors['pre'][] = $callback;
385
-        } else {
386
-            $this->processors['pre'][] = $callback;
387
-        }
388
-    }
389
-
390
-    /**
391
-     * Removes a preprocessor from the compiler.
392
-     *
393
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if it was autoloaded
394
-     */
395
-    public function removePreProcessor($callback)
396
-    {
397
-        if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
398
-            unset($this->processors['pre'][$index]);
399
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
400
-                    $callback),
401
-                $this->processors['pre'], true)) !== false) {
402
-            unset($this->processors['pre'][$index]);
403
-        } else {
404
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
405
-            foreach ($this->processors['pre'] as $index => $proc) {
406
-                if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
407
-                    unset($this->processors['pre'][$index]);
408
-                    break;
409
-                }
410
-            }
411
-        }
412
-    }
413
-
414
-    /**
415
-     * Adds a postprocessor to the compiler, it will be called
416
-     * before the template is compiled.
417
-     *
418
-     * @param mixed $callback either a valid callback to the postprocessor or a simple name if the autoload is set to
419
-     *                        true
420
-     * @param bool  $autoload if set to true, the postprocessor is auto-loaded from one of the plugin directories, else
421
-     *                        you must provide a valid callback
422
-     */
423
-    public function addPostProcessor($callback, $autoload = false)
424
-    {
425
-        if ($autoload) {
426
-            $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
427
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . Core::toCamelCase($name);
428
-
429
-            if (class_exists($class)) {
430
-                $callback = array(new $class($this), 'process');
431
-            } elseif (function_exists($class)) {
432
-                $callback = $class;
433
-            } else {
434
-                $callback = array('autoload' => true, 'class' => $class, 'name' => $name);
435
-            }
436
-
437
-            $this->processors['post'][] = $callback;
438
-        } else {
439
-            $this->processors['post'][] = $callback;
440
-        }
441
-    }
442
-
443
-    /**
444
-     * Removes a postprocessor from the compiler.
445
-     *
446
-     * @param mixed $callback either a valid callback to the postprocessor or a simple name if it was autoloaded
447
-     */
448
-    public function removePostProcessor($callback)
449
-    {
450
-        if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
451
-            unset($this->processors['post'][$index]);
452
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
453
-                    $callback),
454
-                $this->processors['post'], true)) !== false) {
455
-            unset($this->processors['post'][$index]);
456
-        } else {
457
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
458
-            foreach ($this->processors['post'] as $index => $proc) {
459
-                if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
460
-                    unset($this->processors['post'][$index]);
461
-                    break;
462
-                }
463
-            }
464
-        }
465
-    }
466
-
467
-    /**
468
-     * Internal function to autoload processors at runtime if required.
469
-     *
470
-     * @param string $class the class/function name
471
-     * @param string $name  the plugin name (without Dwoo_Plugin_ prefix)
472
-     *
473
-     * @return array|string
474
-     * @throws Exception
475
-     */
476
-    protected function loadProcessor($class, $name)
477
-    {
478
-        if (!class_exists($class) && !function_exists($class)) {
479
-            try {
480
-                $this->getDwoo()->getLoader()->loadPlugin($name);
481
-            }
482
-            catch (Exception $e) {
483
-                throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
484
-            }
485
-        }
486
-
487
-        if (class_exists($class)) {
488
-            return array(new $class($this), 'process');
489
-        }
490
-
491
-        if (function_exists($class)) {
492
-            return $class;
493
-        }
494
-
495
-        throw new Exception('Wrong processor name, when using autoload the processor must be in one of your plugin dir as "name.php" containg a class or function named "Dwoo_Processor_name"');
496
-    }
497
-
498
-    /**
499
-     * Adds an used plugin, this is reserved for use by the {template} plugin.
500
-     * this is required so that plugin loading bubbles up from loaded
501
-     * template files to the current one
502
-     *
503
-     * @private
504
-     *
505
-     * @param string $name function name
506
-     * @param int    $type plugin type (Core::*_PLUGIN)
507
-     */
508
-    public function addUsedPlugin($name, $type)
509
-    {
510
-        $this->usedPlugins[$name] = $type;
511
-    }
512
-
513
-    /**
514
-     * Returns all the plugins this template uses.
515
-     *
516
-     * @private
517
-     * @return  array the list of used plugins in the parsed template
518
-     */
519
-    public function getUsedPlugins()
520
-    {
521
-        return $this->usedPlugins;
522
-    }
523
-
524
-    /**
525
-     * Adds a template plugin, this is reserved for use by the {template} plugin.
526
-     * this is required because the template functions are not declared yet
527
-     * during compilation, so we must have a way of validating their argument
528
-     * signature without using the reflection api
529
-     *
530
-     * @private
531
-     *
532
-     * @param string $name   function name
533
-     * @param array  $params parameter array to help validate the function call
534
-     * @param string $uuid   unique id of the function
535
-     * @param string $body   function php code
536
-     */
537
-    public function addTemplatePlugin($name, array $params, $uuid, $body = null)
538
-    {
539
-        $this->templatePlugins[$name] = array('params' => $params, 'body' => $body, 'uuid' => $uuid);
540
-    }
541
-
542
-    /**
543
-     * Returns all the parsed sub-templates.
544
-     *
545
-     * @private
546
-     * @return  array the parsed sub-templates
547
-     */
548
-    public function getTemplatePlugins()
549
-    {
550
-        return $this->templatePlugins;
551
-    }
552
-
553
-    /**
554
-     * Marks a template plugin as being called, which means its source must be included in the compiled template.
555
-     *
556
-     * @param string $name function name
557
-     */
558
-    public function useTemplatePlugin($name)
559
-    {
560
-        $this->templatePlugins[$name]['called'] = true;
561
-    }
562
-
563
-    /**
564
-     * Adds the custom plugins loaded into Dwoo to the compiler so it can load them.
565
-     *
566
-     * @see Core::addPlugin
567
-     *
568
-     * @param array $customPlugins an array of custom plugins
569
-     */
570
-    public function setCustomPlugins(array $customPlugins)
571
-    {
572
-        $this->customPlugins = $customPlugins;
573
-    }
574
-
575
-    /**
576
-     * Sets the security policy object to enforce some php security settings.
577
-     * use this if untrusted persons can modify templates,
578
-     * set it on the Dwoo object as it will be passed onto the compiler automatically
579
-     *
580
-     * @param SecurityPolicy $policy the security policy object
581
-     */
582
-    public function setSecurityPolicy(SecurityPolicy $policy = null)
583
-    {
584
-        $this->securityPolicy = $policy;
585
-    }
586
-
587
-    /**
588
-     * Returns the current security policy object or null by default.
589
-     *
590
-     * @return SecurityPolicy|null the security policy object if any
591
-     */
592
-    public function getSecurityPolicy()
593
-    {
594
-        return $this->securityPolicy;
595
-    }
596
-
597
-    /**
598
-     * Sets the pointer position.
599
-     *
600
-     * @param int  $position the new pointer position
601
-     * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
602
-     */
603
-    public function setPointer($position, $isOffset = false)
604
-    {
605
-        if ($isOffset) {
606
-            $this->pointer += $position;
607
-        } else {
608
-            $this->pointer = $position;
609
-        }
610
-    }
611
-
612
-    /**
613
-     * Returns the current pointer position, only available during compilation of a template.
614
-     *
615
-     * @return int
616
-     */
617
-    public function getPointer()
618
-    {
619
-        return $this->pointer;
620
-    }
621
-
622
-    /**
623
-     * Sets the line number.
624
-     *
625
-     * @param int  $number   the new line number
626
-     * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
627
-     */
628
-    public function setLine($number, $isOffset = false)
629
-    {
630
-        if ($isOffset) {
631
-            $this->line += $number;
632
-        } else {
633
-            $this->line = $number;
634
-        }
635
-    }
636
-
637
-    /**
638
-     * Returns the current line number, only available during compilation of a template.
639
-     *
640
-     * @return int
641
-     */
642
-    public function getLine()
643
-    {
644
-        return $this->line;
645
-    }
646
-
647
-    /**
648
-     * Returns the dwoo object that initiated this template compilation, only available during compilation of a
649
-     * template.
650
-     *
651
-     * @return Core
652
-     */
653
-    public function getDwoo()
654
-    {
655
-        return $this->dwoo;
656
-    }
657
-
658
-    /**
659
-     * Overwrites the template that is being compiled.
660
-     *
661
-     * @param string $newSource   the template source that must replace the current one
662
-     * @param bool   $fromPointer if set to true, only the source from the current pointer position is replaced
663
-     *
664
-     * @return void
665
-     */
666
-    public function setTemplateSource($newSource, $fromPointer = false)
667
-    {
668
-        if ($fromPointer === true) {
669
-            $this->templateSource = substr($this->templateSource, 0, $this->pointer) . $newSource;
670
-        } else {
671
-            $this->templateSource = $newSource;
672
-        }
673
-    }
674
-
675
-    /**
676
-     * Returns the template that is being compiled.
677
-     *
678
-     * @param mixed $fromPointer if set to true, only the source from the current pointer
679
-     *                           position is returned, if a number is given it overrides the current pointer
680
-     *
681
-     * @return string the template or partial template
682
-     */
683
-    public function getTemplateSource($fromPointer = false)
684
-    {
685
-        if ($fromPointer === true) {
686
-            return substr($this->templateSource, $this->pointer);
687
-        } elseif (is_numeric($fromPointer)) {
688
-            return substr($this->templateSource, $fromPointer);
689
-        } else {
690
-            return $this->templateSource;
691
-        }
692
-    }
693
-
694
-    /**
695
-     * Resets the compilation pointer, effectively restarting the compilation process.
696
-     * this is useful if a plugin modifies the template source since it might need to be recompiled
697
-     */
698
-    public function recompile()
699
-    {
700
-        $this->setPointer(0);
701
-    }
702
-
703
-    /**
704
-     * Compiles the provided string down to php code.
705
-     *
706
-     * @param Core      $dwoo
707
-     * @param ITemplate $template the template to compile
708
-     *
709
-     * @return string a compiled php string
710
-     * @throws CompilationException
711
-     */
712
-    public function compile(Core $dwoo, ITemplate $template)
713
-    {
714
-        // init vars
715
-        //		$compiled = '';
716
-        $tpl                  = $template->getSource();
717
-        $ptr                  = 0;
718
-        $this->dwoo           = $dwoo;
719
-        $this->template       = $template;
720
-        $this->templateSource = &$tpl;
721
-        $this->pointer        = &$ptr;
722
-
723
-        while (true) {
724
-            // if pointer is at the beginning, reset everything, that allows a plugin to externally reset the compiler if everything must be reparsed
725
-            if ($ptr === 0) {
726
-                // resets variables
727
-                $this->usedPlugins     = array();
728
-                $this->data            = array();
729
-                $this->scope           = &$this->data;
730
-                $this->scopeTree       = array();
731
-                $this->stack           = array();
732
-                $this->line            = 1;
733
-                $this->templatePlugins = array();
734
-                // add top level block
735
-                $compiled                 = $this->addBlock('TopLevelBlock', array(), 0);
736
-                $this->stack[0]['buffer'] = '';
737
-
738
-                if ($this->debug) {
739
-                    echo "\n";
740
-                    echo 'COMPILER INIT' . "\n";
741
-                }
742
-
743
-                if ($this->debug) {
744
-                    echo 'PROCESSING PREPROCESSORS (' . count($this->processors['pre']) . ')' . "\n";
745
-                }
746
-
747
-                // runs preprocessors
748
-                foreach ($this->processors['pre'] as $preProc) {
749
-                    if (is_array($preProc) && isset($preProc['autoload'])) {
750
-                        $preProc = $this->loadProcessor($preProc['class'], $preProc['name']);
751
-                    }
752
-                    if (is_array($preProc) && $preProc[0] instanceof Processor) {
753
-                        $tpl = call_user_func($preProc, $tpl);
754
-                    } else {
755
-                        $tpl = call_user_func($preProc, $this, $tpl);
756
-                    }
757
-                }
758
-                unset($preProc);
759
-
760
-                // show template source if debug
761
-                if ($this->debug) {
762
-                    echo '<pre>'.print_r(htmlentities($tpl), true).'</pre>'."\n";
763
-                }
764
-
765
-                // strips php tags if required by the security policy
766
-                if ($this->securityPolicy !== null) {
767
-                    $search = array('{<\?php.*?\?>}');
768
-                    if (ini_get('short_open_tags')) {
769
-                        $search = array('{<\?.*?\?>}', '{<%.*?%>}');
770
-                    }
771
-                    switch ($this->securityPolicy->getPhpHandling()) {
772
-                        case SecurityPolicy::PHP_ALLOW:
773
-                            break;
774
-                        case SecurityPolicy::PHP_ENCODE:
775
-                            $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
-                            break;
777
-                        case SecurityPolicy::PHP_REMOVE:
778
-                            $tpl = preg_replace($search, '', $tpl);
779
-                    }
780
-                }
781
-            }
782
-
783
-            $pos = strpos($tpl, $this->ld, $ptr);
784
-
785
-            if ($pos === false) {
786
-                $this->push(substr($tpl, $ptr), 0);
787
-                break;
788
-            } elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
789
-                $this->push(substr($tpl, $ptr, $pos - $ptr - 1) . $this->ld);
790
-                $ptr = $pos + strlen($this->ld);
791
-            } elseif (preg_match('/^' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . 'literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', substr($tpl, $pos), $litOpen)) {
792
-                if (!preg_match('/' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . '\/literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
793
-                    throw new CompilationException($this, 'The {literal} blocks must be closed explicitly with {/literal}');
794
-                }
795
-                $endpos = $litClose[0][1];
796
-                $this->push(substr($tpl, $ptr, $pos - $ptr) . substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
797
-                $ptr = $endpos + strlen($litClose[0][0]);
798
-            } else {
799
-                if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
800
-                    $this->push(substr($tpl, $ptr, $pos - $ptr - 1));
801
-                    $ptr = $pos;
802
-                }
803
-
804
-                $this->push(substr($tpl, $ptr, $pos - $ptr));
805
-                $ptr = $pos;
806
-
807
-                $pos += strlen($this->ld);
808
-                if ($this->allowLooseOpenings) {
809
-                    while (substr($tpl, $pos, 1) === ' ') {
810
-                        $pos += 1;
811
-                    }
812
-                } else {
813
-                    if (substr($tpl, $pos, 1) === ' ' || substr($tpl, $pos, 1) === "\r" || substr($tpl, $pos, 1) === "\n" || substr($tpl, $pos, 1) === "\t") {
814
-                        $ptr = $pos;
815
-                        $this->push($this->ld);
816
-                        continue;
817
-                    }
818
-                }
819
-
820
-                // check that there is an end tag present
821
-                if (strpos($tpl, $this->rd, $pos) === false) {
822
-                    throw new CompilationException($this, 'A template tag was not closed, started with "' . substr($tpl, $ptr, 30) . '"');
823
-                }
824
-
825
-                $ptr += strlen($this->ld);
826
-                $subptr = $ptr;
827
-
828
-                while (true) {
829
-                    $parsed = $this->parse($tpl, $subptr, null, false, 'root', $subptr);
830
-
831
-                    // reload loop if the compiler was reset
832
-                    if ($ptr === 0) {
833
-                        continue 2;
834
-                    }
835
-
836
-                    $len = $subptr - $ptr;
837
-                    $this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
838
-                    $ptr += $len;
839
-
840
-                    if ($parsed === false) {
841
-                        break;
842
-                    }
843
-                }
844
-            }
845
-        }
846
-
847
-        $compiled .= $this->removeBlock('TopLevelBlock');
848
-
849
-        if ($this->debug) {
850
-            echo 'PROCESSING POSTPROCESSORS' . "\n";
851
-        }
852
-
853
-        foreach ($this->processors['post'] as $postProc) {
854
-            if (is_array($postProc) && isset($postProc['autoload'])) {
855
-                $postProc = $this->loadProcessor($postProc['class'], $postProc['name']);
856
-            }
857
-            if (is_array($postProc) && $postProc[0] instanceof Processor) {
858
-                $compiled = call_user_func($postProc, $compiled);
859
-            } else {
860
-                $compiled = call_user_func($postProc, $this, $compiled);
861
-            }
862
-        }
863
-        unset($postProc);
864
-
865
-        if ($this->debug) {
866
-            echo 'COMPILATION COMPLETE : MEM USAGE : ' . memory_get_usage() . "\n";
867
-        }
868
-
869
-        $output = "<?php\n/* template head */\n";
870
-
871
-        // build plugin preloader
872
-        foreach ($this->getUsedPlugins() as $plugin => $type) {
873
-            if ($type & Core::CUSTOM_PLUGIN) {
874
-                continue;
875
-            }
876
-
877
-            switch ($type) {
878
-                case Core::BLOCK_PLUGIN:
879
-                case Core::CLASS_PLUGIN:
880
-                    if (class_exists('Plugin' . $plugin) !== false) {
881
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
-                    } else {
884
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
-                    }
887
-                    break;
888
-                case Core::FUNC_PLUGIN:
889
-                    if (function_exists('Plugin' . $plugin) !== false) {
890
-                        $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
891
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
-                    } else {
893
-                        $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
-                    }
896
-                    break;
897
-                case Core::SMARTY_MODIFIER:
898
-                    $output .= "if (function_exists('smarty_modifier_$plugin')===false)".
899
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
900
-                    break;
901
-                case Core::SMARTY_FUNCTION:
902
-                    $output .= "if (function_exists('smarty_function_$plugin')===false)".
903
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
904
-                    break;
905
-                case Core::SMARTY_BLOCK:
906
-                    $output .= "if (function_exists('smarty_block_$plugin')===false)".
907
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
908
-                    break;
909
-                case Core::PROXY_PLUGIN:
910
-                    $output .= $this->getDwoo()->getPluginProxy()->getLoader($plugin);
911
-                    break;
912
-                default:
913
-                    throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
914
-            }
915
-        }
916
-
917
-        foreach ($this->templatePlugins as $function => $attr) {
918
-            if (isset($attr['called']) && $attr['called'] === true && !isset($attr['checked'])) {
919
-                $this->resolveSubTemplateDependencies($function);
920
-            }
921
-        }
922
-        foreach ($this->templatePlugins as $function) {
923
-            if (isset($function['called']) && $function['called'] === true) {
924
-                $output .= $function['body'] . PHP_EOL;
925
-            }
926
-        }
927
-
928
-        $output .= $compiled . "\n?>";
929
-
930
-        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*' . preg_quote(self::PHP_CLOSE, '/') . preg_quote(self::PHP_OPEN, '/') . ')/', ";\n", $output);
931
-        $output = str_replace(self::PHP_CLOSE . self::PHP_OPEN, "\n", $output);
932
-
933
-        // handle <?xml tag at the beginning
934
-        $output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
935
-
936
-        // add another line break after PHP closing tags that have a line break following,
937
-        // as we do not know whether it's intended, and PHP will strip it otherwise
938
-        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0' . "\n", $output);
939
-
940
-        if ($this->debug) {
941
-            echo '=============================================================================================' . "\n";
942
-            $lines = preg_split('{\r\n|\n|<br />}', $output);
943
-            array_shift($lines);
944
-            foreach ($lines as $i => $line) {
945
-                echo ($i + 1) . '. ' . $line . "\r\n";
946
-            }
947
-            echo '=============================================================================================' . "\n";
948
-        }
949
-
950
-        $this->template = $this->dwoo = null;
951
-        $tpl            = null;
952
-
953
-        return $output;
954
-    }
955
-
956
-    /**
957
-     * Checks what sub-templates are used in every sub-template so that we're sure they are all compiled.
958
-     *
959
-     * @param string $function the sub-template name
960
-     */
961
-    protected function resolveSubTemplateDependencies($function)
962
-    {
963
-        if ($this->debug) {
964
-            echo 'Compiler::' . __FUNCTION__ . "\n";
965
-        }
966
-
967
-        $body = $this->templatePlugins[$function]['body'];
968
-        foreach ($this->templatePlugins as $func => $attr) {
969
-            if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS .
970
-            'Plugin' . Core::toCamelCase($func)) !== false) {
971
-                $this->templatePlugins[$func]['called'] = true;
972
-                $this->resolveSubTemplateDependencies($func);
973
-            }
974
-        }
975
-        $this->templatePlugins[$function]['checked'] = true;
976
-    }
977
-
978
-    /**
979
-     * Adds compiled content to the current block.
980
-     *
981
-     * @param string $content   the content to push
982
-     * @param int    $lineCount newlines count in content, optional
983
-     *
984
-     * @throws CompilationException
985
-     */
986
-    public function push($content, $lineCount = null)
987
-    {
988
-        if ($lineCount === null) {
989
-            $lineCount = substr_count($content, "\n");
990
-        }
991
-
992
-        if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
993
-            // buffer is not initialized yet (the block has just been created)
994
-            $this->stack[count($this->stack) - 2]['buffer'] .= (string)$content;
995
-            $this->curBlock['buffer'] = '';
996
-        } else {
997
-            if (!isset($this->curBlock['buffer'])) {
998
-                throw new CompilationException($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
999
-            }
1000
-            // append current content to current block's buffer
1001
-            $this->curBlock['buffer'] .= (string)$content;
1002
-        }
1003
-        $this->line += $lineCount;
1004
-    }
1005
-
1006
-    /**
1007
-     * Sets the scope.
1008
-     * set to null if the scope becomes "unstable" (i.e. too variable or unknown) so that
1009
-     * variables are compiled in a more evaluative way than just $this->scope['key']
1010
-     *
1011
-     * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1012
-     * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1013
-     *
1014
-     * @return array the current scope tree
1015
-     */
1016
-    public function setScope($scope, $absolute = false)
1017
-    {
1018
-        $old = $this->scopeTree;
1019
-
1020
-        if ($scope === null) {
1021
-            unset($this->scope);
1022
-            $this->scope = null;
1023
-        }
1024
-
1025
-        if (is_array($scope) === false) {
1026
-            $scope = explode('.', $scope);
1027
-        }
1028
-
1029
-        if ($absolute === true) {
1030
-            $this->scope     = &$this->data;
1031
-            $this->scopeTree = array();
1032
-        }
1033
-
1034
-        while (($bit = array_shift($scope)) !== null) {
1035
-            if ($bit === '_parent' || $bit === '_') {
1036
-                array_pop($this->scopeTree);
1037
-                reset($this->scopeTree);
1038
-                $this->scope = &$this->data;
1039
-                $cnt         = count($this->scopeTree);
1040
-                for ($i = 0; $i < $cnt; ++ $i) {
1041
-                    $this->scope = &$this->scope[$this->scopeTree[$i]];
1042
-                }
1043
-            } elseif ($bit === '_root' || $bit === '__') {
1044
-                $this->scope     = &$this->data;
1045
-                $this->scopeTree = array();
1046
-            } elseif (isset($this->scope[$bit])) {
1047
-                $this->scope       = &$this->scope[$bit];
1048
-                $this->scopeTree[] = $bit;
1049
-            } else {
1050
-                $this->scope[$bit] = array();
1051
-                $this->scope       = &$this->scope[$bit];
1052
-                $this->scopeTree[] = $bit;
1053
-            }
1054
-        }
1055
-
1056
-        return $old;
1057
-    }
1058
-
1059
-    /**
1060
-     * Adds a block to the top of the block stack.
1061
-     *
1062
-     * @param string $type      block type (name)
1063
-     * @param array  $params    the parameters array
1064
-     * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1065
-     *
1066
-     * @return string the preProcessing() method's output
1067
-     */
1068
-    public function addBlock($type, array $params, $paramtype)
1069
-    {
1070
-        if ($this->debug) {
1071
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1072
-        }
1073
-
1074
-        $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1075
-        if (class_exists($class) === false) {
1076
-            $this->getDwoo()->getLoader()->loadPlugin($type);
1077
-        }
1078
-        $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1079
-
1080
-        $this->stack[]  = array(
1081
-            'type'   => $type,
1082
-            'params' => $params,
1083
-            'custom' => false,
1084
-            'class'  => $class,
1085
-            'buffer' => null
1086
-        );
1087
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1088
-
1089
-        return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1090
-    }
1091
-
1092
-    /**
1093
-     * Adds a custom block to the top of the block stack.
1094
-     *
1095
-     * @param string $type      block type (name)
1096
-     * @param array  $params    the parameters array
1097
-     * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1098
-     *
1099
-     * @return string the preProcessing() method's output
1100
-     */
1101
-    public function addCustomBlock($type, array $params, $paramtype)
1102
-    {
1103
-        $callback = $this->customPlugins[$type]['callback'];
1104
-        if (is_array($callback)) {
1105
-            $class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
1106
-        } else {
1107
-            $class = $callback;
1108
-        }
1109
-
1110
-        $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1111
-
1112
-        $this->stack[]  = array(
1113
-            'type'   => $type,
1114
-            'params' => $params,
1115
-            'custom' => true,
1116
-            'class'  => $class,
1117
-            'buffer' => null
1118
-        );
1119
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1120
-
1121
-        return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1122
-    }
1123
-
1124
-    /**
1125
-     * Injects a block at the top of the plugin stack without calling its preProcessing method.
1126
-     * used by {else} blocks to re-add themselves after having closed everything up to their parent
1127
-     *
1128
-     * @param string $type   block type (name)
1129
-     * @param array  $params parameters array
1130
-     */
1131
-    public function injectBlock($type, array $params)
1132
-    {
1133
-        if ($this->debug) {
1134
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1135
-        }
1136
-
1137
-        $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1138
-        if (class_exists($class) === false) {
1139
-            $this->getDwoo()->getLoader()->loadPlugin($type);
1140
-        }
1141
-        $this->stack[]  = array(
1142
-            'type'   => $type,
1143
-            'params' => $params,
1144
-            'custom' => false,
1145
-            'class'  => $class,
1146
-            'buffer' => null
1147
-        );
1148
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1149
-    }
1150
-
1151
-    /**
1152
-     * Removes the closest-to-top block of the given type and all other
1153
-     * blocks encountered while going down the block stack.
1154
-     *
1155
-     * @param string $type block type (name)
1156
-     *
1157
-     * @return string the output of all postProcessing() method's return values of the closed blocks
1158
-     * @throws CompilationException
1159
-     */
1160
-    public function removeBlock($type)
1161
-    {
1162
-        if ($this->debug) {
1163
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1164
-        }
1165
-
1166
-        $output = '';
1167
-
1168
-        $pluginType = $this->getPluginType($type);
1169
-        if ($pluginType & Core::SMARTY_BLOCK) {
1170
-            $type = 'Smartyinterface';
1171
-        }
1172
-        while (true) {
1173
-            while ($top = array_pop($this->stack)) {
1174
-                if ($top['custom']) {
1175
-                    $class = $top['class'];
1176
-                } else {
1177
-                    $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($top['type']);
1178
-                }
1179
-                if (count($this->stack)) {
1180
-                    $this->curBlock = &$this->stack[count($this->stack) - 1];
1181
-                    $this->push(call_user_func(array(
1182
-                        $class,
1183
-                        'postProcessing'
1184
-                    ), $this, $top['params'], '', '', $top['buffer']), 0);
1185
-                } else {
1186
-                    $null           = null;
1187
-                    $this->curBlock = &$null;
1188
-                    $output         = call_user_func(
1189
-                        array(
1190
-                        $class,
1191
-                        'postProcessing'
1192
-                        ), $this, $top['params'], '', '', $top['buffer']
1193
-                    );
1194
-                }
1195
-
1196
-                if ($top['type'] === $type) {
1197
-                    break 2;
1198
-                }
1199
-            }
1200
-
1201
-            throw new CompilationException($this, 'Syntax malformation, a block of type "' . $type . '" was closed but was not opened');
1202
-            break;
1203
-        }
1204
-
1205
-        return $output;
1206
-    }
1207
-
1208
-    /**
1209
-     * Returns a reference to the first block of the given type encountered and
1210
-     * optionally closes all blocks until it finds it
1211
-     * this is mainly used by {else} plugins to close everything that was opened
1212
-     * between their parent and themselves.
1213
-     *
1214
-     * @param string $type       the block type (name)
1215
-     * @param bool   $closeAlong whether to close all blocks encountered while going down the block stack or not
1216
-     *
1217
-     * @return mixed &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1218
-     *               'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1219
-     * @throws CompilationException
1220
-     */
1221
-    public function &findBlock($type, $closeAlong = false)
1222
-    {
1223
-        if ($closeAlong === true) {
1224
-            while ($b = end($this->stack)) {
1225
-                if ($b['type'] === $type) {
1226
-                    return $this->stack[key($this->stack)];
1227
-                }
1228
-                $this->push($this->removeTopBlock(), 0);
1229
-            }
1230
-        } else {
1231
-            end($this->stack);
1232
-            while ($b = current($this->stack)) {
1233
-                if ($b['type'] === $type) {
1234
-                    return $this->stack[key($this->stack)];
1235
-                }
1236
-                prev($this->stack);
1237
-            }
1238
-        }
1239
-
1240
-        throw new CompilationException($this, 'A parent block of type "' . $type . '" is required and can not be found');
1241
-    }
1242
-
1243
-    /**
1244
-     * Returns a reference to the current block array.
1245
-     *
1246
-     * @return array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1247
-     *                'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1248
-     */
1249
-    public function &getCurrentBlock()
1250
-    {
1251
-        return $this->curBlock;
1252
-    }
1253
-
1254
-    /**
1255
-     * Removes the block at the top of the stack and calls its postProcessing() method.
1256
-     *
1257
-     * @return string the postProcessing() method's output
1258
-     * @throws CompilationException
1259
-     */
1260
-    public function removeTopBlock()
1261
-    {
1262
-        if ($this->debug) {
1263
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1264
-        }
1265
-
1266
-        $o = array_pop($this->stack);
1267
-        if ($o === null) {
1268
-            throw new CompilationException($this, 'Syntax malformation, a block of unknown type was closed but was not opened.');
1269
-        }
1270
-        if ($o['custom']) {
1271
-            $class = $o['class'];
1272
-        } else {
1273
-            $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($o['type']);
1274
-        }
1275
-
1276
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1277
-
1278
-        return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1279
-    }
1280
-
1281
-    /**
1282
-     * Returns the compiled parameters (for example a variable's compiled parameter will be "$this->scope['key']") out
1283
-     * of the given parameter array.
1284
-     *
1285
-     * @param array $params parameter array
1286
-     *
1287
-     * @return array filtered parameters
1288
-     */
1289
-    public function getCompiledParams(array $params)
1290
-    {
1291
-        foreach ($params as $k => $p) {
1292
-            if (is_array($p)) {
1293
-                $params[$k] = $p[0];
1294
-            }
1295
-        }
1296
-
1297
-        return $params;
1298
-    }
1299
-
1300
-    /**
1301
-     * Returns the real parameters (for example a variable's real parameter will be its key, etc) out of the given
1302
-     * parameter array.
1303
-     *
1304
-     * @param array $params parameter array
1305
-     *
1306
-     * @return array filtered parameters
1307
-     */
1308
-    public function getRealParams(array $params)
1309
-    {
1310
-        foreach ($params as $k => $p) {
1311
-            if (is_array($p)) {
1312
-                $params[$k] = $p[1];
1313
-            }
1314
-        }
1315
-
1316
-        return $params;
1317
-    }
1318
-
1319
-    /**
1320
-     * Returns the token of each parameter out of the given parameter array.
1321
-     *
1322
-     * @param array $params parameter array
1323
-     *
1324
-     * @return array tokens
1325
-     */
1326
-    public function getParamTokens(array $params)
1327
-    {
1328
-        foreach ($params as $k => $p) {
1329
-            if (is_array($p)) {
1330
-                $params[$k] = isset($p[2]) ? $p[2] : 0;
1331
-            }
1332
-        }
1333
-
1334
-        return $params;
1335
-    }
1336
-
1337
-    /**
1338
-     * Entry point of the parser, it redirects calls to other parse* functions.
1339
-     *
1340
-     * @param string $in            the string within which we must parse something
1341
-     * @param int    $from          the starting offset of the parsed area
1342
-     * @param int    $to            the ending offset of the parsed area
1343
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1344
-     *                              default
1345
-     * @param string $curBlock      the current parser-block being processed
1346
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1347
-     *                              or null by default
1348
-     *
1349
-     * @return string parsed values
1350
-     * @throws CompilationException
1351
-     */
1352
-    protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1353
-    {
1354
-        if ($this->debug) {
1355
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1356
-        }
1357
-
1358
-        if ($to === null) {
1359
-            $to = strlen($in);
1360
-        }
1361
-        $first = substr($in, $from, 1);
1362
-
1363
-        if ($first === false) {
1364
-            throw new CompilationException($this, 'Unexpected EOF, a template tag was not closed');
1365
-        }
1366
-
1367
-        while ($first === ' ' || $first === "\n" || $first === "\t" || $first === "\r") {
1368
-            if ($curBlock === 'root' && substr($in, $from, strlen($this->rd)) === $this->rd) {
1369
-                // end template tag
1370
-                $pointer += strlen($this->rd);
1371
-                if ($this->debug) {
1372
-                    echo 'TEMPLATE PARSING ENDED' . "\n";
1373
-                }
1374
-
1375
-                return false;
1376
-            }
1377
-            ++ $from;
1378
-            if ($pointer !== null) {
1379
-                ++ $pointer;
1380
-            }
1381
-            if ($from >= $to) {
1382
-                if (is_array($parsingParams)) {
1383
-                    return $parsingParams;
1384
-                } else {
1385
-                    return '';
1386
-                }
1387
-            }
1388
-            $first = $in[$from];
1389
-        }
1390
-
1391
-        $substr = substr($in, $from, $to - $from);
1392
-
1393
-        if ($this->debug) {
1394
-            echo 'PARSE CALL : PARSING "<b>' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . '</b>" @ ' . $from . ':' . $to . ' in ' . $curBlock . ' : pointer=' . $pointer . "\n";
1395
-        }
1396
-        $parsed = '';
1397
-
1398
-        if ($curBlock === 'root' && $first === '*') {
1399
-            $src      = $this->getTemplateSource();
1400
-            $startpos = $this->getPointer() - strlen($this->ld);
1401
-            if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1402
-                if ($startpos > 0) {
1403
-                    do {
1404
-                        $char = substr($src, -- $startpos, 1);
1405
-                        if ($char == "\n") {
1406
-                            ++ $startpos;
1407
-                            $whitespaceStart = true;
1408
-                            break;
1409
-                        }
1410
-                    }
1411
-                    while ($startpos > 0 && ($char == ' ' || $char == "\t"));
1412
-                }
1413
-
1414
-                if (!isset($whitespaceStart)) {
1415
-                    $startpos = $this->getPointer();
1416
-                } else {
1417
-                    $pointer -= $this->getPointer() - $startpos;
1418
-                }
1419
-
1420
-                if ($this->allowNestedComments && strpos($src, $this->ld . '*', $this->getPointer()) !== false) {
1421
-                    $comOpen  = $this->ld . '*';
1422
-                    $comClose = '*' . $this->rd;
1423
-                    $level    = 1;
1424
-                    $ptr      = $this->getPointer();
1425
-
1426
-                    while ($level > 0 && $ptr < strlen($src)) {
1427
-                        $open  = strpos($src, $comOpen, $ptr);
1428
-                        $close = strpos($src, $comClose, $ptr);
1429
-
1430
-                        if ($open !== false && $close !== false) {
1431
-                            if ($open < $close) {
1432
-                                $ptr = $open + strlen($comOpen);
1433
-                                ++ $level;
1434
-                            } else {
1435
-                                $ptr = $close + strlen($comClose);
1436
-                                -- $level;
1437
-                            }
1438
-                        } elseif ($open !== false) {
1439
-                            $ptr = $open + strlen($comOpen);
1440
-                            ++ $level;
1441
-                        } elseif ($close !== false) {
1442
-                            $ptr = $close + strlen($comClose);
1443
-                            -- $level;
1444
-                        } else {
1445
-                            $ptr = strlen($src);
1446
-                        }
1447
-                    }
1448
-                    $endpos = $ptr - strlen('*' . $this->rd);
1449
-                } else {
1450
-                    $endpos = strpos($src, '*' . $this->rd, $startpos);
1451
-                    if ($endpos == false) {
1452
-                        throw new CompilationException($this, 'Un-ended comment');
1453
-                    }
1454
-                }
1455
-                $pointer += $endpos - $startpos + strlen('*' . $this->rd);
1456
-                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*' . $this->rd)), $m)) {
1457
-                    $pointer += strlen($m[0]);
1458
-                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1459
-                }
1460
-
1461
-                return false;
1462
-            }
1463
-        }
1464
-
1465
-        if ($first === '$') {
1466
-            // var
1467
-            $out    = $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
1468
-            $parsed = 'var';
1469
-        } elseif ($first === '%' && preg_match('#^%[a-z_\\\\]#i', $substr)) {
1470
-            // Short constant
1471
-            $out = $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
1472
-        } elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1473
-            // string
1474
-            $out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1475
-        } elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?(' . (is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|') . '\s*\(|\s*' . $this->rdr . '|\s*;)/i', $substr)) {
1476
-            // func
1477
-            $out    = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1478
-            $parsed = 'func';
1479
-        } elseif ($first === ';') {
1480
-            // instruction end
1481
-            if ($this->debug) {
1482
-                echo 'END OF INSTRUCTION' . "\n";
1483
-            }
1484
-            if ($pointer !== null) {
1485
-                ++ $pointer;
1486
-            }
1487
-
1488
-            return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1489
-        } elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1490
-            // close block
1491
-            if (!empty($match[1]) && $match[1] == 'else') {
1492
-                throw new CompilationException($this, 'Else blocks must not be closed explicitly, they are automatically closed when their parent block is closed');
1493
-            }
1494
-            if (!empty($match[1]) && $match[1] == 'elseif') {
1495
-                throw new CompilationException($this, 'Elseif blocks must not be closed explicitly, they are automatically closed when their parent block is closed or a new else/elseif block is declared after them');
1496
-            }
1497
-            if ($pointer !== null) {
1498
-                $pointer += strlen($match[0]);
1499
-            }
1500
-            if (empty($match[1])) {
1501
-                if ($this->curBlock['type'] == 'else' || $this->curBlock['type'] == 'elseif') {
1502
-                    $pointer -= strlen($match[0]);
1503
-                }
1504
-                if ($this->debug) {
1505
-                    echo 'TOP BLOCK CLOSED' . "\n";
1506
-                }
1507
-
1508
-                return $this->removeTopBlock();
1509
-            } else {
1510
-                if ($this->debug) {
1511
-                    echo 'BLOCK OF TYPE ' . $match[1] . ' CLOSED' . "\n";
1512
-                }
1513
-
1514
-                return $this->removeBlock($match[1]);
1515
-            }
1516
-        } elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1517
-            // end template tag
1518
-            if ($this->debug) {
1519
-                echo 'TAG PARSING ENDED' . "\n";
1520
-            }
1521
-            $pointer += strlen($this->rd);
1522
-
1523
-            return false;
1524
-        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*=' . ($curBlock === 'array' ? '>?' : '') . ')(?:\s+|[^=]).*#i', $substr, $match)) {
1525
-            // named parameter
1526
-            if ($this->debug) {
1527
-                echo 'NAMED PARAM FOUND' . "\n";
1528
-            }
1529
-            $len = strlen($match[1]);
1530
-            while (substr($in, $from + $len, 1) === ' ') {
1531
-                ++ $len;
1532
-            }
1533
-            if ($pointer !== null) {
1534
-                $pointer += $len;
1535
-            }
1536
-
1537
-            $output = array(
1538
-                trim($match[1], " \t\r\n=>'\""),
1539
-                $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer)
1540
-            );
1541
-
1542
-            $parsingParams[] = $output;
1543
-
1544
-            return $parsingParams;
1545
-        } elseif (preg_match('#^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*::\$[a-z0-9_]+)#i', $substr, $match)) {
1546
-            // static member access
1547
-            $parsed = 'var';
1548
-            if (is_array($parsingParams)) {
1549
-                $parsingParams[] = array($match[1], $match[1]);
1550
-                $out             = $parsingParams;
1551
-            } else {
1552
-                $out = $match[1];
1553
-            }
1554
-            $pointer += strlen($match[1]);
1555
-        } elseif ($substr !== '' && (is_array($parsingParams) || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'expression')) {
1556
-            // unquoted string, bool or number
1557
-            $out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1558
-        } else {
1559
-            // parse error
1560
-            throw new CompilationException($this, 'Parse error in "' . substr($in, $from, $to - $from) . '"');
1561
-        }
1562
-
1563
-        if (empty($out)) {
1564
-            return '';
1565
-        }
1566
-
1567
-        $substr = substr($in, $pointer, $to - $pointer);
1568
-
1569
-        // var parsed, check if any var-extension applies
1570
-        if ($parsed === 'var') {
1571
-            if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1572
-                if ($this->debug) {
1573
-                    echo 'PARSING POST-VAR EXPRESSION ' . $substr . "\n";
1574
-                }
1575
-                // parse expressions
1576
-                $pointer += strlen($match[0]) - 1;
1577
-                if (is_array($parsingParams)) {
1578
-                    if ($match[2] == '$') {
1579
-                        $expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1580
-                    } else {
1581
-                        $expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1582
-                    }
1583
-                    $out[count($out) - 1][0] .= $match[1] . $expr[0][0];
1584
-                    $out[count($out) - 1][1] .= $match[1] . $expr[0][1];
1585
-                } else {
1586
-                    if ($match[2] == '$') {
1587
-                        $expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
1588
-                    } else {
1589
-                        $expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1590
-                    }
1591
-                    if (is_array($out) && is_array($expr)) {
1592
-                        $out[0] .= $match[1] . $expr[0];
1593
-                        $out[1] .= $match[1] . $expr[1];
1594
-                    } elseif (is_array($out)) {
1595
-                        $out[0] .= $match[1] . $expr;
1596
-                        $out[1] .= $match[1] . $expr;
1597
-                    } elseif (is_array($expr)) {
1598
-                        $out .= $match[1] . $expr[0];
1599
-                    } else {
1600
-                        $out .= $match[1] . $expr;
1601
-                    }
1602
-                }
1603
-            } elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1604
-                if ($this->debug) {
1605
-                    echo 'PARSING POST-VAR ASSIGNMENT ' . $substr . "\n";
1606
-                }
1607
-                // parse assignment
1608
-                $value    = $match[2];
1609
-                $operator = trim($match[1]);
1610
-                if (substr($value, 0, 1) == '=') {
1611
-                    throw new CompilationException($this, 'Unexpected "=" in <em>' . $substr . '</em>');
1612
-                }
1613
-
1614
-                if ($pointer !== null) {
1615
-                    $pointer += strlen($match[1]);
1616
-                }
1617
-
1618
-                if ($operator !== '++' && $operator !== '--') {
1619
-                    $parts = array();
1620
-                    $ptr   = 0;
1621
-                    $parts = $this->parse($value, 0, strlen($value), $parts, 'condition', $ptr);
1622
-                    $pointer += $ptr;
1623
-
1624
-                    // load if plugin
1625
-                    try {
1626
-                        $this->getPluginType('if');
1627
-                    }
1628
-                    catch (Exception $e) {
1629
-                        throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1630
-                    }
1631
-
1632
-                    $parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS . 'PluginIf', 'init'), 1);
1633
-                    $tokens = $this->getParamTokens($parts);
1634
-                    $parts  = $this->getCompiledParams($parts);
1635
-
1636
-                    $value = PluginIf::replaceKeywords($parts['*'], $tokens['*'], $this);
1637
-                    $echo  = '';
1638
-                } else {
1639
-                    $value = array();
1640
-                    $echo  = 'echo ';
1641
-                }
1642
-
1643
-                if ($this->autoEscape) {
1644
-                    $out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1645
-                }
1646
-                $out = self::PHP_OPEN . $echo . $out . $operator . implode(' ', $value) . self::PHP_CLOSE;
1647
-            } elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1648
-                // parse namedparam with var as name (only for array)
1649
-                if ($this->debug) {
1650
-                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND' . "\n";
1651
-                }
1652
-                $len = strlen($match[1]);
1653
-                $var = $out[count($out) - 1];
1654
-                $pointer += $len;
1655
-
1656
-                $output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
1657
-
1658
-                $parsingParams[] = $output;
1659
-
1660
-                return $parsingParams;
1661
-            }
1662
-        }
1663
-
1664
-        if ($curBlock !== 'modifier' && ($parsed === 'func' || $parsed === 'var') && preg_match('#^(\|@?[a-z0-9_]+(:.*)?)+#i', $substr, $match)) {
1665
-            // parse modifier on funcs or vars
1666
-            $srcPointer = $pointer;
1667
-            if (is_array($parsingParams)) {
1668
-                $tmp                     = $this->replaceModifiers(
1669
-                    array(
1670
-                    null,
1671
-                    null,
1672
-                    $out[count($out) - 1][0],
1673
-                    $match[0]
1674
-                    ), $curBlock, $pointer
1675
-                );
1676
-                $out[count($out) - 1][0] = $tmp;
1677
-                $out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1678
-            } else {
1679
-                $out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1680
-            }
1681
-        }
1682
-
1683
-        // func parsed, check if any func-extension applies
1684
-        if ($parsed === 'func' && preg_match('#^->[a-z0-9_]+(\s*\(.+|->[a-z_].*)?#is', $substr, $match)) {
1685
-            // parse method call or property read
1686
-            $ptr = 0;
1687
-
1688
-            if (is_array($parsingParams)) {
1689
-                $output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1690
-
1691
-                $out[count($out) - 1][0] = $output;
1692
-                $out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1693
-            } else {
1694
-                $out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1695
-            }
1696
-
1697
-            $pointer += $ptr;
1698
-        }
1699
-
1700
-        if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1701
-            return self::PHP_OPEN . 'echo ' . $out . ';' . self::PHP_CLOSE;
1702
-        } else {
1703
-            return $out;
1704
-        }
1705
-    }
1706
-
1707
-    /**
1708
-     * Parses a function call.
1709
-     *
1710
-     * @param string $in            the string within which we must parse something
1711
-     * @param int    $from          the starting offset of the parsed area
1712
-     * @param int    $to            the ending offset of the parsed area
1713
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1714
-     *                              default
1715
-     * @param string $curBlock      the current parser-block being processed
1716
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1717
-     *                              or null by default
1718
-     *
1719
-     * @return string parsed values
1720
-     * @throws CompilationException
1721
-     * @throws Exception
1722
-     * @throws SecurityException
1723
-     */
1724
-    protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1725
-    {
1726
-        $output = '';
1727
-        $cmdstr = substr($in, $from, $to - $from);
1728
-        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*' . $this->rdr . '|\s*;)?/i', $cmdstr, $match);
1729
-
1730
-        if (empty($match[1])) {
1731
-            throw new CompilationException($this, 'Parse error, invalid function name : ' . substr($cmdstr, 0, 15));
1732
-        }
1733
-
1734
-        $func = $match[1];
1735
-
1736
-        if (!empty($match[2])) {
1737
-            $cmdstr = $match[1];
1738
-        }
1739
-
1740
-        if ($this->debug) {
1741
-            echo 'FUNC FOUND (' . $func . ')' . "\n";
1742
-        }
1743
-
1744
-        $paramsep = '';
1745
-
1746
-        if (is_array($parsingParams) || $curBlock != 'root') {
1747
-            $paramspos = strpos($cmdstr, '(');
1748
-            $paramsep  = ')';
1749
-        } elseif (preg_match_all('#^\s*[\\\\:a-z0-9_]+(\s*\(|\s+[^(])#i', $cmdstr, $match, PREG_OFFSET_CAPTURE)) {
1750
-            $paramspos = $match[1][0][1];
1751
-            $paramsep  = substr($match[1][0][0], - 1) === '(' ? ')' : '';
1752
-            if ($paramsep === ')') {
1753
-                $paramspos += strlen($match[1][0][0]) - 1;
1754
-                if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1755
-                    $paramsep = '';
1756
-                    if (strlen($match[1][0][0]) > 1) {
1757
-                        -- $paramspos;
1758
-                    }
1759
-                }
1760
-            }
1761
-        } else {
1762
-            $paramspos = false;
1763
-        }
1764
-
1765
-        $state = 0;
1766
-
1767
-        if ($paramspos === false) {
1768
-            $params = array();
1769
-
1770
-            if ($curBlock !== 'root') {
1771
-                return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1772
-            }
1773
-        } else {
1774
-            if ($curBlock === 'condition') {
1775
-                // load if plugin
1776
-                $this->getPluginType('if');
1777
-
1778
-                if (PluginIf::replaceKeywords(array($func), array(self::T_UNQUOTED_STRING), $this) !== array($func)) {
1779
-                    return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1780
-                }
1781
-            }
1782
-            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1783
-            $paramstr   = substr($cmdstr, $paramspos + 1);
1784
-            if (substr($paramstr, - 1, 1) === $paramsep) {
1785
-                $paramstr = substr($paramstr, 0, - 1);
1786
-            }
1787
-
1788
-            if (strlen($paramstr) === 0) {
1789
-                $params   = array();
1790
-                $paramstr = '';
1791
-            } else {
1792
-                $ptr    = 0;
1793
-                $params = array();
1794
-                if ($func === 'empty') {
1795
-                    $params = $this->parseVar($paramstr, $ptr, strlen($paramstr), $params, 'root', $ptr);
1796
-                } else {
1797
-                    while ($ptr < strlen($paramstr)) {
1798
-                        while (true) {
1799
-                            if ($ptr >= strlen($paramstr)) {
1800
-                                break 2;
1801
-                            }
1802
-
1803
-                            if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1804
-                                if ($this->debug) {
1805
-                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT ' . $ptr . "\n";
1806
-                                }
1807
-                                break 2;
1808
-                            } elseif ($paramstr[$ptr] === ';') {
1809
-                                ++ $ptr;
1810
-                                if ($this->debug) {
1811
-                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT ' . $ptr . "\n";
1812
-                                }
1813
-                                break 2;
1814
-                            } elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1815
-                                if ($this->debug) {
1816
-                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT ' . $ptr . "\n";
1817
-                                }
1818
-                                break 2;
1819
-                            } elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1820
-                                if ($this->debug) {
1821
-                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT ' . $ptr . "\n";
1822
-                                }
1823
-                                break 2;
1824
-                            }
1825
-
1826
-                            if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1827
-                                ++ $ptr;
1828
-                            } else {
1829
-                                break;
1830
-                            }
1831
-                        }
1832
-
1833
-                        if ($this->debug) {
1834
-                            echo 'FUNC START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
1835
-                        }
1836
-
1837
-                        if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
1838
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'condition', $ptr);
1839
-                        } elseif ($func === 'array') {
1840
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'array', $ptr);
1841
-                        } else {
1842
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'function', $ptr);
1843
-                        }
1844
-
1845
-                        if ($this->debug) {
1846
-                            echo 'PARAM PARSED, POINTER AT ' . $ptr . ' (' . substr($paramstr, $ptr - 1, 3) . ')' . "\n";
1847
-                        }
1848
-                    }
1849
-                }
1850
-                $paramstr = substr($paramstr, 0, $ptr);
1851
-                $state    = 0;
1852
-                foreach ($params as $k => $p) {
1853
-                    if (is_array($p) && is_array($p[1])) {
1854
-                        $state |= 2;
1855
-                    } else {
1856
-                        if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m) && $func !== 'array') {
1857
-                            $params[$k] = array($m[2], array('true', 'true'));
1858
-                        } else {
1859
-                            if ($state & 2 && $func !== 'array') {
1860
-                                throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
1861
-                            }
1862
-                            $state |= 1;
1863
-                        }
1864
-                    }
1865
-                }
1866
-            }
1867
-        }
1868
-
1869
-        if ($pointer !== null) {
1870
-            $pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1871
-            if ($this->debug) {
1872
-                echo 'FUNC ADDS ' . ((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)) . ' TO POINTER' . "\n";
1873
-            }
1874
-        }
1875
-
1876
-        if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1877
-            // handle static method calls with security policy
1878
-            if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1879
-                throw new SecurityException('Call to a disallowed php function : ' . $func);
1880
-            }
1881
-            $pluginType = Core::NATIVE_PLUGIN;
1882
-        } else {
1883
-            $pluginType = $this->getPluginType($func);
1884
-        }
1885
-
1886
-        // Blocks plugin
1887
-        if ($pluginType & Core::BLOCK_PLUGIN) {
1888
-            if ($curBlock !== 'root' || is_array($parsingParams)) {
1889
-                throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1890
-            }
1891
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
1892
-                return $this->addCustomBlock($func, $params, $state);
1893
-            } else {
1894
-                return $this->addBlock($func, $params, $state);
1895
-            }
1896
-        } elseif ($pluginType & Core::SMARTY_BLOCK) {
1897
-            if ($curBlock !== 'root' || is_array($parsingParams)) {
1898
-                throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1899
-            }
1900
-
1901
-            if ($state & 2) {
1902
-                array_unshift($params, array('__functype', array($pluginType, $pluginType)));
1903
-                array_unshift($params, array('__funcname', array($func, $func)));
1904
-            } else {
1905
-                array_unshift($params, array($pluginType, $pluginType));
1906
-                array_unshift($params, array($func, $func));
1907
-            }
1908
-
1909
-            return $this->addBlock('smartyinterface', $params, $state);
1910
-        }
1911
-
1912
-        // Functions plugin
1913
-        if ($pluginType & Core::NATIVE_PLUGIN || $pluginType & Core::SMARTY_FUNCTION || $pluginType & Core::SMARTY_BLOCK) {
1914
-            $params = $this->mapParams($params, null, $state);
1915
-        } elseif ($pluginType & Core::CLASS_PLUGIN) {
1916
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
1917
-                $params = $this->mapParams(
1918
-                    $params, array(
1919
-                    $this->customPlugins[$func]['class'],
1920
-                    $this->customPlugins[$func]['function']
1921
-                ), $state);
1922
-            } else {
1923
-                if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
1924
-                    $params = $this->mapParams($params, array(
1925
-                        'Plugin' . Core::toCamelCase($func),
1926
-                        ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1927
-                    ), $state);
1928
-                } else {
1929
-                    $params = $this->mapParams($params, array(
1930
-                        Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
1931
-                        ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1932
-                    ), $state);
1933
-                }
1934
-            }
1935
-        } elseif ($pluginType & Core::FUNC_PLUGIN) {
1936
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
1937
-                $params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1938
-            } else {
1939
-                // Custom plugin
1940
-                if (function_exists('Plugin' . Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ?
1941
-                        'Compile' : '')) !== false) {
1942
-                    $params = $this->mapParams($params, 'Plugin' . Core::toCamelCase($func) . (($pluginType &
1943
-                            Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1944
-                } // Builtin helper plugin
1945
-                elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . (
1946
-                    ($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '')) !== false) {
1947
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase
1948
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1949
-                } // Builtin function plugin
1950
-                else {
1951
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
1952
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1953
-                }
1954
-            }
1955
-        } elseif ($pluginType & Core::SMARTY_MODIFIER) {
1956
-            $output = 'smarty_modifier_' . $func . '(' . implode(', ', $params) . ')';
1957
-        } elseif ($pluginType & Core::PROXY_PLUGIN) {
1958
-            $params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
1959
-        } elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
1960
-            // transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
1961
-            $map = array();
1962
-            foreach ($this->templatePlugins[$func]['params'] as $param => $defValue) {
1963
-                if ($param == 'rest') {
1964
-                    $param = '*';
1965
-                }
1966
-                $hasDefault = $defValue !== null;
1967
-                if ($defValue === 'null') {
1968
-                    $defValue = null;
1969
-                } elseif ($defValue === 'false') {
1970
-                    $defValue = false;
1971
-                } elseif ($defValue === 'true') {
1972
-                    $defValue = true;
1973
-                } elseif (preg_match('#^([\'"]).*?\1$#', $defValue)) {
1974
-                    $defValue = substr($defValue, 1, - 1);
1975
-                }
1976
-                $map[] = array($param, $hasDefault, $defValue);
1977
-            }
1978
-
1979
-            $params = $this->mapParams($params, null, $state, $map);
1980
-        }
1981
-
1982
-        // only keep php-syntax-safe values for non-block plugins
1983
-        $tokens = array();
1984
-        foreach ($params as $k => $p) {
1985
-            $tokens[$k] = isset($p[2]) ? $p[2] : 0;
1986
-            $params[$k] = $p[0];
1987
-        }
1988
-        if ($pluginType & Core::NATIVE_PLUGIN) {
1989
-            if ($func === 'do') {
1990
-                if (isset($params['*'])) {
1991
-                    $output = implode(';', $params['*']) . ';';
1992
-                } else {
1993
-                    $output = '';
1994
-                }
1995
-
1996
-                if (is_array($parsingParams) || $curBlock !== 'root') {
1997
-                    throw new CompilationException($this, 'Do can not be used inside another function or block');
1998
-                } else {
1999
-                    return self::PHP_OPEN . $output . self::PHP_CLOSE;
2000
-                }
2001
-            } else {
2002
-                if (isset($params['*'])) {
2003
-                    $output = $func . '(' . implode(', ', $params['*']) . ')';
2004
-                } else {
2005
-                    $output = $func . '()';
2006
-                }
2007
-            }
2008
-        } elseif ($pluginType & Core::FUNC_PLUGIN) {
2009
-            if ($pluginType & Core::COMPILABLE_PLUGIN) {
2010
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2011
-                    $funcCompiler = $this->customPlugins[$func]['callback'];
2012
-                } else {
2013
-                    // Custom plugin
2014
-                    if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2015
-                        $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
2016
-                    } // Builtin helper plugin
2017
-                    elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2018
-                            'Compile') !== false) {
2019
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2020
-                            'Compile';
2021
-                    } // Builtin function plugin
2022
-                    else {
2023
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
2024
-                            'Compile';
2025
-                    }
2026
-                }
2027
-                array_unshift($params, $this);
2028
-                if ($func === 'tif') {
2029
-                    $params[] = $tokens;
2030
-                }
2031
-                $output = call_user_func_array($funcCompiler, $params);
2032
-            } else {
2033
-                array_unshift($params, '$this');
2034
-                $params = self::implode_r($params);
2035
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2036
-                    $callback = $this->customPlugins[$func]['callback'];
2037
-                    if ($callback instanceof Closure) {
2038
-                        $output = 'call_user_func($this->getCustomPlugin(\'' . $func . '\'), ' . $params . ')';
2039
-                    } else {
2040
-                        $output = 'call_user_func(\'' . $callback . '\', ' . $params . ')';
2041
-                    }
2042
-                } else {
2043
-                    // Custom plugin
2044
-                    if (function_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2045
-                        $output = 'Plugin' . Core::toCamelCase($func) . '(' . $params .
2046
-                            ')';
2047
-                    } // Builtin helper plugin
2048
-                    elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !==
2049
-                        false) {
2050
-                        $output = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . '(' .
2051
-                            $params . ')';
2052
-                    } // Builtin function plugin
2053
-                    else {
2054
-                        $output = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '(' .
2055
-                            $params . ')';
2056
-                    }
2057
-                }
2058
-            }
2059
-        } elseif ($pluginType & Core::CLASS_PLUGIN) {
2060
-            if ($pluginType & Core::COMPILABLE_PLUGIN) {
2061
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2062
-                    $callback = $this->customPlugins[$func]['callback'];
2063
-                    if (!is_array($callback)) {
2064
-                        if (!method_exists($callback, 'compile')) {
2065
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2066
-                        }
2067
-                        if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
2068
-                            $funcCompiler = array($callback, 'compile');
2069
-                        } else {
2070
-                            $funcCompiler = array(new $callback(), 'compile');
2071
-                        }
2072
-                    } else {
2073
-                        $funcCompiler = $callback;
2074
-                    }
2075
-                } else {
2076
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2077
-                        $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
2078
-                    } else {
2079
-                        $funcCompiler = array(
2080
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
2081
-                            'compile'
2082
-                        );
2083
-                    }
2084
-                    array_unshift($params, $this);
2085
-                }
2086
-                $output = call_user_func_array($funcCompiler, $params);
2087
-            } else {
2088
-                $params = self::implode_r($params);
2089
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
2090
-                    $callback = $this->customPlugins[$func]['callback'];
2091
-                    if (!is_array($callback)) {
2092
-                        if (!method_exists($callback, 'process')) {
2093
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2094
-                        }
2095
-                        if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
2096
-                            $output = 'call_user_func(array(\'' . $callback . '\', \'process\'), ' . $params . ')';
2097
-                        } else {
2098
-                            $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback . '\'), \'process\'), ' . $params . ')';
2099
-                        }
2100
-                    } elseif (is_object($callback[0])) {
2101
-                        $output = 'call_user_func(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), ' . $params . ')';
2102
-                    } elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
2103
-                        $output = 'call_user_func(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), ' . $params . ')';
2104
-                    } else {
2105
-                        $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback[0] . '\'), \'' . $callback[1] . '\'), ' . $params . ')';
2106
-                    }
2107
-                    if (empty($params)) {
2108
-                        $output = substr($output, 0, - 3) . ')';
2109
-                    }
2110
-                } else {
2111
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2112
-                        $output = '$this->classCall(\'Plugin' . $func . '\', array(' . $params . '))';
2113
-                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !==
2114
-                    false) {
2115
-                        $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\', 
34
+	/**
35
+	 * Constant that represents a php opening tag.
36
+	 * use it in case it needs to be adjusted
37
+	 *
38
+	 * @var string
39
+	 */
40
+	const PHP_OPEN = '<?php ';
41
+
42
+	/**
43
+	 * Constant that represents a php closing tag.
44
+	 * use it in case it needs to be adjusted
45
+	 *
46
+	 * @var string
47
+	 */
48
+	const PHP_CLOSE = '?>';
49
+
50
+	/**
51
+	 * Boolean flag to enable or disable debugging output.
52
+	 *
53
+	 * @var bool
54
+	 */
55
+	public $debug = false;
56
+
57
+	/**
58
+	 * Left script delimiter.
59
+	 *
60
+	 * @var string
61
+	 */
62
+	protected $ld = '{';
63
+
64
+	/**
65
+	 * Left script delimiter with escaped regex meta characters.
66
+	 *
67
+	 * @var string
68
+	 */
69
+	protected $ldr = '\\{';
70
+
71
+	/**
72
+	 * Right script delimiter.
73
+	 *
74
+	 * @var string
75
+	 */
76
+	protected $rd = '}';
77
+
78
+	/**
79
+	 * Right script delimiter with escaped regex meta characters.
80
+	 *
81
+	 * @var string
82
+	 */
83
+	protected $rdr = '\\}';
84
+
85
+	/**
86
+	 * Defines whether the nested comments should be parsed as nested or not.
87
+	 * defaults to false (classic block comment parsing as in all languages)
88
+	 *
89
+	 * @var bool
90
+	 */
91
+	protected $allowNestedComments = false;
92
+
93
+	/**
94
+	 * Defines whether opening and closing tags can contain spaces before valid data or not.
95
+	 * turn to true if you want to be sloppy with the syntax, but when set to false it allows
96
+	 * to skip javascript and css tags as long as they are in the form "{ something", which is
97
+	 * nice. default is false.
98
+	 *
99
+	 * @var bool
100
+	 */
101
+	protected $allowLooseOpenings = false;
102
+
103
+	/**
104
+	 * Defines whether the compiler will automatically html-escape variables or not.
105
+	 * default is false
106
+	 *
107
+	 * @var bool
108
+	 */
109
+	protected $autoEscape = false;
110
+
111
+	/**
112
+	 * Security policy object.
113
+	 *
114
+	 * @var SecurityPolicy
115
+	 */
116
+	protected $securityPolicy;
117
+
118
+	/**
119
+	 * Stores the custom plugins registered with this compiler.
120
+	 *
121
+	 * @var array
122
+	 */
123
+	protected $customPlugins = array();
124
+
125
+	/**
126
+	 * Stores the template plugins registered with this compiler.
127
+	 *
128
+	 * @var array
129
+	 */
130
+	protected $templatePlugins = array();
131
+
132
+	/**
133
+	 * Stores the pre- and post-processors callbacks.
134
+	 *
135
+	 * @var array
136
+	 */
137
+	protected $processors = array('pre' => array(), 'post' => array());
138
+
139
+	/**
140
+	 * Stores a list of plugins that are used in the currently compiled
141
+	 * template, and that are not compilable. these plugins will be loaded
142
+	 * during the template's runtime if required.
143
+	 * it is a 1D array formatted as key:pluginName value:pluginType
144
+	 *
145
+	 * @var array
146
+	 */
147
+	protected $usedPlugins;
148
+
149
+	/**
150
+	 * Stores the template undergoing compilation.
151
+	 *
152
+	 * @var string
153
+	 */
154
+	protected $template;
155
+
156
+	/**
157
+	 * Stores the current pointer position inside the template.
158
+	 *
159
+	 * @var int
160
+	 */
161
+	protected $pointer;
162
+
163
+	/**
164
+	 * Stores the current line count inside the template for debugging purposes.
165
+	 *
166
+	 * @var int
167
+	 */
168
+	protected $line;
169
+
170
+	/**
171
+	 * Stores the current template source while compiling it.
172
+	 *
173
+	 * @var string
174
+	 */
175
+	protected $templateSource;
176
+
177
+	/**
178
+	 * Stores the data within which the scope moves.
179
+	 *
180
+	 * @var array
181
+	 */
182
+	protected $data;
183
+
184
+	/**
185
+	 * Variable scope of the compiler, set to null if
186
+	 * it can not be resolved to a static string (i.e. if some
187
+	 * plugin defines a new scope based on a variable array key).
188
+	 *
189
+	 * @var mixed
190
+	 */
191
+	protected $scope;
192
+
193
+	/**
194
+	 * Variable scope tree, that allows to rebuild the current
195
+	 * scope if required, i.e. when going to a parent level.
196
+	 *
197
+	 * @var array
198
+	 */
199
+	protected $scopeTree;
200
+
201
+	/**
202
+	 * Block plugins stack, accessible through some methods.
203
+	 *
204
+	 * @see findBlock
205
+	 * @see getCurrentBlock
206
+	 * @see addBlock
207
+	 * @see addCustomBlock
208
+	 * @see injectBlock
209
+	 * @see removeBlock
210
+	 * @see removeTopBlock
211
+	 * @var array
212
+	 */
213
+	protected $stack = array();
214
+
215
+	/**
216
+	 * Current block at the top of the block plugins stack,
217
+	 * accessible through getCurrentBlock.
218
+	 *
219
+	 * @see getCurrentBlock
220
+	 * @var array
221
+	 */
222
+	protected $curBlock;
223
+
224
+	/**
225
+	 * Current dwoo object that uses this compiler, or null.
226
+	 *
227
+	 * @var Core
228
+	 */
229
+	public $dwoo;
230
+
231
+	/**
232
+	 * Holds an instance of this class, used by getInstance when you don't
233
+	 * provide a custom compiler in order to save resources.
234
+	 *
235
+	 * @var Compiler
236
+	 */
237
+	protected static $instance;
238
+
239
+	/**
240
+	 * Token types.
241
+	 *
242
+	 * @var int
243
+	 */
244
+	const T_UNQUOTED_STRING = 1;
245
+	const T_NUMERIC         = 2;
246
+	const T_NULL            = 4;
247
+	const T_BOOL            = 8;
248
+	const T_MATH            = 16;
249
+	const T_BREAKCHAR       = 32;
250
+
251
+	/**
252
+	 * Compiler constructor.
253
+	 * saves the created instance so that child templates get the same one
254
+	 */
255
+	public function __construct()
256
+	{
257
+		self::$instance = $this;
258
+	}
259
+
260
+	/**
261
+	 * Sets the delimiters to use in the templates.
262
+	 * delimiters can be multi-character strings but should not be one of those as they will
263
+	 * make it very hard to work with templates or might even break the compiler entirely : "\", "$", "|", ":" and
264
+	 * finally "#" only if you intend to use config-vars with the #var# syntax.
265
+	 *
266
+	 * @param string $left  left delimiter
267
+	 * @param string $right right delimiter
268
+	 */
269
+	public function setDelimiters($left, $right)
270
+	{
271
+		$this->ld  = $left;
272
+		$this->rd  = $right;
273
+		$this->ldr = preg_quote($left, '/');
274
+		$this->rdr = preg_quote($right, '/');
275
+	}
276
+
277
+	/**
278
+	 * Returns the left and right template delimiters.
279
+	 *
280
+	 * @return array containing the left and the right delimiters
281
+	 */
282
+	public function getDelimiters()
283
+	{
284
+		return array($this->ld, $this->rd);
285
+	}
286
+
287
+	/**
288
+	 * Sets the way to handle nested comments, if set to true
289
+	 * {* foo {* some other *} comment *} will be stripped correctly.
290
+	 * if false it will remove {* foo {* some other *} and leave "comment *}" alone,
291
+	 * this is the default behavior
292
+	 *
293
+	 * @param bool $allow allow nested comments or not, defaults to true (but the default internal value is false)
294
+	 */
295
+	public function setNestedCommentsHandling($allow = true)
296
+	{
297
+		$this->allowNestedComments = (bool)$allow;
298
+	}
299
+
300
+	/**
301
+	 * Returns the nested comments handling setting.
302
+	 *
303
+	 * @see    setNestedCommentsHandling
304
+	 * @return bool true if nested comments are allowed
305
+	 */
306
+	public function getNestedCommentsHandling()
307
+	{
308
+		return $this->allowNestedComments;
309
+	}
310
+
311
+	/**
312
+	 * Sets the tag openings handling strictness, if set to true, template tags can
313
+	 * contain spaces before the first function/string/variable such as { $foo} is valid.
314
+	 * if set to false (default setting), { $foo} is invalid but that is however a good thing
315
+	 * as it allows css (i.e. #foo { color:red; }) to be parsed silently without triggering
316
+	 * an error, same goes for javascript.
317
+	 *
318
+	 * @param bool $allow true to allow loose handling, false to restore default setting
319
+	 */
320
+	public function setLooseOpeningHandling($allow = false)
321
+	{
322
+		$this->allowLooseOpenings = (bool)$allow;
323
+	}
324
+
325
+	/**
326
+	 * Returns the tag openings handling strictness setting.
327
+	 *
328
+	 * @see    setLooseOpeningHandling
329
+	 * @return bool true if loose tags are allowed
330
+	 */
331
+	public function getLooseOpeningHandling()
332
+	{
333
+		return $this->allowLooseOpenings;
334
+	}
335
+
336
+	/**
337
+	 * Changes the auto escape setting.
338
+	 * if enabled, the compiler will automatically html-escape variables,
339
+	 * unless they are passed through the safe function such as {$var|safe}
340
+	 * or {safe $var}
341
+	 * default setting is disabled/false
342
+	 *
343
+	 * @param bool $enabled set to true to enable, false to disable
344
+	 */
345
+	public function setAutoEscape($enabled)
346
+	{
347
+		$this->autoEscape = (bool)$enabled;
348
+	}
349
+
350
+	/**
351
+	 * Returns the auto escape setting.
352
+	 * default setting is disabled/false
353
+	 *
354
+	 * @return bool
355
+	 */
356
+	public function getAutoEscape()
357
+	{
358
+		return $this->autoEscape;
359
+	}
360
+
361
+	/**
362
+	 * Adds a preprocessor to the compiler, it will be called
363
+	 * before the template is compiled.
364
+	 *
365
+	 * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to
366
+	 *                        true
367
+	 * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else
368
+	 *                        you must provide a valid callback
369
+	 */
370
+	public function addPreProcessor($callback, $autoload = false)
371
+	{
372
+		if ($autoload) {
373
+			$name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', Core::toCamelCase($callback));
374
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . $name;
375
+
376
+			if (class_exists($class)) {
377
+				$callback = array(new $class($this), 'process');
378
+			} elseif (function_exists($class)) {
379
+				$callback = $class;
380
+			} else {
381
+				$callback = array('autoload' => true, 'class' => $class, 'name' => $name);
382
+			}
383
+
384
+			$this->processors['pre'][] = $callback;
385
+		} else {
386
+			$this->processors['pre'][] = $callback;
387
+		}
388
+	}
389
+
390
+	/**
391
+	 * Removes a preprocessor from the compiler.
392
+	 *
393
+	 * @param mixed $callback either a valid callback to the preprocessor or a simple name if it was autoloaded
394
+	 */
395
+	public function removePreProcessor($callback)
396
+	{
397
+		if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
398
+			unset($this->processors['pre'][$index]);
399
+		} elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
400
+					$callback),
401
+				$this->processors['pre'], true)) !== false) {
402
+			unset($this->processors['pre'][$index]);
403
+		} else {
404
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
405
+			foreach ($this->processors['pre'] as $index => $proc) {
406
+				if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
407
+					unset($this->processors['pre'][$index]);
408
+					break;
409
+				}
410
+			}
411
+		}
412
+	}
413
+
414
+	/**
415
+	 * Adds a postprocessor to the compiler, it will be called
416
+	 * before the template is compiled.
417
+	 *
418
+	 * @param mixed $callback either a valid callback to the postprocessor or a simple name if the autoload is set to
419
+	 *                        true
420
+	 * @param bool  $autoload if set to true, the postprocessor is auto-loaded from one of the plugin directories, else
421
+	 *                        you must provide a valid callback
422
+	 */
423
+	public function addPostProcessor($callback, $autoload = false)
424
+	{
425
+		if ($autoload) {
426
+			$name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
427
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . Core::toCamelCase($name);
428
+
429
+			if (class_exists($class)) {
430
+				$callback = array(new $class($this), 'process');
431
+			} elseif (function_exists($class)) {
432
+				$callback = $class;
433
+			} else {
434
+				$callback = array('autoload' => true, 'class' => $class, 'name' => $name);
435
+			}
436
+
437
+			$this->processors['post'][] = $callback;
438
+		} else {
439
+			$this->processors['post'][] = $callback;
440
+		}
441
+	}
442
+
443
+	/**
444
+	 * Removes a postprocessor from the compiler.
445
+	 *
446
+	 * @param mixed $callback either a valid callback to the postprocessor or a simple name if it was autoloaded
447
+	 */
448
+	public function removePostProcessor($callback)
449
+	{
450
+		if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
451
+			unset($this->processors['post'][$index]);
452
+		} elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
453
+					$callback),
454
+				$this->processors['post'], true)) !== false) {
455
+			unset($this->processors['post'][$index]);
456
+		} else {
457
+			$class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
458
+			foreach ($this->processors['post'] as $index => $proc) {
459
+				if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
460
+					unset($this->processors['post'][$index]);
461
+					break;
462
+				}
463
+			}
464
+		}
465
+	}
466
+
467
+	/**
468
+	 * Internal function to autoload processors at runtime if required.
469
+	 *
470
+	 * @param string $class the class/function name
471
+	 * @param string $name  the plugin name (without Dwoo_Plugin_ prefix)
472
+	 *
473
+	 * @return array|string
474
+	 * @throws Exception
475
+	 */
476
+	protected function loadProcessor($class, $name)
477
+	{
478
+		if (!class_exists($class) && !function_exists($class)) {
479
+			try {
480
+				$this->getDwoo()->getLoader()->loadPlugin($name);
481
+			}
482
+			catch (Exception $e) {
483
+				throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
484
+			}
485
+		}
486
+
487
+		if (class_exists($class)) {
488
+			return array(new $class($this), 'process');
489
+		}
490
+
491
+		if (function_exists($class)) {
492
+			return $class;
493
+		}
494
+
495
+		throw new Exception('Wrong processor name, when using autoload the processor must be in one of your plugin dir as "name.php" containg a class or function named "Dwoo_Processor_name"');
496
+	}
497
+
498
+	/**
499
+	 * Adds an used plugin, this is reserved for use by the {template} plugin.
500
+	 * this is required so that plugin loading bubbles up from loaded
501
+	 * template files to the current one
502
+	 *
503
+	 * @private
504
+	 *
505
+	 * @param string $name function name
506
+	 * @param int    $type plugin type (Core::*_PLUGIN)
507
+	 */
508
+	public function addUsedPlugin($name, $type)
509
+	{
510
+		$this->usedPlugins[$name] = $type;
511
+	}
512
+
513
+	/**
514
+	 * Returns all the plugins this template uses.
515
+	 *
516
+	 * @private
517
+	 * @return  array the list of used plugins in the parsed template
518
+	 */
519
+	public function getUsedPlugins()
520
+	{
521
+		return $this->usedPlugins;
522
+	}
523
+
524
+	/**
525
+	 * Adds a template plugin, this is reserved for use by the {template} plugin.
526
+	 * this is required because the template functions are not declared yet
527
+	 * during compilation, so we must have a way of validating their argument
528
+	 * signature without using the reflection api
529
+	 *
530
+	 * @private
531
+	 *
532
+	 * @param string $name   function name
533
+	 * @param array  $params parameter array to help validate the function call
534
+	 * @param string $uuid   unique id of the function
535
+	 * @param string $body   function php code
536
+	 */
537
+	public function addTemplatePlugin($name, array $params, $uuid, $body = null)
538
+	{
539
+		$this->templatePlugins[$name] = array('params' => $params, 'body' => $body, 'uuid' => $uuid);
540
+	}
541
+
542
+	/**
543
+	 * Returns all the parsed sub-templates.
544
+	 *
545
+	 * @private
546
+	 * @return  array the parsed sub-templates
547
+	 */
548
+	public function getTemplatePlugins()
549
+	{
550
+		return $this->templatePlugins;
551
+	}
552
+
553
+	/**
554
+	 * Marks a template plugin as being called, which means its source must be included in the compiled template.
555
+	 *
556
+	 * @param string $name function name
557
+	 */
558
+	public function useTemplatePlugin($name)
559
+	{
560
+		$this->templatePlugins[$name]['called'] = true;
561
+	}
562
+
563
+	/**
564
+	 * Adds the custom plugins loaded into Dwoo to the compiler so it can load them.
565
+	 *
566
+	 * @see Core::addPlugin
567
+	 *
568
+	 * @param array $customPlugins an array of custom plugins
569
+	 */
570
+	public function setCustomPlugins(array $customPlugins)
571
+	{
572
+		$this->customPlugins = $customPlugins;
573
+	}
574
+
575
+	/**
576
+	 * Sets the security policy object to enforce some php security settings.
577
+	 * use this if untrusted persons can modify templates,
578
+	 * set it on the Dwoo object as it will be passed onto the compiler automatically
579
+	 *
580
+	 * @param SecurityPolicy $policy the security policy object
581
+	 */
582
+	public function setSecurityPolicy(SecurityPolicy $policy = null)
583
+	{
584
+		$this->securityPolicy = $policy;
585
+	}
586
+
587
+	/**
588
+	 * Returns the current security policy object or null by default.
589
+	 *
590
+	 * @return SecurityPolicy|null the security policy object if any
591
+	 */
592
+	public function getSecurityPolicy()
593
+	{
594
+		return $this->securityPolicy;
595
+	}
596
+
597
+	/**
598
+	 * Sets the pointer position.
599
+	 *
600
+	 * @param int  $position the new pointer position
601
+	 * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
602
+	 */
603
+	public function setPointer($position, $isOffset = false)
604
+	{
605
+		if ($isOffset) {
606
+			$this->pointer += $position;
607
+		} else {
608
+			$this->pointer = $position;
609
+		}
610
+	}
611
+
612
+	/**
613
+	 * Returns the current pointer position, only available during compilation of a template.
614
+	 *
615
+	 * @return int
616
+	 */
617
+	public function getPointer()
618
+	{
619
+		return $this->pointer;
620
+	}
621
+
622
+	/**
623
+	 * Sets the line number.
624
+	 *
625
+	 * @param int  $number   the new line number
626
+	 * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
627
+	 */
628
+	public function setLine($number, $isOffset = false)
629
+	{
630
+		if ($isOffset) {
631
+			$this->line += $number;
632
+		} else {
633
+			$this->line = $number;
634
+		}
635
+	}
636
+
637
+	/**
638
+	 * Returns the current line number, only available during compilation of a template.
639
+	 *
640
+	 * @return int
641
+	 */
642
+	public function getLine()
643
+	{
644
+		return $this->line;
645
+	}
646
+
647
+	/**
648
+	 * Returns the dwoo object that initiated this template compilation, only available during compilation of a
649
+	 * template.
650
+	 *
651
+	 * @return Core
652
+	 */
653
+	public function getDwoo()
654
+	{
655
+		return $this->dwoo;
656
+	}
657
+
658
+	/**
659
+	 * Overwrites the template that is being compiled.
660
+	 *
661
+	 * @param string $newSource   the template source that must replace the current one
662
+	 * @param bool   $fromPointer if set to true, only the source from the current pointer position is replaced
663
+	 *
664
+	 * @return void
665
+	 */
666
+	public function setTemplateSource($newSource, $fromPointer = false)
667
+	{
668
+		if ($fromPointer === true) {
669
+			$this->templateSource = substr($this->templateSource, 0, $this->pointer) . $newSource;
670
+		} else {
671
+			$this->templateSource = $newSource;
672
+		}
673
+	}
674
+
675
+	/**
676
+	 * Returns the template that is being compiled.
677
+	 *
678
+	 * @param mixed $fromPointer if set to true, only the source from the current pointer
679
+	 *                           position is returned, if a number is given it overrides the current pointer
680
+	 *
681
+	 * @return string the template or partial template
682
+	 */
683
+	public function getTemplateSource($fromPointer = false)
684
+	{
685
+		if ($fromPointer === true) {
686
+			return substr($this->templateSource, $this->pointer);
687
+		} elseif (is_numeric($fromPointer)) {
688
+			return substr($this->templateSource, $fromPointer);
689
+		} else {
690
+			return $this->templateSource;
691
+		}
692
+	}
693
+
694
+	/**
695
+	 * Resets the compilation pointer, effectively restarting the compilation process.
696
+	 * this is useful if a plugin modifies the template source since it might need to be recompiled
697
+	 */
698
+	public function recompile()
699
+	{
700
+		$this->setPointer(0);
701
+	}
702
+
703
+	/**
704
+	 * Compiles the provided string down to php code.
705
+	 *
706
+	 * @param Core      $dwoo
707
+	 * @param ITemplate $template the template to compile
708
+	 *
709
+	 * @return string a compiled php string
710
+	 * @throws CompilationException
711
+	 */
712
+	public function compile(Core $dwoo, ITemplate $template)
713
+	{
714
+		// init vars
715
+		//		$compiled = '';
716
+		$tpl                  = $template->getSource();
717
+		$ptr                  = 0;
718
+		$this->dwoo           = $dwoo;
719
+		$this->template       = $template;
720
+		$this->templateSource = &$tpl;
721
+		$this->pointer        = &$ptr;
722
+
723
+		while (true) {
724
+			// if pointer is at the beginning, reset everything, that allows a plugin to externally reset the compiler if everything must be reparsed
725
+			if ($ptr === 0) {
726
+				// resets variables
727
+				$this->usedPlugins     = array();
728
+				$this->data            = array();
729
+				$this->scope           = &$this->data;
730
+				$this->scopeTree       = array();
731
+				$this->stack           = array();
732
+				$this->line            = 1;
733
+				$this->templatePlugins = array();
734
+				// add top level block
735
+				$compiled                 = $this->addBlock('TopLevelBlock', array(), 0);
736
+				$this->stack[0]['buffer'] = '';
737
+
738
+				if ($this->debug) {
739
+					echo "\n";
740
+					echo 'COMPILER INIT' . "\n";
741
+				}
742
+
743
+				if ($this->debug) {
744
+					echo 'PROCESSING PREPROCESSORS (' . count($this->processors['pre']) . ')' . "\n";
745
+				}
746
+
747
+				// runs preprocessors
748
+				foreach ($this->processors['pre'] as $preProc) {
749
+					if (is_array($preProc) && isset($preProc['autoload'])) {
750
+						$preProc = $this->loadProcessor($preProc['class'], $preProc['name']);
751
+					}
752
+					if (is_array($preProc) && $preProc[0] instanceof Processor) {
753
+						$tpl = call_user_func($preProc, $tpl);
754
+					} else {
755
+						$tpl = call_user_func($preProc, $this, $tpl);
756
+					}
757
+				}
758
+				unset($preProc);
759
+
760
+				// show template source if debug
761
+				if ($this->debug) {
762
+					echo '<pre>'.print_r(htmlentities($tpl), true).'</pre>'."\n";
763
+				}
764
+
765
+				// strips php tags if required by the security policy
766
+				if ($this->securityPolicy !== null) {
767
+					$search = array('{<\?php.*?\?>}');
768
+					if (ini_get('short_open_tags')) {
769
+						$search = array('{<\?.*?\?>}', '{<%.*?%>}');
770
+					}
771
+					switch ($this->securityPolicy->getPhpHandling()) {
772
+						case SecurityPolicy::PHP_ALLOW:
773
+							break;
774
+						case SecurityPolicy::PHP_ENCODE:
775
+							$tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
+							break;
777
+						case SecurityPolicy::PHP_REMOVE:
778
+							$tpl = preg_replace($search, '', $tpl);
779
+					}
780
+				}
781
+			}
782
+
783
+			$pos = strpos($tpl, $this->ld, $ptr);
784
+
785
+			if ($pos === false) {
786
+				$this->push(substr($tpl, $ptr), 0);
787
+				break;
788
+			} elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
789
+				$this->push(substr($tpl, $ptr, $pos - $ptr - 1) . $this->ld);
790
+				$ptr = $pos + strlen($this->ld);
791
+			} elseif (preg_match('/^' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . 'literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', substr($tpl, $pos), $litOpen)) {
792
+				if (!preg_match('/' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . '\/literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
793
+					throw new CompilationException($this, 'The {literal} blocks must be closed explicitly with {/literal}');
794
+				}
795
+				$endpos = $litClose[0][1];
796
+				$this->push(substr($tpl, $ptr, $pos - $ptr) . substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
797
+				$ptr = $endpos + strlen($litClose[0][0]);
798
+			} else {
799
+				if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
800
+					$this->push(substr($tpl, $ptr, $pos - $ptr - 1));
801
+					$ptr = $pos;
802
+				}
803
+
804
+				$this->push(substr($tpl, $ptr, $pos - $ptr));
805
+				$ptr = $pos;
806
+
807
+				$pos += strlen($this->ld);
808
+				if ($this->allowLooseOpenings) {
809
+					while (substr($tpl, $pos, 1) === ' ') {
810
+						$pos += 1;
811
+					}
812
+				} else {
813
+					if (substr($tpl, $pos, 1) === ' ' || substr($tpl, $pos, 1) === "\r" || substr($tpl, $pos, 1) === "\n" || substr($tpl, $pos, 1) === "\t") {
814
+						$ptr = $pos;
815
+						$this->push($this->ld);
816
+						continue;
817
+					}
818
+				}
819
+
820
+				// check that there is an end tag present
821
+				if (strpos($tpl, $this->rd, $pos) === false) {
822
+					throw new CompilationException($this, 'A template tag was not closed, started with "' . substr($tpl, $ptr, 30) . '"');
823
+				}
824
+
825
+				$ptr += strlen($this->ld);
826
+				$subptr = $ptr;
827
+
828
+				while (true) {
829
+					$parsed = $this->parse($tpl, $subptr, null, false, 'root', $subptr);
830
+
831
+					// reload loop if the compiler was reset
832
+					if ($ptr === 0) {
833
+						continue 2;
834
+					}
835
+
836
+					$len = $subptr - $ptr;
837
+					$this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
838
+					$ptr += $len;
839
+
840
+					if ($parsed === false) {
841
+						break;
842
+					}
843
+				}
844
+			}
845
+		}
846
+
847
+		$compiled .= $this->removeBlock('TopLevelBlock');
848
+
849
+		if ($this->debug) {
850
+			echo 'PROCESSING POSTPROCESSORS' . "\n";
851
+		}
852
+
853
+		foreach ($this->processors['post'] as $postProc) {
854
+			if (is_array($postProc) && isset($postProc['autoload'])) {
855
+				$postProc = $this->loadProcessor($postProc['class'], $postProc['name']);
856
+			}
857
+			if (is_array($postProc) && $postProc[0] instanceof Processor) {
858
+				$compiled = call_user_func($postProc, $compiled);
859
+			} else {
860
+				$compiled = call_user_func($postProc, $this, $compiled);
861
+			}
862
+		}
863
+		unset($postProc);
864
+
865
+		if ($this->debug) {
866
+			echo 'COMPILATION COMPLETE : MEM USAGE : ' . memory_get_usage() . "\n";
867
+		}
868
+
869
+		$output = "<?php\n/* template head */\n";
870
+
871
+		// build plugin preloader
872
+		foreach ($this->getUsedPlugins() as $plugin => $type) {
873
+			if ($type & Core::CUSTOM_PLUGIN) {
874
+				continue;
875
+			}
876
+
877
+			switch ($type) {
878
+				case Core::BLOCK_PLUGIN:
879
+				case Core::CLASS_PLUGIN:
880
+					if (class_exists('Plugin' . $plugin) !== false) {
881
+						$output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
+					} else {
884
+						$output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
+					}
887
+					break;
888
+				case Core::FUNC_PLUGIN:
889
+					if (function_exists('Plugin' . $plugin) !== false) {
890
+						$output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
891
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
+					} else {
893
+						$output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
+						"\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
+					}
896
+					break;
897
+				case Core::SMARTY_MODIFIER:
898
+					$output .= "if (function_exists('smarty_modifier_$plugin')===false)".
899
+					"\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
900
+					break;
901
+				case Core::SMARTY_FUNCTION:
902
+					$output .= "if (function_exists('smarty_function_$plugin')===false)".
903
+					"\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
904
+					break;
905
+				case Core::SMARTY_BLOCK:
906
+					$output .= "if (function_exists('smarty_block_$plugin')===false)".
907
+					"\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
908
+					break;
909
+				case Core::PROXY_PLUGIN:
910
+					$output .= $this->getDwoo()->getPluginProxy()->getLoader($plugin);
911
+					break;
912
+				default:
913
+					throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
914
+			}
915
+		}
916
+
917
+		foreach ($this->templatePlugins as $function => $attr) {
918
+			if (isset($attr['called']) && $attr['called'] === true && !isset($attr['checked'])) {
919
+				$this->resolveSubTemplateDependencies($function);
920
+			}
921
+		}
922
+		foreach ($this->templatePlugins as $function) {
923
+			if (isset($function['called']) && $function['called'] === true) {
924
+				$output .= $function['body'] . PHP_EOL;
925
+			}
926
+		}
927
+
928
+		$output .= $compiled . "\n?>";
929
+
930
+		$output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*' . preg_quote(self::PHP_CLOSE, '/') . preg_quote(self::PHP_OPEN, '/') . ')/', ";\n", $output);
931
+		$output = str_replace(self::PHP_CLOSE . self::PHP_OPEN, "\n", $output);
932
+
933
+		// handle <?xml tag at the beginning
934
+		$output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
935
+
936
+		// add another line break after PHP closing tags that have a line break following,
937
+		// as we do not know whether it's intended, and PHP will strip it otherwise
938
+		$output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0' . "\n", $output);
939
+
940
+		if ($this->debug) {
941
+			echo '=============================================================================================' . "\n";
942
+			$lines = preg_split('{\r\n|\n|<br />}', $output);
943
+			array_shift($lines);
944
+			foreach ($lines as $i => $line) {
945
+				echo ($i + 1) . '. ' . $line . "\r\n";
946
+			}
947
+			echo '=============================================================================================' . "\n";
948
+		}
949
+
950
+		$this->template = $this->dwoo = null;
951
+		$tpl            = null;
952
+
953
+		return $output;
954
+	}
955
+
956
+	/**
957
+	 * Checks what sub-templates are used in every sub-template so that we're sure they are all compiled.
958
+	 *
959
+	 * @param string $function the sub-template name
960
+	 */
961
+	protected function resolveSubTemplateDependencies($function)
962
+	{
963
+		if ($this->debug) {
964
+			echo 'Compiler::' . __FUNCTION__ . "\n";
965
+		}
966
+
967
+		$body = $this->templatePlugins[$function]['body'];
968
+		foreach ($this->templatePlugins as $func => $attr) {
969
+			if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS .
970
+			'Plugin' . Core::toCamelCase($func)) !== false) {
971
+				$this->templatePlugins[$func]['called'] = true;
972
+				$this->resolveSubTemplateDependencies($func);
973
+			}
974
+		}
975
+		$this->templatePlugins[$function]['checked'] = true;
976
+	}
977
+
978
+	/**
979
+	 * Adds compiled content to the current block.
980
+	 *
981
+	 * @param string $content   the content to push
982
+	 * @param int    $lineCount newlines count in content, optional
983
+	 *
984
+	 * @throws CompilationException
985
+	 */
986
+	public function push($content, $lineCount = null)
987
+	{
988
+		if ($lineCount === null) {
989
+			$lineCount = substr_count($content, "\n");
990
+		}
991
+
992
+		if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
993
+			// buffer is not initialized yet (the block has just been created)
994
+			$this->stack[count($this->stack) - 2]['buffer'] .= (string)$content;
995
+			$this->curBlock['buffer'] = '';
996
+		} else {
997
+			if (!isset($this->curBlock['buffer'])) {
998
+				throw new CompilationException($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
999
+			}
1000
+			// append current content to current block's buffer
1001
+			$this->curBlock['buffer'] .= (string)$content;
1002
+		}
1003
+		$this->line += $lineCount;
1004
+	}
1005
+
1006
+	/**
1007
+	 * Sets the scope.
1008
+	 * set to null if the scope becomes "unstable" (i.e. too variable or unknown) so that
1009
+	 * variables are compiled in a more evaluative way than just $this->scope['key']
1010
+	 *
1011
+	 * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1012
+	 * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1013
+	 *
1014
+	 * @return array the current scope tree
1015
+	 */
1016
+	public function setScope($scope, $absolute = false)
1017
+	{
1018
+		$old = $this->scopeTree;
1019
+
1020
+		if ($scope === null) {
1021
+			unset($this->scope);
1022
+			$this->scope = null;
1023
+		}
1024
+
1025
+		if (is_array($scope) === false) {
1026
+			$scope = explode('.', $scope);
1027
+		}
1028
+
1029
+		if ($absolute === true) {
1030
+			$this->scope     = &$this->data;
1031
+			$this->scopeTree = array();
1032
+		}
1033
+
1034
+		while (($bit = array_shift($scope)) !== null) {
1035
+			if ($bit === '_parent' || $bit === '_') {
1036
+				array_pop($this->scopeTree);
1037
+				reset($this->scopeTree);
1038
+				$this->scope = &$this->data;
1039
+				$cnt         = count($this->scopeTree);
1040
+				for ($i = 0; $i < $cnt; ++ $i) {
1041
+					$this->scope = &$this->scope[$this->scopeTree[$i]];
1042
+				}
1043
+			} elseif ($bit === '_root' || $bit === '__') {
1044
+				$this->scope     = &$this->data;
1045
+				$this->scopeTree = array();
1046
+			} elseif (isset($this->scope[$bit])) {
1047
+				$this->scope       = &$this->scope[$bit];
1048
+				$this->scopeTree[] = $bit;
1049
+			} else {
1050
+				$this->scope[$bit] = array();
1051
+				$this->scope       = &$this->scope[$bit];
1052
+				$this->scopeTree[] = $bit;
1053
+			}
1054
+		}
1055
+
1056
+		return $old;
1057
+	}
1058
+
1059
+	/**
1060
+	 * Adds a block to the top of the block stack.
1061
+	 *
1062
+	 * @param string $type      block type (name)
1063
+	 * @param array  $params    the parameters array
1064
+	 * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1065
+	 *
1066
+	 * @return string the preProcessing() method's output
1067
+	 */
1068
+	public function addBlock($type, array $params, $paramtype)
1069
+	{
1070
+		if ($this->debug) {
1071
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1072
+		}
1073
+
1074
+		$class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1075
+		if (class_exists($class) === false) {
1076
+			$this->getDwoo()->getLoader()->loadPlugin($type);
1077
+		}
1078
+		$params = $this->mapParams($params, array($class, 'init'), $paramtype);
1079
+
1080
+		$this->stack[]  = array(
1081
+			'type'   => $type,
1082
+			'params' => $params,
1083
+			'custom' => false,
1084
+			'class'  => $class,
1085
+			'buffer' => null
1086
+		);
1087
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1088
+
1089
+		return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1090
+	}
1091
+
1092
+	/**
1093
+	 * Adds a custom block to the top of the block stack.
1094
+	 *
1095
+	 * @param string $type      block type (name)
1096
+	 * @param array  $params    the parameters array
1097
+	 * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1098
+	 *
1099
+	 * @return string the preProcessing() method's output
1100
+	 */
1101
+	public function addCustomBlock($type, array $params, $paramtype)
1102
+	{
1103
+		$callback = $this->customPlugins[$type]['callback'];
1104
+		if (is_array($callback)) {
1105
+			$class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
1106
+		} else {
1107
+			$class = $callback;
1108
+		}
1109
+
1110
+		$params = $this->mapParams($params, array($class, 'init'), $paramtype);
1111
+
1112
+		$this->stack[]  = array(
1113
+			'type'   => $type,
1114
+			'params' => $params,
1115
+			'custom' => true,
1116
+			'class'  => $class,
1117
+			'buffer' => null
1118
+		);
1119
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1120
+
1121
+		return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1122
+	}
1123
+
1124
+	/**
1125
+	 * Injects a block at the top of the plugin stack without calling its preProcessing method.
1126
+	 * used by {else} blocks to re-add themselves after having closed everything up to their parent
1127
+	 *
1128
+	 * @param string $type   block type (name)
1129
+	 * @param array  $params parameters array
1130
+	 */
1131
+	public function injectBlock($type, array $params)
1132
+	{
1133
+		if ($this->debug) {
1134
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1135
+		}
1136
+
1137
+		$class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1138
+		if (class_exists($class) === false) {
1139
+			$this->getDwoo()->getLoader()->loadPlugin($type);
1140
+		}
1141
+		$this->stack[]  = array(
1142
+			'type'   => $type,
1143
+			'params' => $params,
1144
+			'custom' => false,
1145
+			'class'  => $class,
1146
+			'buffer' => null
1147
+		);
1148
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1149
+	}
1150
+
1151
+	/**
1152
+	 * Removes the closest-to-top block of the given type and all other
1153
+	 * blocks encountered while going down the block stack.
1154
+	 *
1155
+	 * @param string $type block type (name)
1156
+	 *
1157
+	 * @return string the output of all postProcessing() method's return values of the closed blocks
1158
+	 * @throws CompilationException
1159
+	 */
1160
+	public function removeBlock($type)
1161
+	{
1162
+		if ($this->debug) {
1163
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1164
+		}
1165
+
1166
+		$output = '';
1167
+
1168
+		$pluginType = $this->getPluginType($type);
1169
+		if ($pluginType & Core::SMARTY_BLOCK) {
1170
+			$type = 'Smartyinterface';
1171
+		}
1172
+		while (true) {
1173
+			while ($top = array_pop($this->stack)) {
1174
+				if ($top['custom']) {
1175
+					$class = $top['class'];
1176
+				} else {
1177
+					$class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($top['type']);
1178
+				}
1179
+				if (count($this->stack)) {
1180
+					$this->curBlock = &$this->stack[count($this->stack) - 1];
1181
+					$this->push(call_user_func(array(
1182
+						$class,
1183
+						'postProcessing'
1184
+					), $this, $top['params'], '', '', $top['buffer']), 0);
1185
+				} else {
1186
+					$null           = null;
1187
+					$this->curBlock = &$null;
1188
+					$output         = call_user_func(
1189
+						array(
1190
+						$class,
1191
+						'postProcessing'
1192
+						), $this, $top['params'], '', '', $top['buffer']
1193
+					);
1194
+				}
1195
+
1196
+				if ($top['type'] === $type) {
1197
+					break 2;
1198
+				}
1199
+			}
1200
+
1201
+			throw new CompilationException($this, 'Syntax malformation, a block of type "' . $type . '" was closed but was not opened');
1202
+			break;
1203
+		}
1204
+
1205
+		return $output;
1206
+	}
1207
+
1208
+	/**
1209
+	 * Returns a reference to the first block of the given type encountered and
1210
+	 * optionally closes all blocks until it finds it
1211
+	 * this is mainly used by {else} plugins to close everything that was opened
1212
+	 * between their parent and themselves.
1213
+	 *
1214
+	 * @param string $type       the block type (name)
1215
+	 * @param bool   $closeAlong whether to close all blocks encountered while going down the block stack or not
1216
+	 *
1217
+	 * @return mixed &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1218
+	 *               'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1219
+	 * @throws CompilationException
1220
+	 */
1221
+	public function &findBlock($type, $closeAlong = false)
1222
+	{
1223
+		if ($closeAlong === true) {
1224
+			while ($b = end($this->stack)) {
1225
+				if ($b['type'] === $type) {
1226
+					return $this->stack[key($this->stack)];
1227
+				}
1228
+				$this->push($this->removeTopBlock(), 0);
1229
+			}
1230
+		} else {
1231
+			end($this->stack);
1232
+			while ($b = current($this->stack)) {
1233
+				if ($b['type'] === $type) {
1234
+					return $this->stack[key($this->stack)];
1235
+				}
1236
+				prev($this->stack);
1237
+			}
1238
+		}
1239
+
1240
+		throw new CompilationException($this, 'A parent block of type "' . $type . '" is required and can not be found');
1241
+	}
1242
+
1243
+	/**
1244
+	 * Returns a reference to the current block array.
1245
+	 *
1246
+	 * @return array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1247
+	 *                'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1248
+	 */
1249
+	public function &getCurrentBlock()
1250
+	{
1251
+		return $this->curBlock;
1252
+	}
1253
+
1254
+	/**
1255
+	 * Removes the block at the top of the stack and calls its postProcessing() method.
1256
+	 *
1257
+	 * @return string the postProcessing() method's output
1258
+	 * @throws CompilationException
1259
+	 */
1260
+	public function removeTopBlock()
1261
+	{
1262
+		if ($this->debug) {
1263
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1264
+		}
1265
+
1266
+		$o = array_pop($this->stack);
1267
+		if ($o === null) {
1268
+			throw new CompilationException($this, 'Syntax malformation, a block of unknown type was closed but was not opened.');
1269
+		}
1270
+		if ($o['custom']) {
1271
+			$class = $o['class'];
1272
+		} else {
1273
+			$class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($o['type']);
1274
+		}
1275
+
1276
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1277
+
1278
+		return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1279
+	}
1280
+
1281
+	/**
1282
+	 * Returns the compiled parameters (for example a variable's compiled parameter will be "$this->scope['key']") out
1283
+	 * of the given parameter array.
1284
+	 *
1285
+	 * @param array $params parameter array
1286
+	 *
1287
+	 * @return array filtered parameters
1288
+	 */
1289
+	public function getCompiledParams(array $params)
1290
+	{
1291
+		foreach ($params as $k => $p) {
1292
+			if (is_array($p)) {
1293
+				$params[$k] = $p[0];
1294
+			}
1295
+		}
1296
+
1297
+		return $params;
1298
+	}
1299
+
1300
+	/**
1301
+	 * Returns the real parameters (for example a variable's real parameter will be its key, etc) out of the given
1302
+	 * parameter array.
1303
+	 *
1304
+	 * @param array $params parameter array
1305
+	 *
1306
+	 * @return array filtered parameters
1307
+	 */
1308
+	public function getRealParams(array $params)
1309
+	{
1310
+		foreach ($params as $k => $p) {
1311
+			if (is_array($p)) {
1312
+				$params[$k] = $p[1];
1313
+			}
1314
+		}
1315
+
1316
+		return $params;
1317
+	}
1318
+
1319
+	/**
1320
+	 * Returns the token of each parameter out of the given parameter array.
1321
+	 *
1322
+	 * @param array $params parameter array
1323
+	 *
1324
+	 * @return array tokens
1325
+	 */
1326
+	public function getParamTokens(array $params)
1327
+	{
1328
+		foreach ($params as $k => $p) {
1329
+			if (is_array($p)) {
1330
+				$params[$k] = isset($p[2]) ? $p[2] : 0;
1331
+			}
1332
+		}
1333
+
1334
+		return $params;
1335
+	}
1336
+
1337
+	/**
1338
+	 * Entry point of the parser, it redirects calls to other parse* functions.
1339
+	 *
1340
+	 * @param string $in            the string within which we must parse something
1341
+	 * @param int    $from          the starting offset of the parsed area
1342
+	 * @param int    $to            the ending offset of the parsed area
1343
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1344
+	 *                              default
1345
+	 * @param string $curBlock      the current parser-block being processed
1346
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1347
+	 *                              or null by default
1348
+	 *
1349
+	 * @return string parsed values
1350
+	 * @throws CompilationException
1351
+	 */
1352
+	protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1353
+	{
1354
+		if ($this->debug) {
1355
+			echo 'Compiler::' . __FUNCTION__ . "\n";
1356
+		}
1357
+
1358
+		if ($to === null) {
1359
+			$to = strlen($in);
1360
+		}
1361
+		$first = substr($in, $from, 1);
1362
+
1363
+		if ($first === false) {
1364
+			throw new CompilationException($this, 'Unexpected EOF, a template tag was not closed');
1365
+		}
1366
+
1367
+		while ($first === ' ' || $first === "\n" || $first === "\t" || $first === "\r") {
1368
+			if ($curBlock === 'root' && substr($in, $from, strlen($this->rd)) === $this->rd) {
1369
+				// end template tag
1370
+				$pointer += strlen($this->rd);
1371
+				if ($this->debug) {
1372
+					echo 'TEMPLATE PARSING ENDED' . "\n";
1373
+				}
1374
+
1375
+				return false;
1376
+			}
1377
+			++ $from;
1378
+			if ($pointer !== null) {
1379
+				++ $pointer;
1380
+			}
1381
+			if ($from >= $to) {
1382
+				if (is_array($parsingParams)) {
1383
+					return $parsingParams;
1384
+				} else {
1385
+					return '';
1386
+				}
1387
+			}
1388
+			$first = $in[$from];
1389
+		}
1390
+
1391
+		$substr = substr($in, $from, $to - $from);
1392
+
1393
+		if ($this->debug) {
1394
+			echo 'PARSE CALL : PARSING "<b>' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . '</b>" @ ' . $from . ':' . $to . ' in ' . $curBlock . ' : pointer=' . $pointer . "\n";
1395
+		}
1396
+		$parsed = '';
1397
+
1398
+		if ($curBlock === 'root' && $first === '*') {
1399
+			$src      = $this->getTemplateSource();
1400
+			$startpos = $this->getPointer() - strlen($this->ld);
1401
+			if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1402
+				if ($startpos > 0) {
1403
+					do {
1404
+						$char = substr($src, -- $startpos, 1);
1405
+						if ($char == "\n") {
1406
+							++ $startpos;
1407
+							$whitespaceStart = true;
1408
+							break;
1409
+						}
1410
+					}
1411
+					while ($startpos > 0 && ($char == ' ' || $char == "\t"));
1412
+				}
1413
+
1414
+				if (!isset($whitespaceStart)) {
1415
+					$startpos = $this->getPointer();
1416
+				} else {
1417
+					$pointer -= $this->getPointer() - $startpos;
1418
+				}
1419
+
1420
+				if ($this->allowNestedComments && strpos($src, $this->ld . '*', $this->getPointer()) !== false) {
1421
+					$comOpen  = $this->ld . '*';
1422
+					$comClose = '*' . $this->rd;
1423
+					$level    = 1;
1424
+					$ptr      = $this->getPointer();
1425
+
1426
+					while ($level > 0 && $ptr < strlen($src)) {
1427
+						$open  = strpos($src, $comOpen, $ptr);
1428
+						$close = strpos($src, $comClose, $ptr);
1429
+
1430
+						if ($open !== false && $close !== false) {
1431
+							if ($open < $close) {
1432
+								$ptr = $open + strlen($comOpen);
1433
+								++ $level;
1434
+							} else {
1435
+								$ptr = $close + strlen($comClose);
1436
+								-- $level;
1437
+							}
1438
+						} elseif ($open !== false) {
1439
+							$ptr = $open + strlen($comOpen);
1440
+							++ $level;
1441
+						} elseif ($close !== false) {
1442
+							$ptr = $close + strlen($comClose);
1443
+							-- $level;
1444
+						} else {
1445
+							$ptr = strlen($src);
1446
+						}
1447
+					}
1448
+					$endpos = $ptr - strlen('*' . $this->rd);
1449
+				} else {
1450
+					$endpos = strpos($src, '*' . $this->rd, $startpos);
1451
+					if ($endpos == false) {
1452
+						throw new CompilationException($this, 'Un-ended comment');
1453
+					}
1454
+				}
1455
+				$pointer += $endpos - $startpos + strlen('*' . $this->rd);
1456
+				if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*' . $this->rd)), $m)) {
1457
+					$pointer += strlen($m[0]);
1458
+					$this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1459
+				}
1460
+
1461
+				return false;
1462
+			}
1463
+		}
1464
+
1465
+		if ($first === '$') {
1466
+			// var
1467
+			$out    = $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
1468
+			$parsed = 'var';
1469
+		} elseif ($first === '%' && preg_match('#^%[a-z_\\\\]#i', $substr)) {
1470
+			// Short constant
1471
+			$out = $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
1472
+		} elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1473
+			// string
1474
+			$out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1475
+		} elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?(' . (is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|') . '\s*\(|\s*' . $this->rdr . '|\s*;)/i', $substr)) {
1476
+			// func
1477
+			$out    = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1478
+			$parsed = 'func';
1479
+		} elseif ($first === ';') {
1480
+			// instruction end
1481
+			if ($this->debug) {
1482
+				echo 'END OF INSTRUCTION' . "\n";
1483
+			}
1484
+			if ($pointer !== null) {
1485
+				++ $pointer;
1486
+			}
1487
+
1488
+			return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1489
+		} elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1490
+			// close block
1491
+			if (!empty($match[1]) && $match[1] == 'else') {
1492
+				throw new CompilationException($this, 'Else blocks must not be closed explicitly, they are automatically closed when their parent block is closed');
1493
+			}
1494
+			if (!empty($match[1]) && $match[1] == 'elseif') {
1495
+				throw new CompilationException($this, 'Elseif blocks must not be closed explicitly, they are automatically closed when their parent block is closed or a new else/elseif block is declared after them');
1496
+			}
1497
+			if ($pointer !== null) {
1498
+				$pointer += strlen($match[0]);
1499
+			}
1500
+			if (empty($match[1])) {
1501
+				if ($this->curBlock['type'] == 'else' || $this->curBlock['type'] == 'elseif') {
1502
+					$pointer -= strlen($match[0]);
1503
+				}
1504
+				if ($this->debug) {
1505
+					echo 'TOP BLOCK CLOSED' . "\n";
1506
+				}
1507
+
1508
+				return $this->removeTopBlock();
1509
+			} else {
1510
+				if ($this->debug) {
1511
+					echo 'BLOCK OF TYPE ' . $match[1] . ' CLOSED' . "\n";
1512
+				}
1513
+
1514
+				return $this->removeBlock($match[1]);
1515
+			}
1516
+		} elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1517
+			// end template tag
1518
+			if ($this->debug) {
1519
+				echo 'TAG PARSING ENDED' . "\n";
1520
+			}
1521
+			$pointer += strlen($this->rd);
1522
+
1523
+			return false;
1524
+		} elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*=' . ($curBlock === 'array' ? '>?' : '') . ')(?:\s+|[^=]).*#i', $substr, $match)) {
1525
+			// named parameter
1526
+			if ($this->debug) {
1527
+				echo 'NAMED PARAM FOUND' . "\n";
1528
+			}
1529
+			$len = strlen($match[1]);
1530
+			while (substr($in, $from + $len, 1) === ' ') {
1531
+				++ $len;
1532
+			}
1533
+			if ($pointer !== null) {
1534
+				$pointer += $len;
1535
+			}
1536
+
1537
+			$output = array(
1538
+				trim($match[1], " \t\r\n=>'\""),
1539
+				$this->parse($in, $from + $len, $to, false, 'namedparam', $pointer)
1540
+			);
1541
+
1542
+			$parsingParams[] = $output;
1543
+
1544
+			return $parsingParams;
1545
+		} elseif (preg_match('#^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*::\$[a-z0-9_]+)#i', $substr, $match)) {
1546
+			// static member access
1547
+			$parsed = 'var';
1548
+			if (is_array($parsingParams)) {
1549
+				$parsingParams[] = array($match[1], $match[1]);
1550
+				$out             = $parsingParams;
1551
+			} else {
1552
+				$out = $match[1];
1553
+			}
1554
+			$pointer += strlen($match[1]);
1555
+		} elseif ($substr !== '' && (is_array($parsingParams) || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'expression')) {
1556
+			// unquoted string, bool or number
1557
+			$out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1558
+		} else {
1559
+			// parse error
1560
+			throw new CompilationException($this, 'Parse error in "' . substr($in, $from, $to - $from) . '"');
1561
+		}
1562
+
1563
+		if (empty($out)) {
1564
+			return '';
1565
+		}
1566
+
1567
+		$substr = substr($in, $pointer, $to - $pointer);
1568
+
1569
+		// var parsed, check if any var-extension applies
1570
+		if ($parsed === 'var') {
1571
+			if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1572
+				if ($this->debug) {
1573
+					echo 'PARSING POST-VAR EXPRESSION ' . $substr . "\n";
1574
+				}
1575
+				// parse expressions
1576
+				$pointer += strlen($match[0]) - 1;
1577
+				if (is_array($parsingParams)) {
1578
+					if ($match[2] == '$') {
1579
+						$expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1580
+					} else {
1581
+						$expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1582
+					}
1583
+					$out[count($out) - 1][0] .= $match[1] . $expr[0][0];
1584
+					$out[count($out) - 1][1] .= $match[1] . $expr[0][1];
1585
+				} else {
1586
+					if ($match[2] == '$') {
1587
+						$expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
1588
+					} else {
1589
+						$expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1590
+					}
1591
+					if (is_array($out) && is_array($expr)) {
1592
+						$out[0] .= $match[1] . $expr[0];
1593
+						$out[1] .= $match[1] . $expr[1];
1594
+					} elseif (is_array($out)) {
1595
+						$out[0] .= $match[1] . $expr;
1596
+						$out[1] .= $match[1] . $expr;
1597
+					} elseif (is_array($expr)) {
1598
+						$out .= $match[1] . $expr[0];
1599
+					} else {
1600
+						$out .= $match[1] . $expr;
1601
+					}
1602
+				}
1603
+			} elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1604
+				if ($this->debug) {
1605
+					echo 'PARSING POST-VAR ASSIGNMENT ' . $substr . "\n";
1606
+				}
1607
+				// parse assignment
1608
+				$value    = $match[2];
1609
+				$operator = trim($match[1]);
1610
+				if (substr($value, 0, 1) == '=') {
1611
+					throw new CompilationException($this, 'Unexpected "=" in <em>' . $substr . '</em>');
1612
+				}
1613
+
1614
+				if ($pointer !== null) {
1615
+					$pointer += strlen($match[1]);
1616
+				}
1617
+
1618
+				if ($operator !== '++' && $operator !== '--') {
1619
+					$parts = array();
1620
+					$ptr   = 0;
1621
+					$parts = $this->parse($value, 0, strlen($value), $parts, 'condition', $ptr);
1622
+					$pointer += $ptr;
1623
+
1624
+					// load if plugin
1625
+					try {
1626
+						$this->getPluginType('if');
1627
+					}
1628
+					catch (Exception $e) {
1629
+						throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1630
+					}
1631
+
1632
+					$parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS . 'PluginIf', 'init'), 1);
1633
+					$tokens = $this->getParamTokens($parts);
1634
+					$parts  = $this->getCompiledParams($parts);
1635
+
1636
+					$value = PluginIf::replaceKeywords($parts['*'], $tokens['*'], $this);
1637
+					$echo  = '';
1638
+				} else {
1639
+					$value = array();
1640
+					$echo  = 'echo ';
1641
+				}
1642
+
1643
+				if ($this->autoEscape) {
1644
+					$out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1645
+				}
1646
+				$out = self::PHP_OPEN . $echo . $out . $operator . implode(' ', $value) . self::PHP_CLOSE;
1647
+			} elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1648
+				// parse namedparam with var as name (only for array)
1649
+				if ($this->debug) {
1650
+					echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND' . "\n";
1651
+				}
1652
+				$len = strlen($match[1]);
1653
+				$var = $out[count($out) - 1];
1654
+				$pointer += $len;
1655
+
1656
+				$output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
1657
+
1658
+				$parsingParams[] = $output;
1659
+
1660
+				return $parsingParams;
1661
+			}
1662
+		}
1663
+
1664
+		if ($curBlock !== 'modifier' && ($parsed === 'func' || $parsed === 'var') && preg_match('#^(\|@?[a-z0-9_]+(:.*)?)+#i', $substr, $match)) {
1665
+			// parse modifier on funcs or vars
1666
+			$srcPointer = $pointer;
1667
+			if (is_array($parsingParams)) {
1668
+				$tmp                     = $this->replaceModifiers(
1669
+					array(
1670
+					null,
1671
+					null,
1672
+					$out[count($out) - 1][0],
1673
+					$match[0]
1674
+					), $curBlock, $pointer
1675
+				);
1676
+				$out[count($out) - 1][0] = $tmp;
1677
+				$out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1678
+			} else {
1679
+				$out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1680
+			}
1681
+		}
1682
+
1683
+		// func parsed, check if any func-extension applies
1684
+		if ($parsed === 'func' && preg_match('#^->[a-z0-9_]+(\s*\(.+|->[a-z_].*)?#is', $substr, $match)) {
1685
+			// parse method call or property read
1686
+			$ptr = 0;
1687
+
1688
+			if (is_array($parsingParams)) {
1689
+				$output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1690
+
1691
+				$out[count($out) - 1][0] = $output;
1692
+				$out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1693
+			} else {
1694
+				$out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1695
+			}
1696
+
1697
+			$pointer += $ptr;
1698
+		}
1699
+
1700
+		if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1701
+			return self::PHP_OPEN . 'echo ' . $out . ';' . self::PHP_CLOSE;
1702
+		} else {
1703
+			return $out;
1704
+		}
1705
+	}
1706
+
1707
+	/**
1708
+	 * Parses a function call.
1709
+	 *
1710
+	 * @param string $in            the string within which we must parse something
1711
+	 * @param int    $from          the starting offset of the parsed area
1712
+	 * @param int    $to            the ending offset of the parsed area
1713
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
1714
+	 *                              default
1715
+	 * @param string $curBlock      the current parser-block being processed
1716
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
1717
+	 *                              or null by default
1718
+	 *
1719
+	 * @return string parsed values
1720
+	 * @throws CompilationException
1721
+	 * @throws Exception
1722
+	 * @throws SecurityException
1723
+	 */
1724
+	protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1725
+	{
1726
+		$output = '';
1727
+		$cmdstr = substr($in, $from, $to - $from);
1728
+		preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*' . $this->rdr . '|\s*;)?/i', $cmdstr, $match);
1729
+
1730
+		if (empty($match[1])) {
1731
+			throw new CompilationException($this, 'Parse error, invalid function name : ' . substr($cmdstr, 0, 15));
1732
+		}
1733
+
1734
+		$func = $match[1];
1735
+
1736
+		if (!empty($match[2])) {
1737
+			$cmdstr = $match[1];
1738
+		}
1739
+
1740
+		if ($this->debug) {
1741
+			echo 'FUNC FOUND (' . $func . ')' . "\n";
1742
+		}
1743
+
1744
+		$paramsep = '';
1745
+
1746
+		if (is_array($parsingParams) || $curBlock != 'root') {
1747
+			$paramspos = strpos($cmdstr, '(');
1748
+			$paramsep  = ')';
1749
+		} elseif (preg_match_all('#^\s*[\\\\:a-z0-9_]+(\s*\(|\s+[^(])#i', $cmdstr, $match, PREG_OFFSET_CAPTURE)) {
1750
+			$paramspos = $match[1][0][1];
1751
+			$paramsep  = substr($match[1][0][0], - 1) === '(' ? ')' : '';
1752
+			if ($paramsep === ')') {
1753
+				$paramspos += strlen($match[1][0][0]) - 1;
1754
+				if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1755
+					$paramsep = '';
1756
+					if (strlen($match[1][0][0]) > 1) {
1757
+						-- $paramspos;
1758
+					}
1759
+				}
1760
+			}
1761
+		} else {
1762
+			$paramspos = false;
1763
+		}
1764
+
1765
+		$state = 0;
1766
+
1767
+		if ($paramspos === false) {
1768
+			$params = array();
1769
+
1770
+			if ($curBlock !== 'root') {
1771
+				return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1772
+			}
1773
+		} else {
1774
+			if ($curBlock === 'condition') {
1775
+				// load if plugin
1776
+				$this->getPluginType('if');
1777
+
1778
+				if (PluginIf::replaceKeywords(array($func), array(self::T_UNQUOTED_STRING), $this) !== array($func)) {
1779
+					return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1780
+				}
1781
+			}
1782
+			$whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1783
+			$paramstr   = substr($cmdstr, $paramspos + 1);
1784
+			if (substr($paramstr, - 1, 1) === $paramsep) {
1785
+				$paramstr = substr($paramstr, 0, - 1);
1786
+			}
1787
+
1788
+			if (strlen($paramstr) === 0) {
1789
+				$params   = array();
1790
+				$paramstr = '';
1791
+			} else {
1792
+				$ptr    = 0;
1793
+				$params = array();
1794
+				if ($func === 'empty') {
1795
+					$params = $this->parseVar($paramstr, $ptr, strlen($paramstr), $params, 'root', $ptr);
1796
+				} else {
1797
+					while ($ptr < strlen($paramstr)) {
1798
+						while (true) {
1799
+							if ($ptr >= strlen($paramstr)) {
1800
+								break 2;
1801
+							}
1802
+
1803
+							if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1804
+								if ($this->debug) {
1805
+									echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT ' . $ptr . "\n";
1806
+								}
1807
+								break 2;
1808
+							} elseif ($paramstr[$ptr] === ';') {
1809
+								++ $ptr;
1810
+								if ($this->debug) {
1811
+									echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT ' . $ptr . "\n";
1812
+								}
1813
+								break 2;
1814
+							} elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1815
+								if ($this->debug) {
1816
+									echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT ' . $ptr . "\n";
1817
+								}
1818
+								break 2;
1819
+							} elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1820
+								if ($this->debug) {
1821
+									echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT ' . $ptr . "\n";
1822
+								}
1823
+								break 2;
1824
+							}
1825
+
1826
+							if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1827
+								++ $ptr;
1828
+							} else {
1829
+								break;
1830
+							}
1831
+						}
1832
+
1833
+						if ($this->debug) {
1834
+							echo 'FUNC START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
1835
+						}
1836
+
1837
+						if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
1838
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'condition', $ptr);
1839
+						} elseif ($func === 'array') {
1840
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'array', $ptr);
1841
+						} else {
1842
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'function', $ptr);
1843
+						}
1844
+
1845
+						if ($this->debug) {
1846
+							echo 'PARAM PARSED, POINTER AT ' . $ptr . ' (' . substr($paramstr, $ptr - 1, 3) . ')' . "\n";
1847
+						}
1848
+					}
1849
+				}
1850
+				$paramstr = substr($paramstr, 0, $ptr);
1851
+				$state    = 0;
1852
+				foreach ($params as $k => $p) {
1853
+					if (is_array($p) && is_array($p[1])) {
1854
+						$state |= 2;
1855
+					} else {
1856
+						if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m) && $func !== 'array') {
1857
+							$params[$k] = array($m[2], array('true', 'true'));
1858
+						} else {
1859
+							if ($state & 2 && $func !== 'array') {
1860
+								throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
1861
+							}
1862
+							$state |= 1;
1863
+						}
1864
+					}
1865
+				}
1866
+			}
1867
+		}
1868
+
1869
+		if ($pointer !== null) {
1870
+			$pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1871
+			if ($this->debug) {
1872
+				echo 'FUNC ADDS ' . ((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)) . ' TO POINTER' . "\n";
1873
+			}
1874
+		}
1875
+
1876
+		if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1877
+			// handle static method calls with security policy
1878
+			if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1879
+				throw new SecurityException('Call to a disallowed php function : ' . $func);
1880
+			}
1881
+			$pluginType = Core::NATIVE_PLUGIN;
1882
+		} else {
1883
+			$pluginType = $this->getPluginType($func);
1884
+		}
1885
+
1886
+		// Blocks plugin
1887
+		if ($pluginType & Core::BLOCK_PLUGIN) {
1888
+			if ($curBlock !== 'root' || is_array($parsingParams)) {
1889
+				throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1890
+			}
1891
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
1892
+				return $this->addCustomBlock($func, $params, $state);
1893
+			} else {
1894
+				return $this->addBlock($func, $params, $state);
1895
+			}
1896
+		} elseif ($pluginType & Core::SMARTY_BLOCK) {
1897
+			if ($curBlock !== 'root' || is_array($parsingParams)) {
1898
+				throw new CompilationException($this, 'Block plugins can not be used as other plugin\'s arguments');
1899
+			}
1900
+
1901
+			if ($state & 2) {
1902
+				array_unshift($params, array('__functype', array($pluginType, $pluginType)));
1903
+				array_unshift($params, array('__funcname', array($func, $func)));
1904
+			} else {
1905
+				array_unshift($params, array($pluginType, $pluginType));
1906
+				array_unshift($params, array($func, $func));
1907
+			}
1908
+
1909
+			return $this->addBlock('smartyinterface', $params, $state);
1910
+		}
1911
+
1912
+		// Functions plugin
1913
+		if ($pluginType & Core::NATIVE_PLUGIN || $pluginType & Core::SMARTY_FUNCTION || $pluginType & Core::SMARTY_BLOCK) {
1914
+			$params = $this->mapParams($params, null, $state);
1915
+		} elseif ($pluginType & Core::CLASS_PLUGIN) {
1916
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
1917
+				$params = $this->mapParams(
1918
+					$params, array(
1919
+					$this->customPlugins[$func]['class'],
1920
+					$this->customPlugins[$func]['function']
1921
+				), $state);
1922
+			} else {
1923
+				if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
1924
+					$params = $this->mapParams($params, array(
1925
+						'Plugin' . Core::toCamelCase($func),
1926
+						($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1927
+					), $state);
1928
+				} else {
1929
+					$params = $this->mapParams($params, array(
1930
+						Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
1931
+						($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1932
+					), $state);
1933
+				}
1934
+			}
1935
+		} elseif ($pluginType & Core::FUNC_PLUGIN) {
1936
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
1937
+				$params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1938
+			} else {
1939
+				// Custom plugin
1940
+				if (function_exists('Plugin' . Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ?
1941
+						'Compile' : '')) !== false) {
1942
+					$params = $this->mapParams($params, 'Plugin' . Core::toCamelCase($func) . (($pluginType &
1943
+							Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1944
+				} // Builtin helper plugin
1945
+				elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . (
1946
+					($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '')) !== false) {
1947
+					$params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase
1948
+						($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1949
+				} // Builtin function plugin
1950
+				else {
1951
+					$params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
1952
+						($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1953
+				}
1954
+			}
1955
+		} elseif ($pluginType & Core::SMARTY_MODIFIER) {
1956
+			$output = 'smarty_modifier_' . $func . '(' . implode(', ', $params) . ')';
1957
+		} elseif ($pluginType & Core::PROXY_PLUGIN) {
1958
+			$params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
1959
+		} elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
1960
+			// transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
1961
+			$map = array();
1962
+			foreach ($this->templatePlugins[$func]['params'] as $param => $defValue) {
1963
+				if ($param == 'rest') {
1964
+					$param = '*';
1965
+				}
1966
+				$hasDefault = $defValue !== null;
1967
+				if ($defValue === 'null') {
1968
+					$defValue = null;
1969
+				} elseif ($defValue === 'false') {
1970
+					$defValue = false;
1971
+				} elseif ($defValue === 'true') {
1972
+					$defValue = true;
1973
+				} elseif (preg_match('#^([\'"]).*?\1$#', $defValue)) {
1974
+					$defValue = substr($defValue, 1, - 1);
1975
+				}
1976
+				$map[] = array($param, $hasDefault, $defValue);
1977
+			}
1978
+
1979
+			$params = $this->mapParams($params, null, $state, $map);
1980
+		}
1981
+
1982
+		// only keep php-syntax-safe values for non-block plugins
1983
+		$tokens = array();
1984
+		foreach ($params as $k => $p) {
1985
+			$tokens[$k] = isset($p[2]) ? $p[2] : 0;
1986
+			$params[$k] = $p[0];
1987
+		}
1988
+		if ($pluginType & Core::NATIVE_PLUGIN) {
1989
+			if ($func === 'do') {
1990
+				if (isset($params['*'])) {
1991
+					$output = implode(';', $params['*']) . ';';
1992
+				} else {
1993
+					$output = '';
1994
+				}
1995
+
1996
+				if (is_array($parsingParams) || $curBlock !== 'root') {
1997
+					throw new CompilationException($this, 'Do can not be used inside another function or block');
1998
+				} else {
1999
+					return self::PHP_OPEN . $output . self::PHP_CLOSE;
2000
+				}
2001
+			} else {
2002
+				if (isset($params['*'])) {
2003
+					$output = $func . '(' . implode(', ', $params['*']) . ')';
2004
+				} else {
2005
+					$output = $func . '()';
2006
+				}
2007
+			}
2008
+		} elseif ($pluginType & Core::FUNC_PLUGIN) {
2009
+			if ($pluginType & Core::COMPILABLE_PLUGIN) {
2010
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2011
+					$funcCompiler = $this->customPlugins[$func]['callback'];
2012
+				} else {
2013
+					// Custom plugin
2014
+					if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2015
+						$funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
2016
+					} // Builtin helper plugin
2017
+					elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2018
+							'Compile') !== false) {
2019
+						$funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2020
+							'Compile';
2021
+					} // Builtin function plugin
2022
+					else {
2023
+						$funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
2024
+							'Compile';
2025
+					}
2026
+				}
2027
+				array_unshift($params, $this);
2028
+				if ($func === 'tif') {
2029
+					$params[] = $tokens;
2030
+				}
2031
+				$output = call_user_func_array($funcCompiler, $params);
2032
+			} else {
2033
+				array_unshift($params, '$this');
2034
+				$params = self::implode_r($params);
2035
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2036
+					$callback = $this->customPlugins[$func]['callback'];
2037
+					if ($callback instanceof Closure) {
2038
+						$output = 'call_user_func($this->getCustomPlugin(\'' . $func . '\'), ' . $params . ')';
2039
+					} else {
2040
+						$output = 'call_user_func(\'' . $callback . '\', ' . $params . ')';
2041
+					}
2042
+				} else {
2043
+					// Custom plugin
2044
+					if (function_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2045
+						$output = 'Plugin' . Core::toCamelCase($func) . '(' . $params .
2046
+							')';
2047
+					} // Builtin helper plugin
2048
+					elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !==
2049
+						false) {
2050
+						$output = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . '(' .
2051
+							$params . ')';
2052
+					} // Builtin function plugin
2053
+					else {
2054
+						$output = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '(' .
2055
+							$params . ')';
2056
+					}
2057
+				}
2058
+			}
2059
+		} elseif ($pluginType & Core::CLASS_PLUGIN) {
2060
+			if ($pluginType & Core::COMPILABLE_PLUGIN) {
2061
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2062
+					$callback = $this->customPlugins[$func]['callback'];
2063
+					if (!is_array($callback)) {
2064
+						if (!method_exists($callback, 'compile')) {
2065
+							throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2066
+						}
2067
+						if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
2068
+							$funcCompiler = array($callback, 'compile');
2069
+						} else {
2070
+							$funcCompiler = array(new $callback(), 'compile');
2071
+						}
2072
+					} else {
2073
+						$funcCompiler = $callback;
2074
+					}
2075
+				} else {
2076
+					if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2077
+						$funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
2078
+					} else {
2079
+						$funcCompiler = array(
2080
+							Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
2081
+							'compile'
2082
+						);
2083
+					}
2084
+					array_unshift($params, $this);
2085
+				}
2086
+				$output = call_user_func_array($funcCompiler, $params);
2087
+			} else {
2088
+				$params = self::implode_r($params);
2089
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
2090
+					$callback = $this->customPlugins[$func]['callback'];
2091
+					if (!is_array($callback)) {
2092
+						if (!method_exists($callback, 'process')) {
2093
+							throw new Exception('Custom plugin ' . $func . ' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2094
+						}
2095
+						if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
2096
+							$output = 'call_user_func(array(\'' . $callback . '\', \'process\'), ' . $params . ')';
2097
+						} else {
2098
+							$output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback . '\'), \'process\'), ' . $params . ')';
2099
+						}
2100
+					} elseif (is_object($callback[0])) {
2101
+						$output = 'call_user_func(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), ' . $params . ')';
2102
+					} elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
2103
+						$output = 'call_user_func(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), ' . $params . ')';
2104
+					} else {
2105
+						$output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback[0] . '\'), \'' . $callback[1] . '\'), ' . $params . ')';
2106
+					}
2107
+					if (empty($params)) {
2108
+						$output = substr($output, 0, - 3) . ')';
2109
+					}
2110
+				} else {
2111
+					if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2112
+						$output = '$this->classCall(\'Plugin' . $func . '\', array(' . $params . '))';
2113
+					} elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !==
2114
+					false) {
2115
+						$output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\', 
2116 2116
                         array(' . $params . '))';
2117
-                    } else{
2118
-                        $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
2119
-                    }
2120
-                }
2121
-            }
2122
-        } elseif ($pluginType & Core::PROXY_PLUGIN) {
2123
-            $output = call_user_func(array($this->getDwoo()->getPluginProxy(), 'getCode'), $func, $params);
2124
-        } elseif ($pluginType & Core::SMARTY_FUNCTION) {
2125
-            if (isset($params['*'])) {
2126
-                $params = self::implode_r($params['*'], true);
2127
-            } else {
2128
-                $params = '';
2129
-            }
2130
-
2131
-            if ($pluginType & Core::CUSTOM_PLUGIN) {
2132
-                $callback = $this->customPlugins[$func]['callback'];
2133
-                if (is_array($callback)) {
2134
-                    if (is_object($callback[0])) {
2135
-                        $output = 'call_user_func_array(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2136
-                    } else {
2137
-                        $output = 'call_user_func_array(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2138
-                    }
2139
-                } else {
2140
-                    $output = $callback . '(array(' . $params . '), $this)';
2141
-                }
2142
-            } else {
2143
-                $output = 'smarty_function_' . $func . '(array(' . $params . '), $this)';
2144
-            }
2145
-        } elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
2146
-            array_unshift($params, '$this');
2147
-            $params                                 = self::implode_r($params);
2148
-            $output                                 = 'Plugin' . Core::toCamelCase($func) .
2149
-                $this->templatePlugins[$func]['uuid'] . '(' . $params . ')';
2150
-            $this->templatePlugins[$func]['called'] = true;
2151
-        }
2152
-
2153
-        if (is_array($parsingParams)) {
2154
-            $parsingParams[] = array($output, $output);
2155
-
2156
-            return $parsingParams;
2157
-        } elseif ($curBlock === 'namedparam') {
2158
-            return array($output, $output);
2159
-        } else {
2160
-            return $output;
2161
-        }
2162
-    }
2163
-
2164
-    /**
2165
-     * Parses a string.
2166
-     *
2167
-     * @param string $in            the string within which we must parse something
2168
-     * @param int    $from          the starting offset of the parsed area
2169
-     * @param int    $to            the ending offset of the parsed area
2170
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2171
-     *                              default
2172
-     * @param string $curBlock      the current parser-block being processed
2173
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2174
-     *                              or null by default
2175
-     *
2176
-     * @return string parsed values
2177
-     * @throws CompilationException
2178
-     */
2179
-    protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2180
-    {
2181
-        $substr = substr($in, $from, $to - $from);
2182
-        $first  = $substr[0];
2183
-
2184
-        if ($this->debug) {
2185
-            echo 'STRING FOUND (in ' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . ')' . "\n";
2186
-        }
2187
-        $strend = false;
2188
-        $o      = $from + 1;
2189
-        while ($strend === false) {
2190
-            $strend = strpos($in, $first, $o);
2191
-            if ($strend === false) {
2192
-                throw new CompilationException($this, 'Unfinished string, started with ' . substr($in, $from, $to - $from));
2193
-            }
2194
-            if (substr($in, $strend - 1, 1) === '\\') {
2195
-                $o      = $strend + 1;
2196
-                $strend = false;
2197
-            }
2198
-        }
2199
-        if ($this->debug) {
2200
-            echo 'STRING DELIMITED: ' . substr($in, $from, $strend + 1 - $from) . "\n";
2201
-        }
2202
-
2203
-        $srcOutput = substr($in, $from, $strend + 1 - $from);
2204
-
2205
-        if ($pointer !== null) {
2206
-            $pointer += strlen($srcOutput);
2207
-        }
2208
-
2209
-        $output = $this->replaceStringVars($srcOutput, $first);
2210
-
2211
-        // handle modifiers
2212
-        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2213
-            $modstr = $match[1];
2214
-
2215
-            if ($curBlock === 'root' && substr($modstr, - 1) === '}') {
2216
-                $modstr = substr($modstr, 0, - 1);
2217
-            }
2218
-            $modstr = str_replace('\\' . $first, $first, $modstr);
2219
-            $ptr    = 0;
2220
-            $output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2221
-
2222
-            $strend += $ptr;
2223
-            if ($pointer !== null) {
2224
-                $pointer += $ptr;
2225
-            }
2226
-            $srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2227
-        }
2228
-
2229
-        if (is_array($parsingParams)) {
2230
-            $parsingParams[] = array($output, substr($srcOutput, 1, - 1));
2231
-
2232
-            return $parsingParams;
2233
-        } elseif ($curBlock === 'namedparam') {
2234
-            return array($output, substr($srcOutput, 1, - 1));
2235
-        } else {
2236
-            return $output;
2237
-        }
2238
-    }
2239
-
2240
-    /**
2241
-     * Parses a constant.
2242
-     *
2243
-     * @param string $in            the string within which we must parse something
2244
-     * @param int    $from          the starting offset of the parsed area
2245
-     * @param int    $to            the ending offset of the parsed area
2246
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2247
-     *                              default
2248
-     * @param string $curBlock      the current parser-block being processed
2249
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2250
-     *                              or null by default
2251
-     *
2252
-     * @return string parsed values
2253
-     * @throws CompilationException
2254
-     */
2255
-    protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2256
-    {
2257
-        $substr = substr($in, $from, $to - $from);
2258
-
2259
-        if ($this->debug) {
2260
-            echo 'CONST FOUND : ' . $substr . "\n";
2261
-        }
2262
-
2263
-        if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
2264
-            throw new CompilationException($this, 'Invalid constant');
2265
-        }
2266
-
2267
-        if ($pointer !== null) {
2268
-            $pointer += strlen($m[0]);
2269
-        }
2270
-
2271
-        $output = $this->parseConstKey($m[1], $curBlock);
2272
-
2273
-        if (is_array($parsingParams)) {
2274
-            $parsingParams[] = array($output, $m[1]);
2275
-
2276
-            return $parsingParams;
2277
-        } elseif ($curBlock === 'namedparam') {
2278
-            return array($output, $m[1]);
2279
-        } else {
2280
-            return $output;
2281
-        }
2282
-    }
2283
-
2284
-    /**
2285
-     * Parses a constant.
2286
-     *
2287
-     * @param string $key      the constant to parse
2288
-     * @param string $curBlock the current parser-block being processed
2289
-     *
2290
-     * @return string parsed constant
2291
-     */
2292
-    protected function parseConstKey($key, $curBlock)
2293
-    {
2294
-        if ($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === SecurityPolicy::CONST_DISALLOW) {
2295
-            return 'null';
2296
-        }
2297
-
2298
-        if ($curBlock !== 'root') {
2299
-            $output = '(defined("' . $key . '") ? ' . $key . ' : null)';
2300
-        } else {
2301
-            $output = $key;
2302
-        }
2303
-
2304
-        return $output;
2305
-    }
2306
-
2307
-    /**
2308
-     * Parses a variable.
2309
-     *
2310
-     * @param string $in            the string within which we must parse something
2311
-     * @param int    $from          the starting offset of the parsed area
2312
-     * @param int    $to            the ending offset of the parsed area
2313
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2314
-     *                              default
2315
-     * @param string $curBlock      the current parser-block being processed
2316
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2317
-     *                              or null by default
2318
-     *
2319
-     * @return string parsed values
2320
-     * @throws CompilationException
2321
-     */
2322
-    protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2323
-    {
2324
-        $methodCall = '';
2325
-        $substr     = substr($in, $from, $to - $from);
2326
-
2327
-        if (preg_match(
2328
-            '#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)' . // var key
2329
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()') . // method call
2330
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()') . // simple math expressions
2331
-            ($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())') . // modifiers
2332
-            '#i', $substr, $match
2333
-        )) {
2334
-            $key = substr($match[1], 1);
2335
-
2336
-            $matchedLength = strlen($match[0]);
2337
-            $hasModifiers  = !empty($match[5]);
2338
-            $hasExpression = !empty($match[4]);
2339
-            $hasMethodCall = !empty($match[3]);
2340
-
2341
-            if (substr($key, - 1) == '.') {
2342
-                $key = substr($key, 0, - 1);
2343
-                -- $matchedLength;
2344
-            }
2345
-
2346
-            if ($hasMethodCall) {
2347
-                $matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2348
-                $key        = substr($match[1], 1, strrpos($match[1], '->') - 1);
2349
-                $methodCall = substr($match[1], strrpos($match[1], '->')) . $match[3];
2350
-            }
2351
-
2352
-            if ($hasModifiers) {
2353
-                $matchedLength -= strlen($match[5]);
2354
-            }
2355
-
2356
-            if ($pointer !== null) {
2357
-                $pointer += $matchedLength;
2358
-            }
2359
-
2360
-            // replace useless brackets by dot accessed vars and strip enclosing quotes if present
2361
-            $key = preg_replace('#\[(["\']?)([^$%\[.>-]+)\1\]#', '.$2', $key);
2362
-
2363
-            if ($this->debug) {
2364
-                if ($hasMethodCall) {
2365
-                    echo 'METHOD CALL FOUND : $' . $key . substr($methodCall, 0, 30) . "\n";
2366
-                } else {
2367
-                    echo 'VAR FOUND : $' . $key . "\n";
2368
-                }
2369
-            }
2370
-
2371
-            $key = str_replace('"', '\\"', $key);
2372
-
2373
-            $cnt = substr_count($key, '$');
2374
-            if ($cnt > 0) {
2375
-                $uid           = 0;
2376
-                $parsed        = array($uid => '');
2377
-                $current       = &$parsed;
2378
-                $curTxt        = &$parsed[$uid ++];
2379
-                $tree          = array();
2380
-                $chars         = str_split($key, 1);
2381
-                $inSplittedVar = false;
2382
-                $bracketCount  = 0;
2383
-
2384
-                while (($char = array_shift($chars)) !== null) {
2385
-                    if ($char === '[') {
2386
-                        if (count($tree) > 0) {
2387
-                            ++ $bracketCount;
2388
-                        } else {
2389
-                            $tree[]        = &$current;
2390
-                            $current[$uid] = array($uid + 1 => '');
2391
-                            $current       = &$current[$uid ++];
2392
-                            $curTxt        = &$current[$uid ++];
2393
-                            continue;
2394
-                        }
2395
-                    } elseif ($char === ']') {
2396
-                        if ($bracketCount > 0) {
2397
-                            -- $bracketCount;
2398
-                        } else {
2399
-                            $current = &$tree[count($tree) - 1];
2400
-                            array_pop($tree);
2401
-                            if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2402
-                                $current[$uid] = '';
2403
-                                $curTxt        = &$current[$uid ++];
2404
-                            }
2405
-                            continue;
2406
-                        }
2407
-                    } elseif ($char === '$') {
2408
-                        if (count($tree) == 0) {
2409
-                            $curTxt        = &$current[$uid ++];
2410
-                            $inSplittedVar = true;
2411
-                        }
2412
-                    } elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2413
-                        $curTxt        = &$current[$uid ++];
2414
-                        $inSplittedVar = false;
2415
-                    }
2416
-
2417
-                    $curTxt .= $char;
2418
-                }
2419
-                unset($uid, $current, $curTxt, $tree, $chars);
2420
-
2421
-                if ($this->debug) {
2422
-                    echo 'RECURSIVE VAR REPLACEMENT : ' . $key . "\n";
2423
-                }
2424
-
2425
-                $key = $this->flattenVarTree($parsed);
2426
-
2427
-                if ($this->debug) {
2428
-                    echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2429
-                }
2430
-
2431
-                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("' . $key . '")');
2432
-            } else {
2433
-                $output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2434
-            }
2435
-
2436
-            // methods
2437
-            if ($hasMethodCall) {
2438
-                $ptr = 0;
2439
-
2440
-                $output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
2441
-
2442
-                if ($pointer !== null) {
2443
-                    $pointer += $ptr;
2444
-                }
2445
-                $matchedLength += $ptr;
2446
-            }
2447
-
2448
-            if ($hasExpression) {
2449
-                // expressions
2450
-                preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[4], $expMatch);
2451
-
2452
-                foreach ($expMatch[1] as $k => $operator) {
2453
-                    if (substr($expMatch[2][$k], 0, 1) === '=') {
2454
-                        $assign = true;
2455
-                        if ($operator === '=') {
2456
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, can not use "==" in expressions');
2457
-                        }
2458
-                        if ($curBlock !== 'root') {
2459
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2460
-                        }
2461
-                        $operator .= '=';
2462
-                        $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2463
-                    }
2464
-
2465
-                    if (substr($expMatch[2][$k], 0, 1) === '-' && strlen($expMatch[2][$k]) > 1) {
2466
-                        $operator .= '-';
2467
-                        $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2468
-                    }
2469
-                    if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2470
-                        $output = '(' . $output . $operator . $operator . ')';
2471
-                        break;
2472
-                    } elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2473
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2474
-                    } elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2475
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2476
-                    } elseif (!empty($expMatch[2][$k])) {
2477
-                        $output = '(' . $output . ' ' . $operator . ' ' . str_replace(',', '.', $expMatch[2][$k]) . ')';
2478
-                    } else {
2479
-                        throw new CompilationException($this, 'Unfinished expression <em>' . $substr . '</em>, missing var or number after math operator');
2480
-                    }
2481
-                }
2482
-            }
2483
-
2484
-            if ($this->autoEscape === true && $curBlock !== 'condition') {
2485
-                $output = '(is_string($tmp=' . $output . ') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2486
-            }
2487
-
2488
-            // handle modifiers
2489
-            if ($curBlock !== 'modifier' && $hasModifiers) {
2490
-                $ptr    = 0;
2491
-                $output = $this->replaceModifiers(array(null, null, $output, $match[5]), 'var', $ptr);
2492
-                if ($pointer !== null) {
2493
-                    $pointer += $ptr;
2494
-                }
2495
-                $matchedLength += $ptr;
2496
-            }
2497
-
2498
-            if (is_array($parsingParams)) {
2499
-                $parsingParams[] = array($output, $key);
2500
-
2501
-                return $parsingParams;
2502
-            } elseif ($curBlock === 'namedparam') {
2503
-                return array($output, $key);
2504
-            } elseif ($curBlock === 'string' || $curBlock === 'delimited_string') {
2505
-                return array($matchedLength, $output);
2506
-            } elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2507
-                return $output;
2508
-            } elseif (isset($assign)) {
2509
-                return self::PHP_OPEN . $output . ';' . self::PHP_CLOSE;
2510
-            } else {
2511
-                return $output;
2512
-            }
2513
-        } else {
2514
-            if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2515
-                return array(0, '');
2516
-            } else {
2517
-                throw new CompilationException($this, 'Invalid variable name <em>' . $substr . '</em>');
2518
-            }
2519
-        }
2520
-    }
2521
-
2522
-    /**
2523
-     * Parses any number of chained method calls/property reads.
2524
-     *
2525
-     * @param string $output     the variable or whatever upon which the method are called
2526
-     * @param string $methodCall method call source, starting at "->"
2527
-     * @param string $curBlock   the current parser-block being processed
2528
-     * @param int    $pointer    a reference to a pointer that will be increased by the amount of characters parsed
2529
-     *
2530
-     * @return string parsed call(s)/read(s)
2531
-     */
2532
-    protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
2533
-    {
2534
-        $ptr = 0;
2535
-        $len = strlen($methodCall);
2536
-
2537
-        while ($ptr < $len) {
2538
-            if (strpos($methodCall, '->', $ptr) === $ptr) {
2539
-                $ptr += 2;
2540
-            }
2541
-
2542
-            if (in_array(
2543
-                $methodCall[$ptr], array(
2544
-                    ';',
2545
-                    ',',
2546
-                    '/',
2547
-                    ' ',
2548
-                    "\t",
2549
-                    "\r",
2550
-                    "\n",
2551
-                    ')',
2552
-                    '+',
2553
-                    '*',
2554
-                    '%',
2555
-                    '=',
2556
-                    '-',
2557
-                    '|'
2558
-                )
2559
-            ) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd
2560
-            ) {
2561
-                // break char found
2562
-                break;
2563
-            }
2564
-
2565
-            if (!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
2566
-                break;
2567
-            }
2568
-
2569
-            if (empty($methMatch[2])) {
2570
-                // property
2571
-                if ($curBlock === 'root') {
2572
-                    $output .= '->' . $methMatch[1];
2573
-                } else {
2574
-                    $output = '(($tmp = ' . $output . ') ? $tmp->' . $methMatch[1] . ' : null)';
2575
-                }
2576
-                $ptr += strlen($methMatch[1]);
2577
-            } else {
2578
-                // method
2579
-                if (substr($methMatch[2], 0, 2) === '()') {
2580
-                    $parsedCall = $methMatch[1] . '()';
2581
-                    $ptr += strlen($methMatch[1]) + 2;
2582
-                } else {
2583
-                    $parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2584
-                }
2585
-                if ($this->securityPolicy !== null) {
2586
-                    $argPos = strpos($parsedCall, '(');
2587
-                    $method = strtolower(substr($parsedCall, 0, $argPos));
2588
-                    $args   = substr($parsedCall, $argPos);
2589
-                    if ($curBlock === 'root') {
2590
-                        $output = '$this->getSecurityPolicy()->callMethod($this, ' . $output . ', ' . var_export($method, true) . ', array' . $args . ')';
2591
-                    } else {
2592
-                        $output = '(($tmp = ' . $output . ') ? $this->getSecurityPolicy()->callMethod($this, $tmp, ' . var_export($method, true) . ', array' . $args . ') : null)';
2593
-                    }
2594
-                } else {
2595
-                    if ($curBlock === 'root') {
2596
-                        $output .= '->' . $parsedCall;
2597
-                    } else {
2598
-                        $output = '(($tmp = ' . $output . ') ? $tmp->' . $parsedCall . ' : null)';
2599
-                    }
2600
-                }
2601
-            }
2602
-        }
2603
-
2604
-        $pointer += $ptr;
2605
-
2606
-        return $output;
2607
-    }
2608
-
2609
-    /**
2610
-     * Parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save
2611
-     * runtime processing time.
2612
-     *
2613
-     * @param string $key      the variable to parse
2614
-     * @param string $curBlock the current parser-block being processed
2615
-     *
2616
-     * @return string parsed variable
2617
-     */
2618
-    protected function parseVarKey($key, $curBlock)
2619
-    {
2620
-        if ($key === '') {
2621
-            return '$this->scope';
2622
-        }
2623
-        if (substr($key, 0, 1) === '.') {
2624
-            $key = 'dwoo' . $key;
2625
-        }
2626
-        if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2627
-            $global = strtoupper($m[1]);
2628
-            if ($global === 'COOKIES') {
2629
-                $global = 'COOKIE';
2630
-            }
2631
-            $key = '$_' . $global;
2632
-            foreach (explode('.', ltrim($m[2], '.')) as $part) {
2633
-                $key .= '[' . var_export($part, true) . ']';
2634
-            }
2635
-            if ($curBlock === 'root') {
2636
-                $output = $key;
2637
-            } else {
2638
-                $output = '(isset(' . $key . ')?' . $key . ':null)';
2639
-            }
2640
-        } elseif (preg_match('#dwoo\.const\.([a-z0-9_:]+)#i', $key, $m)) {
2641
-            return $this->parseConstKey($m[1], $curBlock);
2642
-        } elseif ($this->scope !== null) {
2643
-            if (strstr($key, '.') === false && strstr($key, '[') === false && strstr($key, '->') === false) {
2644
-                if ($key === 'dwoo') {
2645
-                    $output = '$this->globals';
2646
-                } elseif ($key === '_root' || $key === '__') {
2647
-                    $output = '$this->data';
2648
-                } elseif ($key === '_parent' || $key === '_') {
2649
-                    $output = '$this->readParentVar(1)';
2650
-                } elseif ($key === '_key') {
2651
-                    $output = '$tmp_key';
2652
-                } else {
2653
-                    if ($curBlock === 'root') {
2654
-                        $output = '$this->scope["' . $key . '"]';
2655
-                    } else {
2656
-                        $output = '(isset($this->scope["' . $key . '"]) ? $this->scope["' . $key . '"] : null)';
2657
-                    }
2658
-                }
2659
-            } else {
2660
-                preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+|(\\\?[\'"])[^\3]*?\3)\]?#i', $key, $m);
2661
-
2662
-                $i = $m[2][0];
2663
-                if ($i === '_parent' || $i === '_') {
2664
-                    $parentCnt = 0;
2665
-
2666
-                    while (true) {
2667
-                        ++ $parentCnt;
2668
-                        array_shift($m[2]);
2669
-                        array_shift($m[1]);
2670
-                        if (current($m[2]) === '_parent') {
2671
-                            continue;
2672
-                        }
2673
-                        break;
2674
-                    }
2675
-
2676
-                    $output = '$this->readParentVar(' . $parentCnt . ')';
2677
-                } else {
2678
-                    if ($i === 'dwoo') {
2679
-                        $output = '$this->globals';
2680
-                        array_shift($m[2]);
2681
-                        array_shift($m[1]);
2682
-                    } elseif ($i === '_root' || $i === '__') {
2683
-                        $output = '$this->data';
2684
-                        array_shift($m[2]);
2685
-                        array_shift($m[1]);
2686
-                    } elseif ($i === '_key') {
2687
-                        $output = '$tmp_key';
2688
-                    } else {
2689
-                        $output = '$this->scope';
2690
-                    }
2691
-
2692
-                    while (count($m[1]) && $m[1][0] !== '->') {
2693
-                        $m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2694
-                        if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2695
-                            $output .= '[' . $m[2][0] . ']';
2696
-                        } else {
2697
-                            $output .= '["' . $m[2][0] . '"]';
2698
-                        }
2699
-                        array_shift($m[2]);
2700
-                        array_shift($m[1]);
2701
-                    }
2702
-
2703
-                    if ($curBlock !== 'root') {
2704
-                        $output = '(isset(' . $output . ') ? ' . $output . ':null)';
2705
-                    }
2706
-                }
2707
-
2708
-                if (count($m[2])) {
2709
-                    unset($m[0]);
2710
-                    $output = '$this->readVarInto(' . str_replace("\n", '', var_export($m, true)) . ', ' . $output . ', ' . ($curBlock == 'root' ? 'false' : 'true') . ')';
2711
-                }
2712
-            }
2713
-        } else {
2714
-            preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2715
-            unset($m[0]);
2716
-            $output = '$this->readVar(' . str_replace("\n", '', var_export($m, true)) . ')';
2717
-        }
2718
-
2719
-        return $output;
2720
-    }
2721
-
2722
-    /**
2723
-     * Flattens a variable tree, this helps in parsing very complex variables such as $var.foo[$foo.bar->baz].baz,
2724
-     * it computes the contents of the brackets first and works out from there.
2725
-     *
2726
-     * @param array $tree     the variable tree parsed by he parseVar() method that must be flattened
2727
-     * @param bool  $recursed leave that to false by default, it is only for internal use
2728
-     *
2729
-     * @return string flattened tree
2730
-     */
2731
-    protected function flattenVarTree(array $tree, $recursed = false)
2732
-    {
2733
-        $out = $recursed ? '".$this->readVarInto(' : '';
2734
-        foreach ($tree as $bit) {
2735
-            if (is_array($bit)) {
2736
-                $out .= '.' . $this->flattenVarTree($bit, false);
2737
-            } else {
2738
-                $key = str_replace('"', '\\"', $bit);
2739
-
2740
-                if (substr($key, 0, 1) === '$') {
2741
-                    $out .= '".' . $this->parseVar($key, 0, strlen($key), false, 'variable') . '."';
2742
-                } else {
2743
-                    $cnt = substr_count($key, '$');
2744
-
2745
-                    if ($this->debug) {
2746
-                        echo 'PARSING SUBVARS IN : ' . $key . "\n";
2747
-                    }
2748
-                    if ($cnt > 0) {
2749
-                        while (-- $cnt >= 0) {
2750
-                            if (isset($last)) {
2751
-                                $last = strrpos($key, '$', - (strlen($key) - $last + 1));
2752
-                            } else {
2753
-                                $last = strrpos($key, '$');
2754
-                            }
2755
-                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2756
-
2757
-                            $len = strlen($submatch[0]);
2758
-                            $key = substr_replace(
2759
-                                $key, preg_replace_callback(
2760
-                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2761
-                                        $this,
2762
-                                        'replaceVarKeyHelper'
2763
-                                    ), substr($key, $last, $len)
2764
-                                ), $last, $len
2765
-                            );
2766
-                            if ($this->debug) {
2767
-                                echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2768
-                            }
2769
-                        }
2770
-                        unset($last);
2771
-
2772
-                        $out .= $key;
2773
-                    } else {
2774
-                        $out .= $key;
2775
-                    }
2776
-                }
2777
-            }
2778
-        }
2779
-        $out .= $recursed ? ', true)."' : '';
2780
-
2781
-        return $out;
2782
-    }
2783
-
2784
-    /**
2785
-     * Helper function that parses a variable.
2786
-     *
2787
-     * @param array $match the matched variable, array(1=>"string match")
2788
-     *
2789
-     * @return string parsed variable
2790
-     */
2791
-    protected function replaceVarKeyHelper($match)
2792
-    {
2793
-        return '".' . $this->parseVar($match[0], 0, strlen($match[0]), false, 'variable') . '."';
2794
-    }
2795
-
2796
-    /**
2797
-     * Parses various constants, operators or non-quoted strings.
2798
-     *
2799
-     * @param string $in            the string within which we must parse something
2800
-     * @param int    $from          the starting offset of the parsed area
2801
-     * @param int    $to            the ending offset of the parsed area
2802
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2803
-     *                              default
2804
-     * @param string $curBlock      the current parser-block being processed
2805
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2806
-     *                              or null by default
2807
-     *
2808
-     * @return string parsed values
2809
-     * @throws Exception
2810
-     */
2811
-    protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2812
-    {
2813
-        $substr = substr($in, $from, $to - $from);
2814
-
2815
-        $end = strlen($substr);
2816
-
2817
-        if ($curBlock === 'condition') {
2818
-            $breakChars = array(
2819
-                '(',
2820
-                ')',
2821
-                ' ',
2822
-                '||',
2823
-                '&&',
2824
-                '|',
2825
-                '&',
2826
-                '>=',
2827
-                '<=',
2828
-                '===',
2829
-                '==',
2830
-                '=',
2831
-                '!==',
2832
-                '!=',
2833
-                '<<',
2834
-                '<',
2835
-                '>>',
2836
-                '>',
2837
-                '^',
2838
-                '~',
2839
-                ',',
2840
-                '+',
2841
-                '-',
2842
-                '*',
2843
-                '/',
2844
-                '%',
2845
-                '!',
2846
-                '?',
2847
-                ':',
2848
-                $this->rd,
2849
-                ';'
2850
-            );
2851
-        } elseif ($curBlock === 'modifier') {
2852
-            $breakChars = array(' ', ',', ')', ':', '|', "\r", "\n", "\t", ';', $this->rd);
2853
-        } elseif ($curBlock === 'expression') {
2854
-            $breakChars = array('/', '%', '+', '-', '*', ' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2855
-        } else {
2856
-            $breakChars = array(' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2857
-        }
2858
-
2859
-        $breaker = false;
2860
-        while (list($k, $char) = each($breakChars)) {
2861
-            $test = strpos($substr, $char);
2862
-            if ($test !== false && $test < $end) {
2863
-                $end     = $test;
2864
-                $breaker = $k;
2865
-            }
2866
-        }
2867
-
2868
-        if ($curBlock === 'condition') {
2869
-            if ($end === 0 && $breaker !== false) {
2870
-                $end = strlen($breakChars[$breaker]);
2871
-            }
2872
-        }
2873
-
2874
-        if ($end !== false) {
2875
-            $substr = substr($substr, 0, $end);
2876
-        }
2877
-
2878
-        if ($pointer !== null) {
2879
-            $pointer += strlen($substr);
2880
-        }
2881
-
2882
-        $src    = $substr;
2883
-        $substr = trim($substr);
2884
-
2885
-        if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2886
-            if ($this->debug) {
2887
-                echo 'BOOLEAN(FALSE) PARSED' . "\n";
2888
-            }
2889
-            $substr = 'false';
2890
-            $type   = self::T_BOOL;
2891
-        } elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2892
-            if ($this->debug) {
2893
-                echo 'BOOLEAN(TRUE) PARSED' . "\n";
2894
-            }
2895
-            $substr = 'true';
2896
-            $type   = self::T_BOOL;
2897
-        } elseif ($substr === 'null' || $substr === 'NULL') {
2898
-            if ($this->debug) {
2899
-                echo 'NULL PARSED' . "\n";
2900
-            }
2901
-            $substr = 'null';
2902
-            $type   = self::T_NULL;
2903
-        } elseif (is_numeric($substr)) {
2904
-            $substr = (float)$substr;
2905
-            if ((int)$substr == $substr) {
2906
-                $substr = (int)$substr;
2907
-            }
2908
-            $type = self::T_NUMERIC;
2909
-            if ($this->debug) {
2910
-                echo 'NUMBER (' . $substr . ') PARSED' . "\n";
2911
-            }
2912
-        } elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2913
-            if ($this->debug) {
2914
-                echo 'SIMPLE MATH PARSED . "\n"';
2915
-            }
2916
-            $type   = self::T_MATH;
2917
-            $substr = '(' . $substr . ')';
2918
-        } elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2919
-            if ($this->debug) {
2920
-                echo 'BREAKCHAR (' . $substr . ') PARSED' . "\n";
2921
-            }
2922
-            $type = self::T_BREAKCHAR;
2923
-            //$substr = '"'.$substr.'"';
2924
-        } else {
2925
-            $substr = $this->replaceStringVars('\'' . str_replace('\'', '\\\'', $substr) . '\'', '\'', $curBlock);
2926
-            $type   = self::T_UNQUOTED_STRING;
2927
-            if ($this->debug) {
2928
-                echo 'BLABBER (' . $substr . ') CASTED AS STRING' . "\n";
2929
-            }
2930
-        }
2931
-
2932
-        if (is_array($parsingParams)) {
2933
-            $parsingParams[] = array($substr, $src, $type);
2934
-
2935
-            return $parsingParams;
2936
-        } elseif ($curBlock === 'namedparam') {
2937
-            return array($substr, $src, $type);
2938
-        } elseif ($curBlock === 'expression') {
2939
-            return $substr;
2940
-        } else {
2941
-            throw new Exception('Something went wrong');
2942
-        }
2943
-    }
2944
-
2945
-    /**
2946
-     * Replaces variables within a parsed string.
2947
-     *
2948
-     * @param string $string   the parsed string
2949
-     * @param string $first    the first character parsed in the string, which is the string delimiter (' or ")
2950
-     * @param string $curBlock the current parser-block being processed
2951
-     *
2952
-     * @return string the original string with variables replaced
2953
-     */
2954
-    protected function replaceStringVars($string, $first, $curBlock = '')
2955
-    {
2956
-        $pos = 0;
2957
-        if ($this->debug) {
2958
-            echo 'STRING VAR REPLACEMENT : ' . $string . "\n";
2959
-        }
2960
-        // replace vars
2961
-        while (($pos = strpos($string, '$', $pos)) !== false) {
2962
-            $prev = substr($string, $pos - 1, 1);
2963
-            if ($prev === '\\') {
2964
-                ++ $pos;
2965
-                continue;
2966
-            }
2967
-
2968
-            $var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2969
-            $len = $var[0];
2970
-            $var = $this->parse(str_replace('\\' . $first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2971
-
2972
-            if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
2973
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos - 1, $len + 2);
2974
-            } else {
2975
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos, $len);
2976
-            }
2977
-            $pos += strlen($var[1]) + 2;
2978
-            if ($this->debug) {
2979
-                echo 'STRING VAR REPLACEMENT DONE : ' . $string . "\n";
2980
-            }
2981
-        }
2982
-
2983
-        // handle modifiers
2984
-        // TODO Obsolete?
2985
-        $string = preg_replace_callback(
2986
-            '#("|\')\.(.+?)\.\1((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\4|:[^`]*))*))+)#i', array(
2987
-            $this,
2988
-            'replaceModifiers'
2989
-            ), $string
2990
-        );
2991
-
2992
-        // replace escaped dollar operators by unescaped ones if required
2993
-        if ($first === "'") {
2994
-            $string = str_replace('\\$', '$', $string);
2995
-        }
2996
-
2997
-        return $string;
2998
-    }
2999
-
3000
-    /**
3001
-     * Replaces the modifiers applied to a string or a variable.
3002
-     *
3003
-     * @param array  $m        the regex matches that must be array(1=>"double or single quotes enclosing a string,
3004
-     *                         when applicable", 2=>"the string or var", 3=>"the modifiers matched")
3005
-     * @param string $curBlock the current parser-block being processed
3006
-     * @param null   $pointer
3007
-     *
3008
-     * @return string the input enclosed with various function calls according to the modifiers found
3009
-     * @throws CompilationException
3010
-     * @throws Exception
3011
-     */
3012
-    protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
3013
-    {
3014
-        if ($this->debug) {
3015
-            echo 'PARSING MODIFIERS : ' . $m[3] . "\n";
3016
-        }
3017
-
3018
-        if ($pointer !== null) {
3019
-            $pointer += strlen($m[3]);
3020
-        }
3021
-        // remove first pipe
3022
-        $cmdstrsrc = substr($m[3], 1);
3023
-        // remove last quote if present
3024
-        if (substr($cmdstrsrc, - 1, 1) === $m[1]) {
3025
-            $cmdstrsrc = substr($cmdstrsrc, 0, - 1);
3026
-            $add       = $m[1];
3027
-        }
3028
-
3029
-        $output = $m[2];
3030
-
3031
-        $continue = true;
3032
-        while (strlen($cmdstrsrc) > 0 && $continue) {
3033
-            if ($cmdstrsrc[0] === '|') {
3034
-                $cmdstrsrc = substr($cmdstrsrc, 1);
3035
-                continue;
3036
-            }
3037
-            if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
3038
-                if ($this->debug) {
3039
-                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND' . "\n";
3040
-                }
3041
-                $continue = false;
3042
-                if ($pointer !== null) {
3043
-                    $pointer -= strlen($cmdstrsrc);
3044
-                }
3045
-                break;
3046
-            }
3047
-            $cmdstr   = $cmdstrsrc;
3048
-            $paramsep = ':';
3049
-            if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
3050
-                throw new CompilationException($this, 'Invalid modifier name, started with : ' . substr($cmdstr, 0, 10));
3051
-            }
3052
-            $paramspos = !empty($match[2]) ? strlen($match[1]) : false;
3053
-            $func      = $match[1];
3054
-
3055
-            $state = 0;
3056
-            if ($paramspos === false) {
3057
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func));
3058
-                $params    = array();
3059
-                if ($this->debug) {
3060
-                    echo 'MODIFIER (' . $func . ') CALLED WITH NO PARAMS' . "\n";
3061
-                }
3062
-            } else {
3063
-                $paramstr = substr($cmdstr, $paramspos + 1);
3064
-                if (substr($paramstr, - 1, 1) === $paramsep) {
3065
-                    $paramstr = substr($paramstr, 0, - 1);
3066
-                }
3067
-
3068
-                $ptr    = 0;
3069
-                $params = array();
3070
-                while ($ptr < strlen($paramstr)) {
3071
-                    if ($this->debug) {
3072
-                        echo 'MODIFIER (' . $func . ') START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
3073
-                    }
3074
-                    if ($this->debug) {
3075
-                        echo $paramstr . '--' . $ptr . '--' . strlen($paramstr) . '--modifier' . "\n";
3076
-                    }
3077
-                    $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
3078
-                    if ($this->debug) {
3079
-                        echo 'PARAM PARSED, POINTER AT ' . $ptr . "\n";
3080
-                    }
3081
-
3082
-                    if ($ptr >= strlen($paramstr)) {
3083
-                        if ($this->debug) {
3084
-                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED' . "\n";
3085
-                        }
3086
-                        break;
3087
-                    }
3088
-
3089
-                    if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
3090
-                        if ($this->debug) {
3091
-                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT ' . $ptr . "\n";
3092
-                        }
3093
-                        if ($paramstr[$ptr] !== '|') {
3094
-                            $continue = false;
3095
-                            if ($pointer !== null) {
3096
-                                $pointer -= strlen($paramstr) - $ptr;
3097
-                            }
3098
-                        }
3099
-                        ++ $ptr;
3100
-                        break;
3101
-                    }
3102
-                    if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
3103
-                        ++ $ptr;
3104
-                    }
3105
-                }
3106
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
3107
-                foreach ($params as $k => $p) {
3108
-                    if (is_array($p) && is_array($p[1])) {
3109
-                        $state |= 2;
3110
-                    } else {
3111
-                        if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m)) {
3112
-                            $params[$k] = array($m[2], array('true', 'true'));
3113
-                        } else {
3114
-                            if ($state & 2) {
3115
-                                throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
3116
-                            }
3117
-                            $state |= 1;
3118
-                        }
3119
-                    }
3120
-                }
3121
-            }
3122
-
3123
-            // check if we must use array_map with this plugin or not
3124
-            $mapped = false;
3125
-            if (substr($func, 0, 1) === '@') {
3126
-                $func   = substr($func, 1);
3127
-                $mapped = true;
3128
-            }
3129
-
3130
-            $pluginType = $this->getPluginType($func);
3131
-
3132
-            if ($state & 2) {
3133
-                array_unshift($params, array('value', is_array($output) ? $output : array($output, $output)));
3134
-            } else {
3135
-                array_unshift($params, is_array($output) ? $output : array($output, $output));
3136
-            }
3137
-
3138
-            if ($pluginType & Core::NATIVE_PLUGIN) {
3139
-                $params = $this->mapParams($params, null, $state);
3140
-
3141
-                $params = $params['*'][0];
3142
-
3143
-                $params = self::implode_r($params);
3144
-
3145
-                if ($mapped) {
3146
-                    $output = '$this->arrayMap(\'' . $func . '\', array(' . $params . '))';
3147
-                } else {
3148
-                    $output = $func . '(' . $params . ')';
3149
-                }
3150
-            } elseif ($pluginType & Core::PROXY_PLUGIN) {
3151
-                $params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
3152
-                foreach ($params as &$p) {
3153
-                    $p = $p[0];
3154
-                }
3155
-                $output = call_user_func(array($this->getDwoo()->getPluginProxy(), 'getCode'), $func, $params);
3156
-            } elseif ($pluginType & Core::SMARTY_MODIFIER) {
3157
-                $params = $this->mapParams($params, null, $state);
3158
-                $params = $params['*'][0];
3159
-
3160
-                $params = self::implode_r($params);
3161
-
3162
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
3163
-                    $callback = $this->customPlugins[$func]['callback'];
3164
-                    if (is_array($callback)) {
3165
-                        if (is_object($callback[0])) {
3166
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3167
-                        } else {
3168
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3169
-                        }
3170
-                    } elseif ($mapped) {
3171
-                        $output = '$this->arrayMap(\'' . $callback . '\', array(' . $params . '))';
3172
-                    } else {
3173
-                        $output = $callback . '(' . $params . ')';
3174
-                    }
3175
-                } elseif ($mapped) {
3176
-                    $output = '$this->arrayMap(\'smarty_modifier_' . $func . '\', array(' . $params . '))';
3177
-                } else {
3178
-                    $output = 'smarty_modifier_' . $func . '(' . $params . ')';
3179
-                }
3180
-            } else {
3181
-                if ($pluginType & Core::CUSTOM_PLUGIN) {
3182
-                    $callback   = $this->customPlugins[$func]['callback'];
3183
-                    $pluginName = $callback;
3184
-                } else {
3185
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false || function_exists('Plugin' .
3186
-                            Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3187
-                        !== false) {
3188
-                        $pluginName = 'Plugin' . Core::toCamelCase($func);
3189
-                    } else {
3190
-                        $pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func);
3191
-                    }
3192
-                    if ($pluginType & Core::CLASS_PLUGIN) {
3193
-                        $callback = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3194
-                    } else {
3195
-                        $callback = $pluginName . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3196
-                    }
3197
-                }
3198
-                $params = $this->mapParams($params, $callback, $state);
3199
-
3200
-                foreach ($params as &$p) {
3201
-                    $p = $p[0];
3202
-                }
3203
-
3204
-                if ($pluginType & Core::FUNC_PLUGIN) {
3205
-                    if ($pluginType & Core::COMPILABLE_PLUGIN) {
3206
-                        if ($mapped) {
3207
-                            throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3208
-                        }
3209
-                        if ($pluginType & Core::CUSTOM_PLUGIN) {
3210
-                            $funcCompiler = $this->customPlugins[$func]['callback'];
3211
-                        } else {
3212
-                            if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
3213
-                                $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
3214
-                            } else {
3215
-                                $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
3216
-                                    'Compile';
3217
-                            }
3218
-                        }
3219
-                        array_unshift($params, $this);
3220
-                        $output = call_user_func_array($funcCompiler, $params);
3221
-                    } else {
3222
-                        array_unshift($params, '$this');
3223
-
3224
-                        $params = self::implode_r($params);
3225
-                        if ($mapped) {
3226
-                            $output = '$this->arrayMap(\'' . $pluginName . '\', array(' . $params . '))';
3227
-                        } else {
3228
-                            $output = $pluginName . '(' . $params . ')';
3229
-                        }
3230
-                    }
3231
-                } else {
3232
-                    if ($pluginType & Core::COMPILABLE_PLUGIN) {
3233
-                        if ($mapped) {
3234
-                            throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3235
-                        }
3236
-                        if ($pluginType & Core::CUSTOM_PLUGIN) {
3237
-                            $callback = $this->customPlugins[$func]['callback'];
3238
-                            if (!is_array($callback)) {
3239
-                                if (!method_exists($callback, 'compile')) {
3240
-                                    throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3241
-                                }
3242
-                                if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3243
-                                    $funcCompiler = array($callback, 'compile');
3244
-                                } else {
3245
-                                    $funcCompiler = array(new $callback(), 'compile');
3246
-                                }
3247
-                            } else {
3248
-                                $funcCompiler = $callback;
3249
-                            }
3250
-                        } else {
3251
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3252
-                                $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
3253
-                            } else {
3254
-                                $funcCompiler = array(
3255
-                                    Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
3256
-                                    'compile'
3257
-                                );
3258
-                            }
3259
-                            array_unshift($params, $this);
3260
-                        }
3261
-                        $output = call_user_func_array($funcCompiler, $params);
3262
-                    } else {
3263
-                        $params = self::implode_r($params);
3264
-
3265
-                        if ($pluginType & Core::CUSTOM_PLUGIN) {
3266
-                            if (is_object($callback[0])) {
3267
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3268
-                            } else {
3269
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3270
-                            }
3271
-                        } elseif ($mapped) {
3272
-                            $output = '$this->arrayMap(array($this->getObjectPlugin(\''.
3273
-                                Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '\'), 
2117
+					} else{
2118
+						$output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
2119
+					}
2120
+				}
2121
+			}
2122
+		} elseif ($pluginType & Core::PROXY_PLUGIN) {
2123
+			$output = call_user_func(array($this->getDwoo()->getPluginProxy(), 'getCode'), $func, $params);
2124
+		} elseif ($pluginType & Core::SMARTY_FUNCTION) {
2125
+			if (isset($params['*'])) {
2126
+				$params = self::implode_r($params['*'], true);
2127
+			} else {
2128
+				$params = '';
2129
+			}
2130
+
2131
+			if ($pluginType & Core::CUSTOM_PLUGIN) {
2132
+				$callback = $this->customPlugins[$func]['callback'];
2133
+				if (is_array($callback)) {
2134
+					if (is_object($callback[0])) {
2135
+						$output = 'call_user_func_array(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2136
+					} else {
2137
+						$output = 'call_user_func_array(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2138
+					}
2139
+				} else {
2140
+					$output = $callback . '(array(' . $params . '), $this)';
2141
+				}
2142
+			} else {
2143
+				$output = 'smarty_function_' . $func . '(array(' . $params . '), $this)';
2144
+			}
2145
+		} elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
2146
+			array_unshift($params, '$this');
2147
+			$params                                 = self::implode_r($params);
2148
+			$output                                 = 'Plugin' . Core::toCamelCase($func) .
2149
+				$this->templatePlugins[$func]['uuid'] . '(' . $params . ')';
2150
+			$this->templatePlugins[$func]['called'] = true;
2151
+		}
2152
+
2153
+		if (is_array($parsingParams)) {
2154
+			$parsingParams[] = array($output, $output);
2155
+
2156
+			return $parsingParams;
2157
+		} elseif ($curBlock === 'namedparam') {
2158
+			return array($output, $output);
2159
+		} else {
2160
+			return $output;
2161
+		}
2162
+	}
2163
+
2164
+	/**
2165
+	 * Parses a string.
2166
+	 *
2167
+	 * @param string $in            the string within which we must parse something
2168
+	 * @param int    $from          the starting offset of the parsed area
2169
+	 * @param int    $to            the ending offset of the parsed area
2170
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2171
+	 *                              default
2172
+	 * @param string $curBlock      the current parser-block being processed
2173
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2174
+	 *                              or null by default
2175
+	 *
2176
+	 * @return string parsed values
2177
+	 * @throws CompilationException
2178
+	 */
2179
+	protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2180
+	{
2181
+		$substr = substr($in, $from, $to - $from);
2182
+		$first  = $substr[0];
2183
+
2184
+		if ($this->debug) {
2185
+			echo 'STRING FOUND (in ' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . ')' . "\n";
2186
+		}
2187
+		$strend = false;
2188
+		$o      = $from + 1;
2189
+		while ($strend === false) {
2190
+			$strend = strpos($in, $first, $o);
2191
+			if ($strend === false) {
2192
+				throw new CompilationException($this, 'Unfinished string, started with ' . substr($in, $from, $to - $from));
2193
+			}
2194
+			if (substr($in, $strend - 1, 1) === '\\') {
2195
+				$o      = $strend + 1;
2196
+				$strend = false;
2197
+			}
2198
+		}
2199
+		if ($this->debug) {
2200
+			echo 'STRING DELIMITED: ' . substr($in, $from, $strend + 1 - $from) . "\n";
2201
+		}
2202
+
2203
+		$srcOutput = substr($in, $from, $strend + 1 - $from);
2204
+
2205
+		if ($pointer !== null) {
2206
+			$pointer += strlen($srcOutput);
2207
+		}
2208
+
2209
+		$output = $this->replaceStringVars($srcOutput, $first);
2210
+
2211
+		// handle modifiers
2212
+		if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2213
+			$modstr = $match[1];
2214
+
2215
+			if ($curBlock === 'root' && substr($modstr, - 1) === '}') {
2216
+				$modstr = substr($modstr, 0, - 1);
2217
+			}
2218
+			$modstr = str_replace('\\' . $first, $first, $modstr);
2219
+			$ptr    = 0;
2220
+			$output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2221
+
2222
+			$strend += $ptr;
2223
+			if ($pointer !== null) {
2224
+				$pointer += $ptr;
2225
+			}
2226
+			$srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2227
+		}
2228
+
2229
+		if (is_array($parsingParams)) {
2230
+			$parsingParams[] = array($output, substr($srcOutput, 1, - 1));
2231
+
2232
+			return $parsingParams;
2233
+		} elseif ($curBlock === 'namedparam') {
2234
+			return array($output, substr($srcOutput, 1, - 1));
2235
+		} else {
2236
+			return $output;
2237
+		}
2238
+	}
2239
+
2240
+	/**
2241
+	 * Parses a constant.
2242
+	 *
2243
+	 * @param string $in            the string within which we must parse something
2244
+	 * @param int    $from          the starting offset of the parsed area
2245
+	 * @param int    $to            the ending offset of the parsed area
2246
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2247
+	 *                              default
2248
+	 * @param string $curBlock      the current parser-block being processed
2249
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2250
+	 *                              or null by default
2251
+	 *
2252
+	 * @return string parsed values
2253
+	 * @throws CompilationException
2254
+	 */
2255
+	protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2256
+	{
2257
+		$substr = substr($in, $from, $to - $from);
2258
+
2259
+		if ($this->debug) {
2260
+			echo 'CONST FOUND : ' . $substr . "\n";
2261
+		}
2262
+
2263
+		if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
2264
+			throw new CompilationException($this, 'Invalid constant');
2265
+		}
2266
+
2267
+		if ($pointer !== null) {
2268
+			$pointer += strlen($m[0]);
2269
+		}
2270
+
2271
+		$output = $this->parseConstKey($m[1], $curBlock);
2272
+
2273
+		if (is_array($parsingParams)) {
2274
+			$parsingParams[] = array($output, $m[1]);
2275
+
2276
+			return $parsingParams;
2277
+		} elseif ($curBlock === 'namedparam') {
2278
+			return array($output, $m[1]);
2279
+		} else {
2280
+			return $output;
2281
+		}
2282
+	}
2283
+
2284
+	/**
2285
+	 * Parses a constant.
2286
+	 *
2287
+	 * @param string $key      the constant to parse
2288
+	 * @param string $curBlock the current parser-block being processed
2289
+	 *
2290
+	 * @return string parsed constant
2291
+	 */
2292
+	protected function parseConstKey($key, $curBlock)
2293
+	{
2294
+		if ($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === SecurityPolicy::CONST_DISALLOW) {
2295
+			return 'null';
2296
+		}
2297
+
2298
+		if ($curBlock !== 'root') {
2299
+			$output = '(defined("' . $key . '") ? ' . $key . ' : null)';
2300
+		} else {
2301
+			$output = $key;
2302
+		}
2303
+
2304
+		return $output;
2305
+	}
2306
+
2307
+	/**
2308
+	 * Parses a variable.
2309
+	 *
2310
+	 * @param string $in            the string within which we must parse something
2311
+	 * @param int    $from          the starting offset of the parsed area
2312
+	 * @param int    $to            the ending offset of the parsed area
2313
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2314
+	 *                              default
2315
+	 * @param string $curBlock      the current parser-block being processed
2316
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2317
+	 *                              or null by default
2318
+	 *
2319
+	 * @return string parsed values
2320
+	 * @throws CompilationException
2321
+	 */
2322
+	protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2323
+	{
2324
+		$methodCall = '';
2325
+		$substr     = substr($in, $from, $to - $from);
2326
+
2327
+		if (preg_match(
2328
+			'#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)' . // var key
2329
+			($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()') . // method call
2330
+			($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()') . // simple math expressions
2331
+			($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())') . // modifiers
2332
+			'#i', $substr, $match
2333
+		)) {
2334
+			$key = substr($match[1], 1);
2335
+
2336
+			$matchedLength = strlen($match[0]);
2337
+			$hasModifiers  = !empty($match[5]);
2338
+			$hasExpression = !empty($match[4]);
2339
+			$hasMethodCall = !empty($match[3]);
2340
+
2341
+			if (substr($key, - 1) == '.') {
2342
+				$key = substr($key, 0, - 1);
2343
+				-- $matchedLength;
2344
+			}
2345
+
2346
+			if ($hasMethodCall) {
2347
+				$matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2348
+				$key        = substr($match[1], 1, strrpos($match[1], '->') - 1);
2349
+				$methodCall = substr($match[1], strrpos($match[1], '->')) . $match[3];
2350
+			}
2351
+
2352
+			if ($hasModifiers) {
2353
+				$matchedLength -= strlen($match[5]);
2354
+			}
2355
+
2356
+			if ($pointer !== null) {
2357
+				$pointer += $matchedLength;
2358
+			}
2359
+
2360
+			// replace useless brackets by dot accessed vars and strip enclosing quotes if present
2361
+			$key = preg_replace('#\[(["\']?)([^$%\[.>-]+)\1\]#', '.$2', $key);
2362
+
2363
+			if ($this->debug) {
2364
+				if ($hasMethodCall) {
2365
+					echo 'METHOD CALL FOUND : $' . $key . substr($methodCall, 0, 30) . "\n";
2366
+				} else {
2367
+					echo 'VAR FOUND : $' . $key . "\n";
2368
+				}
2369
+			}
2370
+
2371
+			$key = str_replace('"', '\\"', $key);
2372
+
2373
+			$cnt = substr_count($key, '$');
2374
+			if ($cnt > 0) {
2375
+				$uid           = 0;
2376
+				$parsed        = array($uid => '');
2377
+				$current       = &$parsed;
2378
+				$curTxt        = &$parsed[$uid ++];
2379
+				$tree          = array();
2380
+				$chars         = str_split($key, 1);
2381
+				$inSplittedVar = false;
2382
+				$bracketCount  = 0;
2383
+
2384
+				while (($char = array_shift($chars)) !== null) {
2385
+					if ($char === '[') {
2386
+						if (count($tree) > 0) {
2387
+							++ $bracketCount;
2388
+						} else {
2389
+							$tree[]        = &$current;
2390
+							$current[$uid] = array($uid + 1 => '');
2391
+							$current       = &$current[$uid ++];
2392
+							$curTxt        = &$current[$uid ++];
2393
+							continue;
2394
+						}
2395
+					} elseif ($char === ']') {
2396
+						if ($bracketCount > 0) {
2397
+							-- $bracketCount;
2398
+						} else {
2399
+							$current = &$tree[count($tree) - 1];
2400
+							array_pop($tree);
2401
+							if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2402
+								$current[$uid] = '';
2403
+								$curTxt        = &$current[$uid ++];
2404
+							}
2405
+							continue;
2406
+						}
2407
+					} elseif ($char === '$') {
2408
+						if (count($tree) == 0) {
2409
+							$curTxt        = &$current[$uid ++];
2410
+							$inSplittedVar = true;
2411
+						}
2412
+					} elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2413
+						$curTxt        = &$current[$uid ++];
2414
+						$inSplittedVar = false;
2415
+					}
2416
+
2417
+					$curTxt .= $char;
2418
+				}
2419
+				unset($uid, $current, $curTxt, $tree, $chars);
2420
+
2421
+				if ($this->debug) {
2422
+					echo 'RECURSIVE VAR REPLACEMENT : ' . $key . "\n";
2423
+				}
2424
+
2425
+				$key = $this->flattenVarTree($parsed);
2426
+
2427
+				if ($this->debug) {
2428
+					echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2429
+				}
2430
+
2431
+				$output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("' . $key . '")');
2432
+			} else {
2433
+				$output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2434
+			}
2435
+
2436
+			// methods
2437
+			if ($hasMethodCall) {
2438
+				$ptr = 0;
2439
+
2440
+				$output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
2441
+
2442
+				if ($pointer !== null) {
2443
+					$pointer += $ptr;
2444
+				}
2445
+				$matchedLength += $ptr;
2446
+			}
2447
+
2448
+			if ($hasExpression) {
2449
+				// expressions
2450
+				preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[4], $expMatch);
2451
+
2452
+				foreach ($expMatch[1] as $k => $operator) {
2453
+					if (substr($expMatch[2][$k], 0, 1) === '=') {
2454
+						$assign = true;
2455
+						if ($operator === '=') {
2456
+							throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, can not use "==" in expressions');
2457
+						}
2458
+						if ($curBlock !== 'root') {
2459
+							throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2460
+						}
2461
+						$operator .= '=';
2462
+						$expMatch[2][$k] = substr($expMatch[2][$k], 1);
2463
+					}
2464
+
2465
+					if (substr($expMatch[2][$k], 0, 1) === '-' && strlen($expMatch[2][$k]) > 1) {
2466
+						$operator .= '-';
2467
+						$expMatch[2][$k] = substr($expMatch[2][$k], 1);
2468
+					}
2469
+					if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2470
+						$output = '(' . $output . $operator . $operator . ')';
2471
+						break;
2472
+					} elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2473
+						$output = '(' . $output . ' ' . $operator . ' ' . $this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2474
+					} elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2475
+						$output = '(' . $output . ' ' . $operator . ' ' . $this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2476
+					} elseif (!empty($expMatch[2][$k])) {
2477
+						$output = '(' . $output . ' ' . $operator . ' ' . str_replace(',', '.', $expMatch[2][$k]) . ')';
2478
+					} else {
2479
+						throw new CompilationException($this, 'Unfinished expression <em>' . $substr . '</em>, missing var or number after math operator');
2480
+					}
2481
+				}
2482
+			}
2483
+
2484
+			if ($this->autoEscape === true && $curBlock !== 'condition') {
2485
+				$output = '(is_string($tmp=' . $output . ') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2486
+			}
2487
+
2488
+			// handle modifiers
2489
+			if ($curBlock !== 'modifier' && $hasModifiers) {
2490
+				$ptr    = 0;
2491
+				$output = $this->replaceModifiers(array(null, null, $output, $match[5]), 'var', $ptr);
2492
+				if ($pointer !== null) {
2493
+					$pointer += $ptr;
2494
+				}
2495
+				$matchedLength += $ptr;
2496
+			}
2497
+
2498
+			if (is_array($parsingParams)) {
2499
+				$parsingParams[] = array($output, $key);
2500
+
2501
+				return $parsingParams;
2502
+			} elseif ($curBlock === 'namedparam') {
2503
+				return array($output, $key);
2504
+			} elseif ($curBlock === 'string' || $curBlock === 'delimited_string') {
2505
+				return array($matchedLength, $output);
2506
+			} elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2507
+				return $output;
2508
+			} elseif (isset($assign)) {
2509
+				return self::PHP_OPEN . $output . ';' . self::PHP_CLOSE;
2510
+			} else {
2511
+				return $output;
2512
+			}
2513
+		} else {
2514
+			if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2515
+				return array(0, '');
2516
+			} else {
2517
+				throw new CompilationException($this, 'Invalid variable name <em>' . $substr . '</em>');
2518
+			}
2519
+		}
2520
+	}
2521
+
2522
+	/**
2523
+	 * Parses any number of chained method calls/property reads.
2524
+	 *
2525
+	 * @param string $output     the variable or whatever upon which the method are called
2526
+	 * @param string $methodCall method call source, starting at "->"
2527
+	 * @param string $curBlock   the current parser-block being processed
2528
+	 * @param int    $pointer    a reference to a pointer that will be increased by the amount of characters parsed
2529
+	 *
2530
+	 * @return string parsed call(s)/read(s)
2531
+	 */
2532
+	protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
2533
+	{
2534
+		$ptr = 0;
2535
+		$len = strlen($methodCall);
2536
+
2537
+		while ($ptr < $len) {
2538
+			if (strpos($methodCall, '->', $ptr) === $ptr) {
2539
+				$ptr += 2;
2540
+			}
2541
+
2542
+			if (in_array(
2543
+				$methodCall[$ptr], array(
2544
+					';',
2545
+					',',
2546
+					'/',
2547
+					' ',
2548
+					"\t",
2549
+					"\r",
2550
+					"\n",
2551
+					')',
2552
+					'+',
2553
+					'*',
2554
+					'%',
2555
+					'=',
2556
+					'-',
2557
+					'|'
2558
+				)
2559
+			) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd
2560
+			) {
2561
+				// break char found
2562
+				break;
2563
+			}
2564
+
2565
+			if (!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
2566
+				break;
2567
+			}
2568
+
2569
+			if (empty($methMatch[2])) {
2570
+				// property
2571
+				if ($curBlock === 'root') {
2572
+					$output .= '->' . $methMatch[1];
2573
+				} else {
2574
+					$output = '(($tmp = ' . $output . ') ? $tmp->' . $methMatch[1] . ' : null)';
2575
+				}
2576
+				$ptr += strlen($methMatch[1]);
2577
+			} else {
2578
+				// method
2579
+				if (substr($methMatch[2], 0, 2) === '()') {
2580
+					$parsedCall = $methMatch[1] . '()';
2581
+					$ptr += strlen($methMatch[1]) + 2;
2582
+				} else {
2583
+					$parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2584
+				}
2585
+				if ($this->securityPolicy !== null) {
2586
+					$argPos = strpos($parsedCall, '(');
2587
+					$method = strtolower(substr($parsedCall, 0, $argPos));
2588
+					$args   = substr($parsedCall, $argPos);
2589
+					if ($curBlock === 'root') {
2590
+						$output = '$this->getSecurityPolicy()->callMethod($this, ' . $output . ', ' . var_export($method, true) . ', array' . $args . ')';
2591
+					} else {
2592
+						$output = '(($tmp = ' . $output . ') ? $this->getSecurityPolicy()->callMethod($this, $tmp, ' . var_export($method, true) . ', array' . $args . ') : null)';
2593
+					}
2594
+				} else {
2595
+					if ($curBlock === 'root') {
2596
+						$output .= '->' . $parsedCall;
2597
+					} else {
2598
+						$output = '(($tmp = ' . $output . ') ? $tmp->' . $parsedCall . ' : null)';
2599
+					}
2600
+				}
2601
+			}
2602
+		}
2603
+
2604
+		$pointer += $ptr;
2605
+
2606
+		return $output;
2607
+	}
2608
+
2609
+	/**
2610
+	 * Parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save
2611
+	 * runtime processing time.
2612
+	 *
2613
+	 * @param string $key      the variable to parse
2614
+	 * @param string $curBlock the current parser-block being processed
2615
+	 *
2616
+	 * @return string parsed variable
2617
+	 */
2618
+	protected function parseVarKey($key, $curBlock)
2619
+	{
2620
+		if ($key === '') {
2621
+			return '$this->scope';
2622
+		}
2623
+		if (substr($key, 0, 1) === '.') {
2624
+			$key = 'dwoo' . $key;
2625
+		}
2626
+		if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2627
+			$global = strtoupper($m[1]);
2628
+			if ($global === 'COOKIES') {
2629
+				$global = 'COOKIE';
2630
+			}
2631
+			$key = '$_' . $global;
2632
+			foreach (explode('.', ltrim($m[2], '.')) as $part) {
2633
+				$key .= '[' . var_export($part, true) . ']';
2634
+			}
2635
+			if ($curBlock === 'root') {
2636
+				$output = $key;
2637
+			} else {
2638
+				$output = '(isset(' . $key . ')?' . $key . ':null)';
2639
+			}
2640
+		} elseif (preg_match('#dwoo\.const\.([a-z0-9_:]+)#i', $key, $m)) {
2641
+			return $this->parseConstKey($m[1], $curBlock);
2642
+		} elseif ($this->scope !== null) {
2643
+			if (strstr($key, '.') === false && strstr($key, '[') === false && strstr($key, '->') === false) {
2644
+				if ($key === 'dwoo') {
2645
+					$output = '$this->globals';
2646
+				} elseif ($key === '_root' || $key === '__') {
2647
+					$output = '$this->data';
2648
+				} elseif ($key === '_parent' || $key === '_') {
2649
+					$output = '$this->readParentVar(1)';
2650
+				} elseif ($key === '_key') {
2651
+					$output = '$tmp_key';
2652
+				} else {
2653
+					if ($curBlock === 'root') {
2654
+						$output = '$this->scope["' . $key . '"]';
2655
+					} else {
2656
+						$output = '(isset($this->scope["' . $key . '"]) ? $this->scope["' . $key . '"] : null)';
2657
+					}
2658
+				}
2659
+			} else {
2660
+				preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+|(\\\?[\'"])[^\3]*?\3)\]?#i', $key, $m);
2661
+
2662
+				$i = $m[2][0];
2663
+				if ($i === '_parent' || $i === '_') {
2664
+					$parentCnt = 0;
2665
+
2666
+					while (true) {
2667
+						++ $parentCnt;
2668
+						array_shift($m[2]);
2669
+						array_shift($m[1]);
2670
+						if (current($m[2]) === '_parent') {
2671
+							continue;
2672
+						}
2673
+						break;
2674
+					}
2675
+
2676
+					$output = '$this->readParentVar(' . $parentCnt . ')';
2677
+				} else {
2678
+					if ($i === 'dwoo') {
2679
+						$output = '$this->globals';
2680
+						array_shift($m[2]);
2681
+						array_shift($m[1]);
2682
+					} elseif ($i === '_root' || $i === '__') {
2683
+						$output = '$this->data';
2684
+						array_shift($m[2]);
2685
+						array_shift($m[1]);
2686
+					} elseif ($i === '_key') {
2687
+						$output = '$tmp_key';
2688
+					} else {
2689
+						$output = '$this->scope';
2690
+					}
2691
+
2692
+					while (count($m[1]) && $m[1][0] !== '->') {
2693
+						$m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2694
+						if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2695
+							$output .= '[' . $m[2][0] . ']';
2696
+						} else {
2697
+							$output .= '["' . $m[2][0] . '"]';
2698
+						}
2699
+						array_shift($m[2]);
2700
+						array_shift($m[1]);
2701
+					}
2702
+
2703
+					if ($curBlock !== 'root') {
2704
+						$output = '(isset(' . $output . ') ? ' . $output . ':null)';
2705
+					}
2706
+				}
2707
+
2708
+				if (count($m[2])) {
2709
+					unset($m[0]);
2710
+					$output = '$this->readVarInto(' . str_replace("\n", '', var_export($m, true)) . ', ' . $output . ', ' . ($curBlock == 'root' ? 'false' : 'true') . ')';
2711
+				}
2712
+			}
2713
+		} else {
2714
+			preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2715
+			unset($m[0]);
2716
+			$output = '$this->readVar(' . str_replace("\n", '', var_export($m, true)) . ')';
2717
+		}
2718
+
2719
+		return $output;
2720
+	}
2721
+
2722
+	/**
2723
+	 * Flattens a variable tree, this helps in parsing very complex variables such as $var.foo[$foo.bar->baz].baz,
2724
+	 * it computes the contents of the brackets first and works out from there.
2725
+	 *
2726
+	 * @param array $tree     the variable tree parsed by he parseVar() method that must be flattened
2727
+	 * @param bool  $recursed leave that to false by default, it is only for internal use
2728
+	 *
2729
+	 * @return string flattened tree
2730
+	 */
2731
+	protected function flattenVarTree(array $tree, $recursed = false)
2732
+	{
2733
+		$out = $recursed ? '".$this->readVarInto(' : '';
2734
+		foreach ($tree as $bit) {
2735
+			if (is_array($bit)) {
2736
+				$out .= '.' . $this->flattenVarTree($bit, false);
2737
+			} else {
2738
+				$key = str_replace('"', '\\"', $bit);
2739
+
2740
+				if (substr($key, 0, 1) === '$') {
2741
+					$out .= '".' . $this->parseVar($key, 0, strlen($key), false, 'variable') . '."';
2742
+				} else {
2743
+					$cnt = substr_count($key, '$');
2744
+
2745
+					if ($this->debug) {
2746
+						echo 'PARSING SUBVARS IN : ' . $key . "\n";
2747
+					}
2748
+					if ($cnt > 0) {
2749
+						while (-- $cnt >= 0) {
2750
+							if (isset($last)) {
2751
+								$last = strrpos($key, '$', - (strlen($key) - $last + 1));
2752
+							} else {
2753
+								$last = strrpos($key, '$');
2754
+							}
2755
+							preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2756
+
2757
+							$len = strlen($submatch[0]);
2758
+							$key = substr_replace(
2759
+								$key, preg_replace_callback(
2760
+									'#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2761
+										$this,
2762
+										'replaceVarKeyHelper'
2763
+									), substr($key, $last, $len)
2764
+								), $last, $len
2765
+							);
2766
+							if ($this->debug) {
2767
+								echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2768
+							}
2769
+						}
2770
+						unset($last);
2771
+
2772
+						$out .= $key;
2773
+					} else {
2774
+						$out .= $key;
2775
+					}
2776
+				}
2777
+			}
2778
+		}
2779
+		$out .= $recursed ? ', true)."' : '';
2780
+
2781
+		return $out;
2782
+	}
2783
+
2784
+	/**
2785
+	 * Helper function that parses a variable.
2786
+	 *
2787
+	 * @param array $match the matched variable, array(1=>"string match")
2788
+	 *
2789
+	 * @return string parsed variable
2790
+	 */
2791
+	protected function replaceVarKeyHelper($match)
2792
+	{
2793
+		return '".' . $this->parseVar($match[0], 0, strlen($match[0]), false, 'variable') . '."';
2794
+	}
2795
+
2796
+	/**
2797
+	 * Parses various constants, operators or non-quoted strings.
2798
+	 *
2799
+	 * @param string $in            the string within which we must parse something
2800
+	 * @param int    $from          the starting offset of the parsed area
2801
+	 * @param int    $to            the ending offset of the parsed area
2802
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by
2803
+	 *                              default
2804
+	 * @param string $curBlock      the current parser-block being processed
2805
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed,
2806
+	 *                              or null by default
2807
+	 *
2808
+	 * @return string parsed values
2809
+	 * @throws Exception
2810
+	 */
2811
+	protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2812
+	{
2813
+		$substr = substr($in, $from, $to - $from);
2814
+
2815
+		$end = strlen($substr);
2816
+
2817
+		if ($curBlock === 'condition') {
2818
+			$breakChars = array(
2819
+				'(',
2820
+				')',
2821
+				' ',
2822
+				'||',
2823
+				'&&',
2824
+				'|',
2825
+				'&',
2826
+				'>=',
2827
+				'<=',
2828
+				'===',
2829
+				'==',
2830
+				'=',
2831
+				'!==',
2832
+				'!=',
2833
+				'<<',
2834
+				'<',
2835
+				'>>',
2836
+				'>',
2837
+				'^',
2838
+				'~',
2839
+				',',
2840
+				'+',
2841
+				'-',
2842
+				'*',
2843
+				'/',
2844
+				'%',
2845
+				'!',
2846
+				'?',
2847
+				':',
2848
+				$this->rd,
2849
+				';'
2850
+			);
2851
+		} elseif ($curBlock === 'modifier') {
2852
+			$breakChars = array(' ', ',', ')', ':', '|', "\r", "\n", "\t", ';', $this->rd);
2853
+		} elseif ($curBlock === 'expression') {
2854
+			$breakChars = array('/', '%', '+', '-', '*', ' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2855
+		} else {
2856
+			$breakChars = array(' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2857
+		}
2858
+
2859
+		$breaker = false;
2860
+		while (list($k, $char) = each($breakChars)) {
2861
+			$test = strpos($substr, $char);
2862
+			if ($test !== false && $test < $end) {
2863
+				$end     = $test;
2864
+				$breaker = $k;
2865
+			}
2866
+		}
2867
+
2868
+		if ($curBlock === 'condition') {
2869
+			if ($end === 0 && $breaker !== false) {
2870
+				$end = strlen($breakChars[$breaker]);
2871
+			}
2872
+		}
2873
+
2874
+		if ($end !== false) {
2875
+			$substr = substr($substr, 0, $end);
2876
+		}
2877
+
2878
+		if ($pointer !== null) {
2879
+			$pointer += strlen($substr);
2880
+		}
2881
+
2882
+		$src    = $substr;
2883
+		$substr = trim($substr);
2884
+
2885
+		if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2886
+			if ($this->debug) {
2887
+				echo 'BOOLEAN(FALSE) PARSED' . "\n";
2888
+			}
2889
+			$substr = 'false';
2890
+			$type   = self::T_BOOL;
2891
+		} elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2892
+			if ($this->debug) {
2893
+				echo 'BOOLEAN(TRUE) PARSED' . "\n";
2894
+			}
2895
+			$substr = 'true';
2896
+			$type   = self::T_BOOL;
2897
+		} elseif ($substr === 'null' || $substr === 'NULL') {
2898
+			if ($this->debug) {
2899
+				echo 'NULL PARSED' . "\n";
2900
+			}
2901
+			$substr = 'null';
2902
+			$type   = self::T_NULL;
2903
+		} elseif (is_numeric($substr)) {
2904
+			$substr = (float)$substr;
2905
+			if ((int)$substr == $substr) {
2906
+				$substr = (int)$substr;
2907
+			}
2908
+			$type = self::T_NUMERIC;
2909
+			if ($this->debug) {
2910
+				echo 'NUMBER (' . $substr . ') PARSED' . "\n";
2911
+			}
2912
+		} elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2913
+			if ($this->debug) {
2914
+				echo 'SIMPLE MATH PARSED . "\n"';
2915
+			}
2916
+			$type   = self::T_MATH;
2917
+			$substr = '(' . $substr . ')';
2918
+		} elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2919
+			if ($this->debug) {
2920
+				echo 'BREAKCHAR (' . $substr . ') PARSED' . "\n";
2921
+			}
2922
+			$type = self::T_BREAKCHAR;
2923
+			//$substr = '"'.$substr.'"';
2924
+		} else {
2925
+			$substr = $this->replaceStringVars('\'' . str_replace('\'', '\\\'', $substr) . '\'', '\'', $curBlock);
2926
+			$type   = self::T_UNQUOTED_STRING;
2927
+			if ($this->debug) {
2928
+				echo 'BLABBER (' . $substr . ') CASTED AS STRING' . "\n";
2929
+			}
2930
+		}
2931
+
2932
+		if (is_array($parsingParams)) {
2933
+			$parsingParams[] = array($substr, $src, $type);
2934
+
2935
+			return $parsingParams;
2936
+		} elseif ($curBlock === 'namedparam') {
2937
+			return array($substr, $src, $type);
2938
+		} elseif ($curBlock === 'expression') {
2939
+			return $substr;
2940
+		} else {
2941
+			throw new Exception('Something went wrong');
2942
+		}
2943
+	}
2944
+
2945
+	/**
2946
+	 * Replaces variables within a parsed string.
2947
+	 *
2948
+	 * @param string $string   the parsed string
2949
+	 * @param string $first    the first character parsed in the string, which is the string delimiter (' or ")
2950
+	 * @param string $curBlock the current parser-block being processed
2951
+	 *
2952
+	 * @return string the original string with variables replaced
2953
+	 */
2954
+	protected function replaceStringVars($string, $first, $curBlock = '')
2955
+	{
2956
+		$pos = 0;
2957
+		if ($this->debug) {
2958
+			echo 'STRING VAR REPLACEMENT : ' . $string . "\n";
2959
+		}
2960
+		// replace vars
2961
+		while (($pos = strpos($string, '$', $pos)) !== false) {
2962
+			$prev = substr($string, $pos - 1, 1);
2963
+			if ($prev === '\\') {
2964
+				++ $pos;
2965
+				continue;
2966
+			}
2967
+
2968
+			$var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2969
+			$len = $var[0];
2970
+			$var = $this->parse(str_replace('\\' . $first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2971
+
2972
+			if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
2973
+				$string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos - 1, $len + 2);
2974
+			} else {
2975
+				$string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos, $len);
2976
+			}
2977
+			$pos += strlen($var[1]) + 2;
2978
+			if ($this->debug) {
2979
+				echo 'STRING VAR REPLACEMENT DONE : ' . $string . "\n";
2980
+			}
2981
+		}
2982
+
2983
+		// handle modifiers
2984
+		// TODO Obsolete?
2985
+		$string = preg_replace_callback(
2986
+			'#("|\')\.(.+?)\.\1((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\4|:[^`]*))*))+)#i', array(
2987
+			$this,
2988
+			'replaceModifiers'
2989
+			), $string
2990
+		);
2991
+
2992
+		// replace escaped dollar operators by unescaped ones if required
2993
+		if ($first === "'") {
2994
+			$string = str_replace('\\$', '$', $string);
2995
+		}
2996
+
2997
+		return $string;
2998
+	}
2999
+
3000
+	/**
3001
+	 * Replaces the modifiers applied to a string or a variable.
3002
+	 *
3003
+	 * @param array  $m        the regex matches that must be array(1=>"double or single quotes enclosing a string,
3004
+	 *                         when applicable", 2=>"the string or var", 3=>"the modifiers matched")
3005
+	 * @param string $curBlock the current parser-block being processed
3006
+	 * @param null   $pointer
3007
+	 *
3008
+	 * @return string the input enclosed with various function calls according to the modifiers found
3009
+	 * @throws CompilationException
3010
+	 * @throws Exception
3011
+	 */
3012
+	protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
3013
+	{
3014
+		if ($this->debug) {
3015
+			echo 'PARSING MODIFIERS : ' . $m[3] . "\n";
3016
+		}
3017
+
3018
+		if ($pointer !== null) {
3019
+			$pointer += strlen($m[3]);
3020
+		}
3021
+		// remove first pipe
3022
+		$cmdstrsrc = substr($m[3], 1);
3023
+		// remove last quote if present
3024
+		if (substr($cmdstrsrc, - 1, 1) === $m[1]) {
3025
+			$cmdstrsrc = substr($cmdstrsrc, 0, - 1);
3026
+			$add       = $m[1];
3027
+		}
3028
+
3029
+		$output = $m[2];
3030
+
3031
+		$continue = true;
3032
+		while (strlen($cmdstrsrc) > 0 && $continue) {
3033
+			if ($cmdstrsrc[0] === '|') {
3034
+				$cmdstrsrc = substr($cmdstrsrc, 1);
3035
+				continue;
3036
+			}
3037
+			if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
3038
+				if ($this->debug) {
3039
+					echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND' . "\n";
3040
+				}
3041
+				$continue = false;
3042
+				if ($pointer !== null) {
3043
+					$pointer -= strlen($cmdstrsrc);
3044
+				}
3045
+				break;
3046
+			}
3047
+			$cmdstr   = $cmdstrsrc;
3048
+			$paramsep = ':';
3049
+			if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
3050
+				throw new CompilationException($this, 'Invalid modifier name, started with : ' . substr($cmdstr, 0, 10));
3051
+			}
3052
+			$paramspos = !empty($match[2]) ? strlen($match[1]) : false;
3053
+			$func      = $match[1];
3054
+
3055
+			$state = 0;
3056
+			if ($paramspos === false) {
3057
+				$cmdstrsrc = substr($cmdstrsrc, strlen($func));
3058
+				$params    = array();
3059
+				if ($this->debug) {
3060
+					echo 'MODIFIER (' . $func . ') CALLED WITH NO PARAMS' . "\n";
3061
+				}
3062
+			} else {
3063
+				$paramstr = substr($cmdstr, $paramspos + 1);
3064
+				if (substr($paramstr, - 1, 1) === $paramsep) {
3065
+					$paramstr = substr($paramstr, 0, - 1);
3066
+				}
3067
+
3068
+				$ptr    = 0;
3069
+				$params = array();
3070
+				while ($ptr < strlen($paramstr)) {
3071
+					if ($this->debug) {
3072
+						echo 'MODIFIER (' . $func . ') START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
3073
+					}
3074
+					if ($this->debug) {
3075
+						echo $paramstr . '--' . $ptr . '--' . strlen($paramstr) . '--modifier' . "\n";
3076
+					}
3077
+					$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
3078
+					if ($this->debug) {
3079
+						echo 'PARAM PARSED, POINTER AT ' . $ptr . "\n";
3080
+					}
3081
+
3082
+					if ($ptr >= strlen($paramstr)) {
3083
+						if ($this->debug) {
3084
+							echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED' . "\n";
3085
+						}
3086
+						break;
3087
+					}
3088
+
3089
+					if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
3090
+						if ($this->debug) {
3091
+							echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT ' . $ptr . "\n";
3092
+						}
3093
+						if ($paramstr[$ptr] !== '|') {
3094
+							$continue = false;
3095
+							if ($pointer !== null) {
3096
+								$pointer -= strlen($paramstr) - $ptr;
3097
+							}
3098
+						}
3099
+						++ $ptr;
3100
+						break;
3101
+					}
3102
+					if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
3103
+						++ $ptr;
3104
+					}
3105
+				}
3106
+				$cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
3107
+				foreach ($params as $k => $p) {
3108
+					if (is_array($p) && is_array($p[1])) {
3109
+						$state |= 2;
3110
+					} else {
3111
+						if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m)) {
3112
+							$params[$k] = array($m[2], array('true', 'true'));
3113
+						} else {
3114
+							if ($state & 2) {
3115
+								throw new CompilationException($this, 'You can not use an unnamed parameter after a named one');
3116
+							}
3117
+							$state |= 1;
3118
+						}
3119
+					}
3120
+				}
3121
+			}
3122
+
3123
+			// check if we must use array_map with this plugin or not
3124
+			$mapped = false;
3125
+			if (substr($func, 0, 1) === '@') {
3126
+				$func   = substr($func, 1);
3127
+				$mapped = true;
3128
+			}
3129
+
3130
+			$pluginType = $this->getPluginType($func);
3131
+
3132
+			if ($state & 2) {
3133
+				array_unshift($params, array('value', is_array($output) ? $output : array($output, $output)));
3134
+			} else {
3135
+				array_unshift($params, is_array($output) ? $output : array($output, $output));
3136
+			}
3137
+
3138
+			if ($pluginType & Core::NATIVE_PLUGIN) {
3139
+				$params = $this->mapParams($params, null, $state);
3140
+
3141
+				$params = $params['*'][0];
3142
+
3143
+				$params = self::implode_r($params);
3144
+
3145
+				if ($mapped) {
3146
+					$output = '$this->arrayMap(\'' . $func . '\', array(' . $params . '))';
3147
+				} else {
3148
+					$output = $func . '(' . $params . ')';
3149
+				}
3150
+			} elseif ($pluginType & Core::PROXY_PLUGIN) {
3151
+				$params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
3152
+				foreach ($params as &$p) {
3153
+					$p = $p[0];
3154
+				}
3155
+				$output = call_user_func(array($this->getDwoo()->getPluginProxy(), 'getCode'), $func, $params);
3156
+			} elseif ($pluginType & Core::SMARTY_MODIFIER) {
3157
+				$params = $this->mapParams($params, null, $state);
3158
+				$params = $params['*'][0];
3159
+
3160
+				$params = self::implode_r($params);
3161
+
3162
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
3163
+					$callback = $this->customPlugins[$func]['callback'];
3164
+					if (is_array($callback)) {
3165
+						if (is_object($callback[0])) {
3166
+							$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3167
+						} else {
3168
+							$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3169
+						}
3170
+					} elseif ($mapped) {
3171
+						$output = '$this->arrayMap(\'' . $callback . '\', array(' . $params . '))';
3172
+					} else {
3173
+						$output = $callback . '(' . $params . ')';
3174
+					}
3175
+				} elseif ($mapped) {
3176
+					$output = '$this->arrayMap(\'smarty_modifier_' . $func . '\', array(' . $params . '))';
3177
+				} else {
3178
+					$output = 'smarty_modifier_' . $func . '(' . $params . ')';
3179
+				}
3180
+			} else {
3181
+				if ($pluginType & Core::CUSTOM_PLUGIN) {
3182
+					$callback   = $this->customPlugins[$func]['callback'];
3183
+					$pluginName = $callback;
3184
+				} else {
3185
+					if (class_exists('Plugin' . Core::toCamelCase($func)) !== false || function_exists('Plugin' .
3186
+							Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3187
+						!== false) {
3188
+						$pluginName = 'Plugin' . Core::toCamelCase($func);
3189
+					} else {
3190
+						$pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func);
3191
+					}
3192
+					if ($pluginType & Core::CLASS_PLUGIN) {
3193
+						$callback = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3194
+					} else {
3195
+						$callback = $pluginName . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3196
+					}
3197
+				}
3198
+				$params = $this->mapParams($params, $callback, $state);
3199
+
3200
+				foreach ($params as &$p) {
3201
+					$p = $p[0];
3202
+				}
3203
+
3204
+				if ($pluginType & Core::FUNC_PLUGIN) {
3205
+					if ($pluginType & Core::COMPILABLE_PLUGIN) {
3206
+						if ($mapped) {
3207
+							throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3208
+						}
3209
+						if ($pluginType & Core::CUSTOM_PLUGIN) {
3210
+							$funcCompiler = $this->customPlugins[$func]['callback'];
3211
+						} else {
3212
+							if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
3213
+								$funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
3214
+							} else {
3215
+								$funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
3216
+									'Compile';
3217
+							}
3218
+						}
3219
+						array_unshift($params, $this);
3220
+						$output = call_user_func_array($funcCompiler, $params);
3221
+					} else {
3222
+						array_unshift($params, '$this');
3223
+
3224
+						$params = self::implode_r($params);
3225
+						if ($mapped) {
3226
+							$output = '$this->arrayMap(\'' . $pluginName . '\', array(' . $params . '))';
3227
+						} else {
3228
+							$output = $pluginName . '(' . $params . ')';
3229
+						}
3230
+					}
3231
+				} else {
3232
+					if ($pluginType & Core::COMPILABLE_PLUGIN) {
3233
+						if ($mapped) {
3234
+							throw new CompilationException($this, 'The @ operator can not be used on compiled plugins.');
3235
+						}
3236
+						if ($pluginType & Core::CUSTOM_PLUGIN) {
3237
+							$callback = $this->customPlugins[$func]['callback'];
3238
+							if (!is_array($callback)) {
3239
+								if (!method_exists($callback, 'compile')) {
3240
+									throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3241
+								}
3242
+								if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3243
+									$funcCompiler = array($callback, 'compile');
3244
+								} else {
3245
+									$funcCompiler = array(new $callback(), 'compile');
3246
+								}
3247
+							} else {
3248
+								$funcCompiler = $callback;
3249
+							}
3250
+						} else {
3251
+							if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3252
+								$funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
3253
+							} else {
3254
+								$funcCompiler = array(
3255
+									Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
3256
+									'compile'
3257
+								);
3258
+							}
3259
+							array_unshift($params, $this);
3260
+						}
3261
+						$output = call_user_func_array($funcCompiler, $params);
3262
+					} else {
3263
+						$params = self::implode_r($params);
3264
+
3265
+						if ($pluginType & Core::CUSTOM_PLUGIN) {
3266
+							if (is_object($callback[0])) {
3267
+								$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3268
+							} else {
3269
+								$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3270
+							}
3271
+						} elseif ($mapped) {
3272
+							$output = '$this->arrayMap(array($this->getObjectPlugin(\''.
3273
+								Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '\'), 
3274 3274
                             \'process\'), array(' . $params . '))';
3275
-                        } else {
3276
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3277
-                                $output = '$this->classCall(\'Plugin' . Core::toCamelCase($func) . '\', array(' . $params . '))';
3278
-                            } else {
3279
-                                $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
3280
-                            }
3281
-                        }
3282
-                    }
3283
-                }
3284
-            }
3285
-        }
3286
-
3287
-        if ($curBlock === 'namedparam') {
3288
-            return array($output, $output);
3289
-        } elseif ($curBlock === 'var' || $m[1] === null) {
3290
-            return $output;
3291
-        } elseif ($curBlock === 'string' || $curBlock === 'root') {
3292
-            return $m[1] . '.' . $output . '.' . $m[1] . (isset($add) ? $add : null);
3293
-        }
3294
-
3295
-        return '';
3296
-    }
3297
-
3298
-    /**
3299
-     * Recursively implodes an array in a similar manner as var_export() does but with some tweaks
3300
-     * to handle pre-compiled values and the fact that we do not need to enclose everything with
3301
-     * "array" and do not require top-level keys to be displayed.
3302
-     *
3303
-     * @param array $params        the array to implode
3304
-     * @param bool  $recursiveCall if set to true, the function outputs key names for the top level
3305
-     *
3306
-     * @return string the imploded array
3307
-     */
3308
-    public static function implode_r(array $params, $recursiveCall = false)
3309
-    {
3310
-        $out = '';
3311
-        foreach ($params as $k => $p) {
3312
-            if (is_array($p)) {
3313
-                $out2 = 'array(';
3314
-                foreach ($p as $k2 => $v) {
3315
-                    $out2 .= var_export($k2, true) . ' => ' . (is_array($v) ? 'array(' . self::implode_r($v, true) . ')' : $v) . ', ';
3316
-                }
3317
-                $p = rtrim($out2, ', ') . ')';
3318
-            }
3319
-            if ($recursiveCall) {
3320
-                $out .= var_export($k, true) . ' => ' . $p . ', ';
3321
-            } else {
3322
-                $out .= $p . ', ';
3323
-            }
3324
-        }
3325
-
3326
-        return rtrim($out, ', ');
3327
-    }
3328
-
3329
-    /**
3330
-     * Returns the plugin type of a plugin and adds it to the used plugins array if required.
3331
-     *
3332
-     * @param string $name plugin name, as found in the template
3333
-     *
3334
-     * @return int type as a multi bit flag composed of the Dwoo plugin types constants
3335
-     * @throws Exception
3336
-     * @throws SecurityException
3337
-     * @throws Exception
3338
-     */
3339
-    protected function getPluginType($name)
3340
-    {
3341
-        $pluginType = - 1;
3342
-
3343
-        if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) || ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3344
-            $phpFunc = true;
3345
-        } elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3346
-            throw new SecurityException('Call to a disallowed php function : ' . $name);
3347
-        }
3348
-
3349
-        while ($pluginType <= 0) {
3350
-            // Template plugin compilable
3351
-            if (isset($this->templatePlugins[$name])) {
3352
-                $pluginType = Core::TEMPLATE_PLUGIN | Core::COMPILABLE_PLUGIN;
3353
-            } // Custom plugin
3354
-            elseif (isset($this->customPlugins[$name])) {
3355
-                $pluginType = $this->customPlugins[$name]['type'] | Core::CUSTOM_PLUGIN;
3356
-            } // Class blocks plugin
3357
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), false) !==
3358
-                false) {
3359
-                if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3360
-                    $pluginType = Core::BLOCK_PLUGIN;
3361
-                } else {
3362
-                    $pluginType = Core::CLASS_PLUGIN;
3363
-                }
3364
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name));
3365
-                if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3366
-                    $pluginType |= Core::COMPILABLE_PLUGIN;
3367
-                }
3368
-            } // Class functions plugin
3369
-            elseif(class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name), false) !==
3370
-                false) {
3371
-                $pluginType = Core::CLASS_PLUGIN;
3372
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name));
3373
-                if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3374
-                    $pluginType |= Core::COMPILABLE_PLUGIN;
3375
-                }
3376
-            } // Class without namespace
3377
-            elseif(class_exists('Plugin' . Core::toCamelCase($name), false) !== false) {
3378
-                $pluginType = Core::CLASS_PLUGIN;
3379
-                $interfaces = class_implements('Plugin' . Core::toCamelCase($name));
3380
-                if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3381
-                    $pluginType |= Core::COMPILABLE_PLUGIN;
3382
-                }
3383
-            } // Function plugin (with/without namespaces)
3384
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
3385
-                    ($name)) !==
3386
-                false || function_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3387
-                $pluginType = Core::FUNC_PLUGIN;
3388
-            } // Function plugin compile (with/without namespaces)
3389
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name) .
3390
-                    'Compile') !== false || function_exists('Plugin' . Core::toCamelCase($name) . 'Compile') !==
3391
-                false) {
3392
-                $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3393
-            } // Helper plugin compile
3394
-            elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name) . 'Compile')
3395
-                !== false) {
3396
-                $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3397
-            } // Smarty modifier
3398
-            elseif (function_exists('smarty_modifier_' . $name) !== false) {
3399
-                $pluginType = Core::SMARTY_MODIFIER;
3400
-            } // Smarty function
3401
-            elseif (function_exists('smarty_function_' . $name) !== false) {
3402
-                $pluginType = Core::SMARTY_FUNCTION;
3403
-            } // Smarty block
3404
-            elseif (function_exists('smarty_block_' . $name) !== false) {
3405
-                $pluginType = Core::SMARTY_BLOCK;
3406
-            } // Everything else
3407
-            else {
3408
-                if ($pluginType === - 1) {
3409
-                    try {
3410
-                        $this->getDwoo()->getLoader()->loadPlugin(
3411
-                            'Plugin' . Core::toCamelCase($name));
3412
-                    }
3413
-                    catch (Exception $e) {
3414
-                        if (isset($phpFunc)) {
3415
-                            $pluginType = Core::NATIVE_PLUGIN;
3416
-                        } elseif (is_object($this->getDwoo()->getPluginProxy()) && $this->getDwoo()->getPluginProxy()->handles($name)) {
3417
-                            $pluginType = Core::PROXY_PLUGIN;
3418
-                            break;
3419
-                        } else {
3420
-                            throw $e;
3421
-                        }
3422
-                    }
3423
-                } else {
3424
-                    throw new Exception('Plugin "' . $name . '" could not be found, type:' . $pluginType);
3425
-                }
3426
-                ++ $pluginType;
3427
-            }
3428
-        }
3429
-
3430
-        if (($pluginType & Core::COMPILABLE_PLUGIN) === 0 && ($pluginType & Core::NATIVE_PLUGIN) === 0 && ($pluginType & Core::PROXY_PLUGIN) === 0) {
3431
-            $this->addUsedPlugin(Core::toCamelCase($name), $pluginType);
3432
-        }
3433
-
3434
-        return $pluginType;
3435
-    }
3436
-
3437
-    /**
3438
-     * Allows a plugin to load another one at compile time, this will also mark
3439
-     * it as used by this template so it will be loaded at runtime (which can be
3440
-     * useful for compiled plugins that rely on another plugin when their compiled
3441
-     * code runs).
3442
-     *
3443
-     * @param string $name the plugin name
3444
-     *
3445
-     * @return void
3446
-     */
3447
-    public function loadPlugin($name)
3448
-    {
3449
-        $this->getPluginType($name);
3450
-    }
3451
-
3452
-    /**
3453
-     * Runs htmlentities over the matched <?php ?> blocks when the security policy enforces that.
3454
-     *
3455
-     * @param array $match matched php block
3456
-     *
3457
-     * @return string the htmlentities-converted string
3458
-     */
3459
-    protected function phpTagEncodingHelper($match)
3460
-    {
3461
-        return htmlspecialchars($match[0]);
3462
-    }
3463
-
3464
-    /**
3465
-     * Maps the parameters received from the template onto the parameters required by the given callback.
3466
-     *
3467
-     * @param array    $params   the array of parameters
3468
-     * @param callback $callback the function or method to reflect on to find out the required parameters
3469
-     * @param int      $callType the type of call in the template, 0 = no params, 1 = php-style call, 2 = named
3470
-     *                           parameters call
3471
-     * @param array    $map      the parameter map to use, if not provided it will be built from the callback
3472
-     *
3473
-     * @return array parameters sorted in the correct order with missing optional parameters filled
3474
-     * @throws CompilationException
3475
-     */
3476
-    protected function mapParams(array $params, $callback, $callType = 2, $map = null)
3477
-    {
3478
-        if (!$map) {
3479
-            $map = $this->getParamMap($callback);
3480
-        }
3481
-
3482
-        $paramlist = array();
3483
-
3484
-        // transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
3485
-        $ps = array();
3486
-        foreach ($params as $p) {
3487
-            if (is_array($p[1])) {
3488
-                $ps[$p[0]] = $p[1];
3489
-            } else {
3490
-                $ps[] = $p;
3491
-            }
3492
-        }
3493
-
3494
-        // loops over the param map and assigns values from the template or default value for unset optional params
3495
-        while (list($k, $v) = each($map)) {
3496
-            if ($v[0] === '*') {
3497
-                // "rest" array parameter, fill every remaining params in it and then break
3498
-                if (count($ps) === 0) {
3499
-                    if ($v[1] === false) {
3500
-                        throw new CompilationException(
3501
-                            $this, 'Rest argument missing for ' . str_replace(
3502
-                                array(
3503
-                                    Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3504
-                                'Compile'
3505
-                                ), '', (is_array($callback) ? $callback[0] : $callback)
3506
-                            )
3507
-                        );
3508
-                    } else {
3509
-                        break;
3510
-                    }
3511
-                }
3512
-                $tmp  = array();
3513
-                $tmp2 = array();
3514
-                $tmp3 = array();
3515
-                foreach ($ps as $i => $p) {
3516
-                    $tmp[$i]  = $p[0];
3517
-                    $tmp2[$i] = $p[1];
3518
-                    $tmp3[$i] = isset($p[2]) ? $p[2] : 0;
3519
-                    unset($ps[$i]);
3520
-                }
3521
-                $paramlist[$v[0]] = array($tmp, $tmp2, $tmp3);
3522
-                unset($tmp, $tmp2, $i, $p);
3523
-                break;
3524
-            } elseif (isset($ps[$v[0]])) {
3525
-                // parameter is defined as named param
3526
-                $paramlist[$v[0]] = $ps[$v[0]];
3527
-                unset($ps[$v[0]]);
3528
-            } elseif (isset($ps[$k])) {
3529
-                // parameter is defined as ordered param
3530
-                $paramlist[$v[0]] = $ps[$k];
3531
-                unset($ps[$k]);
3532
-            } elseif ($v[1] === false) {
3533
-                // parameter is not defined and not optional, throw error
3534
-                if (is_array($callback)) {
3535
-                    if (is_object($callback[0])) {
3536
-                        $name = get_class($callback[0]) . '::' . $callback[1];
3537
-                    } else {
3538
-                        $name = $callback[0];
3539
-                    }
3540
-                } else {
3541
-                    $name = $callback;
3542
-                }
3543
-
3544
-                throw new CompilationException(
3545
-                    $this, 'Argument ' . $k . '/' . $v[0] . ' missing for ' . str_replace(
3546
-                        array(
3547
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3548
-                        'Compile'
3549
-                        ), '', $name
3550
-                    )
3551
-                );
3552
-            } elseif ($v[2] === null) {
3553
-                // enforce lowercased null if default value is null (php outputs NULL with var export)
3554
-                $paramlist[$v[0]] = array('null', null, self::T_NULL);
3555
-            } else {
3556
-                // outputs default value with var_export
3557
-                $paramlist[$v[0]] = array(var_export($v[2], true), $v[2]);
3558
-            }
3559
-        }
3560
-
3561
-        if (count($ps)) {
3562
-            foreach ($ps as $i => $p) {
3563
-                array_push($paramlist, $p);
3564
-            }
3565
-        }
3566
-
3567
-        return $paramlist;
3568
-    }
3569
-
3570
-    /**
3571
-     * Returns the parameter map of the given callback, it filters out entries typed as Dwoo and Compiler and turns the
3572
-     * rest parameter into a "*".
3573
-     *
3574
-     * @param callback $callback the function/method to reflect on
3575
-     *
3576
-     * @return array processed parameter map
3577
-     */
3578
-    protected function getParamMap($callback)
3579
-    {
3580
-        if (is_null($callback)) {
3581
-            return array(array('*', true));
3582
-        }
3583
-        if (is_array($callback)) {
3584
-            $ref = new ReflectionMethod($callback[0], $callback[1]);
3585
-        } else {
3586
-            $ref = new ReflectionFunction($callback);
3587
-        }
3588
-
3589
-        $out = array();
3590
-        foreach ($ref->getParameters() as $param) {
3591
-            if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Core') {
3592
-                continue;
3593
-            }
3594
-            if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Compiler') {
3595
-                continue;
3596
-            }
3597
-            if ($param->getName() === 'rest' && $param->isArray() === true) {
3598
-                $out[] = array('*', $param->isOptional(), null);
3599
-                continue;
3600
-            }
3601
-            $out[] = array(
3602
-                $param->getName(),
3603
-                $param->isOptional(),
3604
-                $param->isOptional() ? $param->getDefaultValue() : null
3605
-            );
3606
-        }
3607
-
3608
-        return $out;
3609
-    }
3610
-
3611
-    /**
3612
-     * Returns a default instance of this compiler, used by default by all Dwoo templates that do not have a
3613
-     * specific compiler assigned and when you do not override the default compiler factory function.
3614
-     *
3615
-     * @see    Core::setDefaultCompilerFactory()
3616
-     * @return Compiler
3617
-     */
3618
-    public static function compilerFactory()
3619
-    {
3620
-        if (self::$instance === null) {
3621
-            self::$instance = new self();
3622
-        }
3623
-
3624
-        return self::$instance;
3625
-    }
3275
+						} else {
3276
+							if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3277
+								$output = '$this->classCall(\'Plugin' . Core::toCamelCase($func) . '\', array(' . $params . '))';
3278
+							} else {
3279
+								$output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
3280
+							}
3281
+						}
3282
+					}
3283
+				}
3284
+			}
3285
+		}
3286
+
3287
+		if ($curBlock === 'namedparam') {
3288
+			return array($output, $output);
3289
+		} elseif ($curBlock === 'var' || $m[1] === null) {
3290
+			return $output;
3291
+		} elseif ($curBlock === 'string' || $curBlock === 'root') {
3292
+			return $m[1] . '.' . $output . '.' . $m[1] . (isset($add) ? $add : null);
3293
+		}
3294
+
3295
+		return '';
3296
+	}
3297
+
3298
+	/**
3299
+	 * Recursively implodes an array in a similar manner as var_export() does but with some tweaks
3300
+	 * to handle pre-compiled values and the fact that we do not need to enclose everything with
3301
+	 * "array" and do not require top-level keys to be displayed.
3302
+	 *
3303
+	 * @param array $params        the array to implode
3304
+	 * @param bool  $recursiveCall if set to true, the function outputs key names for the top level
3305
+	 *
3306
+	 * @return string the imploded array
3307
+	 */
3308
+	public static function implode_r(array $params, $recursiveCall = false)
3309
+	{
3310
+		$out = '';
3311
+		foreach ($params as $k => $p) {
3312
+			if (is_array($p)) {
3313
+				$out2 = 'array(';
3314
+				foreach ($p as $k2 => $v) {
3315
+					$out2 .= var_export($k2, true) . ' => ' . (is_array($v) ? 'array(' . self::implode_r($v, true) . ')' : $v) . ', ';
3316
+				}
3317
+				$p = rtrim($out2, ', ') . ')';
3318
+			}
3319
+			if ($recursiveCall) {
3320
+				$out .= var_export($k, true) . ' => ' . $p . ', ';
3321
+			} else {
3322
+				$out .= $p . ', ';
3323
+			}
3324
+		}
3325
+
3326
+		return rtrim($out, ', ');
3327
+	}
3328
+
3329
+	/**
3330
+	 * Returns the plugin type of a plugin and adds it to the used plugins array if required.
3331
+	 *
3332
+	 * @param string $name plugin name, as found in the template
3333
+	 *
3334
+	 * @return int type as a multi bit flag composed of the Dwoo plugin types constants
3335
+	 * @throws Exception
3336
+	 * @throws SecurityException
3337
+	 * @throws Exception
3338
+	 */
3339
+	protected function getPluginType($name)
3340
+	{
3341
+		$pluginType = - 1;
3342
+
3343
+		if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) || ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3344
+			$phpFunc = true;
3345
+		} elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3346
+			throw new SecurityException('Call to a disallowed php function : ' . $name);
3347
+		}
3348
+
3349
+		while ($pluginType <= 0) {
3350
+			// Template plugin compilable
3351
+			if (isset($this->templatePlugins[$name])) {
3352
+				$pluginType = Core::TEMPLATE_PLUGIN | Core::COMPILABLE_PLUGIN;
3353
+			} // Custom plugin
3354
+			elseif (isset($this->customPlugins[$name])) {
3355
+				$pluginType = $this->customPlugins[$name]['type'] | Core::CUSTOM_PLUGIN;
3356
+			} // Class blocks plugin
3357
+			elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), false) !==
3358
+				false) {
3359
+				if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3360
+					$pluginType = Core::BLOCK_PLUGIN;
3361
+				} else {
3362
+					$pluginType = Core::CLASS_PLUGIN;
3363
+				}
3364
+				$interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name));
3365
+				if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3366
+					$pluginType |= Core::COMPILABLE_PLUGIN;
3367
+				}
3368
+			} // Class functions plugin
3369
+			elseif(class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name), false) !==
3370
+				false) {
3371
+				$pluginType = Core::CLASS_PLUGIN;
3372
+				$interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name));
3373
+				if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3374
+					$pluginType |= Core::COMPILABLE_PLUGIN;
3375
+				}
3376
+			} // Class without namespace
3377
+			elseif(class_exists('Plugin' . Core::toCamelCase($name), false) !== false) {
3378
+				$pluginType = Core::CLASS_PLUGIN;
3379
+				$interfaces = class_implements('Plugin' . Core::toCamelCase($name));
3380
+				if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3381
+					$pluginType |= Core::COMPILABLE_PLUGIN;
3382
+				}
3383
+			} // Function plugin (with/without namespaces)
3384
+			elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
3385
+					($name)) !==
3386
+				false || function_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3387
+				$pluginType = Core::FUNC_PLUGIN;
3388
+			} // Function plugin compile (with/without namespaces)
3389
+			elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name) .
3390
+					'Compile') !== false || function_exists('Plugin' . Core::toCamelCase($name) . 'Compile') !==
3391
+				false) {
3392
+				$pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3393
+			} // Helper plugin compile
3394
+			elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name) . 'Compile')
3395
+				!== false) {
3396
+				$pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3397
+			} // Smarty modifier
3398
+			elseif (function_exists('smarty_modifier_' . $name) !== false) {
3399
+				$pluginType = Core::SMARTY_MODIFIER;
3400
+			} // Smarty function
3401
+			elseif (function_exists('smarty_function_' . $name) !== false) {
3402
+				$pluginType = Core::SMARTY_FUNCTION;
3403
+			} // Smarty block
3404
+			elseif (function_exists('smarty_block_' . $name) !== false) {
3405
+				$pluginType = Core::SMARTY_BLOCK;
3406
+			} // Everything else
3407
+			else {
3408
+				if ($pluginType === - 1) {
3409
+					try {
3410
+						$this->getDwoo()->getLoader()->loadPlugin(
3411
+							'Plugin' . Core::toCamelCase($name));
3412
+					}
3413
+					catch (Exception $e) {
3414
+						if (isset($phpFunc)) {
3415
+							$pluginType = Core::NATIVE_PLUGIN;
3416
+						} elseif (is_object($this->getDwoo()->getPluginProxy()) && $this->getDwoo()->getPluginProxy()->handles($name)) {
3417
+							$pluginType = Core::PROXY_PLUGIN;
3418
+							break;
3419
+						} else {
3420
+							throw $e;
3421
+						}
3422
+					}
3423
+				} else {
3424
+					throw new Exception('Plugin "' . $name . '" could not be found, type:' . $pluginType);
3425
+				}
3426
+				++ $pluginType;
3427
+			}
3428
+		}
3429
+
3430
+		if (($pluginType & Core::COMPILABLE_PLUGIN) === 0 && ($pluginType & Core::NATIVE_PLUGIN) === 0 && ($pluginType & Core::PROXY_PLUGIN) === 0) {
3431
+			$this->addUsedPlugin(Core::toCamelCase($name), $pluginType);
3432
+		}
3433
+
3434
+		return $pluginType;
3435
+	}
3436
+
3437
+	/**
3438
+	 * Allows a plugin to load another one at compile time, this will also mark
3439
+	 * it as used by this template so it will be loaded at runtime (which can be
3440
+	 * useful for compiled plugins that rely on another plugin when their compiled
3441
+	 * code runs).
3442
+	 *
3443
+	 * @param string $name the plugin name
3444
+	 *
3445
+	 * @return void
3446
+	 */
3447
+	public function loadPlugin($name)
3448
+	{
3449
+		$this->getPluginType($name);
3450
+	}
3451
+
3452
+	/**
3453
+	 * Runs htmlentities over the matched <?php ?> blocks when the security policy enforces that.
3454
+	 *
3455
+	 * @param array $match matched php block
3456
+	 *
3457
+	 * @return string the htmlentities-converted string
3458
+	 */
3459
+	protected function phpTagEncodingHelper($match)
3460
+	{
3461
+		return htmlspecialchars($match[0]);
3462
+	}
3463
+
3464
+	/**
3465
+	 * Maps the parameters received from the template onto the parameters required by the given callback.
3466
+	 *
3467
+	 * @param array    $params   the array of parameters
3468
+	 * @param callback $callback the function or method to reflect on to find out the required parameters
3469
+	 * @param int      $callType the type of call in the template, 0 = no params, 1 = php-style call, 2 = named
3470
+	 *                           parameters call
3471
+	 * @param array    $map      the parameter map to use, if not provided it will be built from the callback
3472
+	 *
3473
+	 * @return array parameters sorted in the correct order with missing optional parameters filled
3474
+	 * @throws CompilationException
3475
+	 */
3476
+	protected function mapParams(array $params, $callback, $callType = 2, $map = null)
3477
+	{
3478
+		if (!$map) {
3479
+			$map = $this->getParamMap($callback);
3480
+		}
3481
+
3482
+		$paramlist = array();
3483
+
3484
+		// transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
3485
+		$ps = array();
3486
+		foreach ($params as $p) {
3487
+			if (is_array($p[1])) {
3488
+				$ps[$p[0]] = $p[1];
3489
+			} else {
3490
+				$ps[] = $p;
3491
+			}
3492
+		}
3493
+
3494
+		// loops over the param map and assigns values from the template or default value for unset optional params
3495
+		while (list($k, $v) = each($map)) {
3496
+			if ($v[0] === '*') {
3497
+				// "rest" array parameter, fill every remaining params in it and then break
3498
+				if (count($ps) === 0) {
3499
+					if ($v[1] === false) {
3500
+						throw new CompilationException(
3501
+							$this, 'Rest argument missing for ' . str_replace(
3502
+								array(
3503
+									Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3504
+								'Compile'
3505
+								), '', (is_array($callback) ? $callback[0] : $callback)
3506
+							)
3507
+						);
3508
+					} else {
3509
+						break;
3510
+					}
3511
+				}
3512
+				$tmp  = array();
3513
+				$tmp2 = array();
3514
+				$tmp3 = array();
3515
+				foreach ($ps as $i => $p) {
3516
+					$tmp[$i]  = $p[0];
3517
+					$tmp2[$i] = $p[1];
3518
+					$tmp3[$i] = isset($p[2]) ? $p[2] : 0;
3519
+					unset($ps[$i]);
3520
+				}
3521
+				$paramlist[$v[0]] = array($tmp, $tmp2, $tmp3);
3522
+				unset($tmp, $tmp2, $i, $p);
3523
+				break;
3524
+			} elseif (isset($ps[$v[0]])) {
3525
+				// parameter is defined as named param
3526
+				$paramlist[$v[0]] = $ps[$v[0]];
3527
+				unset($ps[$v[0]]);
3528
+			} elseif (isset($ps[$k])) {
3529
+				// parameter is defined as ordered param
3530
+				$paramlist[$v[0]] = $ps[$k];
3531
+				unset($ps[$k]);
3532
+			} elseif ($v[1] === false) {
3533
+				// parameter is not defined and not optional, throw error
3534
+				if (is_array($callback)) {
3535
+					if (is_object($callback[0])) {
3536
+						$name = get_class($callback[0]) . '::' . $callback[1];
3537
+					} else {
3538
+						$name = $callback[0];
3539
+					}
3540
+				} else {
3541
+					$name = $callback;
3542
+				}
3543
+
3544
+				throw new CompilationException(
3545
+					$this, 'Argument ' . $k . '/' . $v[0] . ' missing for ' . str_replace(
3546
+						array(
3547
+							Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3548
+						'Compile'
3549
+						), '', $name
3550
+					)
3551
+				);
3552
+			} elseif ($v[2] === null) {
3553
+				// enforce lowercased null if default value is null (php outputs NULL with var export)
3554
+				$paramlist[$v[0]] = array('null', null, self::T_NULL);
3555
+			} else {
3556
+				// outputs default value with var_export
3557
+				$paramlist[$v[0]] = array(var_export($v[2], true), $v[2]);
3558
+			}
3559
+		}
3560
+
3561
+		if (count($ps)) {
3562
+			foreach ($ps as $i => $p) {
3563
+				array_push($paramlist, $p);
3564
+			}
3565
+		}
3566
+
3567
+		return $paramlist;
3568
+	}
3569
+
3570
+	/**
3571
+	 * Returns the parameter map of the given callback, it filters out entries typed as Dwoo and Compiler and turns the
3572
+	 * rest parameter into a "*".
3573
+	 *
3574
+	 * @param callback $callback the function/method to reflect on
3575
+	 *
3576
+	 * @return array processed parameter map
3577
+	 */
3578
+	protected function getParamMap($callback)
3579
+	{
3580
+		if (is_null($callback)) {
3581
+			return array(array('*', true));
3582
+		}
3583
+		if (is_array($callback)) {
3584
+			$ref = new ReflectionMethod($callback[0], $callback[1]);
3585
+		} else {
3586
+			$ref = new ReflectionFunction($callback);
3587
+		}
3588
+
3589
+		$out = array();
3590
+		foreach ($ref->getParameters() as $param) {
3591
+			if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Core') {
3592
+				continue;
3593
+			}
3594
+			if (($class = $param->getClass()) !== null && $class->name === 'Dwoo\Compiler') {
3595
+				continue;
3596
+			}
3597
+			if ($param->getName() === 'rest' && $param->isArray() === true) {
3598
+				$out[] = array('*', $param->isOptional(), null);
3599
+				continue;
3600
+			}
3601
+			$out[] = array(
3602
+				$param->getName(),
3603
+				$param->isOptional(),
3604
+				$param->isOptional() ? $param->getDefaultValue() : null
3605
+			);
3606
+		}
3607
+
3608
+		return $out;
3609
+	}
3610
+
3611
+	/**
3612
+	 * Returns a default instance of this compiler, used by default by all Dwoo templates that do not have a
3613
+	 * specific compiler assigned and when you do not override the default compiler factory function.
3614
+	 *
3615
+	 * @see    Core::setDefaultCompilerFactory()
3616
+	 * @return Compiler
3617
+	 */
3618
+	public static function compilerFactory()
3619
+	{
3620
+		if (self::$instance === null) {
3621
+			self::$instance = new self();
3622
+		}
3623
+
3624
+		return self::$instance;
3625
+	}
3626 3626
 }
Please login to merge, or discard this patch.
Switch Indentation   +43 added lines, -43 removed lines patch added patch discarded remove patch
@@ -769,13 +769,13 @@  discard block
 block discarded – undo
769 769
                         $search = array('{<\?.*?\?>}', '{<%.*?%>}');
770 770
                     }
771 771
                     switch ($this->securityPolicy->getPhpHandling()) {
772
-                        case SecurityPolicy::PHP_ALLOW:
773
-                            break;
774
-                        case SecurityPolicy::PHP_ENCODE:
775
-                            $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
-                            break;
777
-                        case SecurityPolicy::PHP_REMOVE:
778
-                            $tpl = preg_replace($search, '', $tpl);
772
+                    case SecurityPolicy::PHP_ALLOW:
773
+                        break;
774
+                    case SecurityPolicy::PHP_ENCODE:
775
+                        $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
776
+                        break;
777
+                    case SecurityPolicy::PHP_REMOVE:
778
+                        $tpl = preg_replace($search, '', $tpl);
779 779
                     }
780 780
                 }
781 781
             }
@@ -875,42 +875,42 @@  discard block
 block discarded – undo
875 875
             }
876 876
 
877 877
             switch ($type) {
878
-                case Core::BLOCK_PLUGIN:
879
-                case Core::CLASS_PLUGIN:
880
-                    if (class_exists('Plugin' . $plugin) !== false) {
881
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
-                    } else {
884
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
-                    }
887
-                    break;
888
-                case Core::FUNC_PLUGIN:
889
-                    if (function_exists('Plugin' . $plugin) !== false) {
890
-                        $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
891
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
-                    } else {
893
-                        $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
-                        "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
-                    }
896
-                    break;
897
-                case Core::SMARTY_MODIFIER:
898
-                    $output .= "if (function_exists('smarty_modifier_$plugin')===false)".
899
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
900
-                    break;
901
-                case Core::SMARTY_FUNCTION:
902
-                    $output .= "if (function_exists('smarty_function_$plugin')===false)".
903
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
904
-                    break;
905
-                case Core::SMARTY_BLOCK:
906
-                    $output .= "if (function_exists('smarty_block_$plugin')===false)".
907
-                    "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
908
-                    break;
909
-                case Core::PROXY_PLUGIN:
910
-                    $output .= $this->getDwoo()->getPluginProxy()->getLoader($plugin);
911
-                    break;
912
-                default:
913
-                    throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
878
+            case Core::BLOCK_PLUGIN:
879
+            case Core::CLASS_PLUGIN:
880
+                if (class_exists('Plugin' . $plugin) !== false) {
881
+                    $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
882
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883
+                } else {
884
+                    $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
885
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886
+                }
887
+                break;
888
+            case Core::FUNC_PLUGIN:
889
+                if (function_exists('Plugin' . $plugin) !== false) {
890
+                    $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
891
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892
+                } else {
893
+                    $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
894
+                    "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895
+                }
896
+                break;
897
+            case Core::SMARTY_MODIFIER:
898
+                $output .= "if (function_exists('smarty_modifier_$plugin')===false)".
899
+                "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
900
+                break;
901
+            case Core::SMARTY_FUNCTION:
902
+                $output .= "if (function_exists('smarty_function_$plugin')===false)".
903
+                "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
904
+                break;
905
+            case Core::SMARTY_BLOCK:
906
+                $output .= "if (function_exists('smarty_block_$plugin')===false)".
907
+                "\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
908
+                break;
909
+            case Core::PROXY_PLUGIN:
910
+                $output .= $this->getDwoo()->getPluginProxy()->getLoader($plugin);
911
+                break;
912
+            default:
913
+                throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
914 914
             }
915 915
         }
916 916
 
Please login to merge, or discard this patch.
Spacing   +369 added lines, -372 removed lines patch added patch discarded remove patch
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
      */
295 295
     public function setNestedCommentsHandling($allow = true)
296 296
     {
297
-        $this->allowNestedComments = (bool)$allow;
297
+        $this->allowNestedComments = (bool) $allow;
298 298
     }
299 299
 
300 300
     /**
@@ -319,7 +319,7 @@  discard block
 block discarded – undo
319 319
      */
320 320
     public function setLooseOpeningHandling($allow = false)
321 321
     {
322
-        $this->allowLooseOpenings = (bool)$allow;
322
+        $this->allowLooseOpenings = (bool) $allow;
323 323
     }
324 324
 
325 325
     /**
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
      */
345 345
     public function setAutoEscape($enabled)
346 346
     {
347
-        $this->autoEscape = (bool)$enabled;
347
+        $this->autoEscape = (bool) $enabled;
348 348
     }
349 349
 
350 350
     /**
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
     {
372 372
         if ($autoload) {
373 373
             $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', Core::toCamelCase($callback));
374
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . $name;
374
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.$name;
375 375
 
376 376
             if (class_exists($class)) {
377 377
                 $callback = array(new $class($this), 'process');
@@ -396,12 +396,12 @@  discard block
 block discarded – undo
396 396
     {
397 397
         if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
398 398
             unset($this->processors['pre'][$index]);
399
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
399
+        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
400 400
                     $callback),
401 401
                 $this->processors['pre'], true)) !== false) {
402 402
             unset($this->processors['pre'][$index]);
403 403
         } else {
404
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
404
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
405 405
             foreach ($this->processors['pre'] as $index => $proc) {
406 406
                 if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
407 407
                     unset($this->processors['pre'][$index]);
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
     {
425 425
         if ($autoload) {
426 426
             $name  = str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
427
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . Core::toCamelCase($name);
427
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.Core::toCamelCase($name);
428 428
 
429 429
             if (class_exists($class)) {
430 430
                 $callback = array(new $class($this), 'process');
@@ -449,12 +449,12 @@  discard block
 block discarded – undo
449 449
     {
450 450
         if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
451 451
             unset($this->processors['post'][$index]);
452
-        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
452
+        } elseif (($index = array_search(Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '',
453 453
                     $callback),
454 454
                 $this->processors['post'], true)) !== false) {
455 455
             unset($this->processors['post'][$index]);
456 456
         } else {
457
-            $class = Core::NAMESPACE_PLUGINS_PROCESSORS . str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
457
+            $class = Core::NAMESPACE_PLUGINS_PROCESSORS.str_replace(Core::NAMESPACE_PLUGINS_PROCESSORS, '', $callback);
458 458
             foreach ($this->processors['post'] as $index => $proc) {
459 459
                 if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
460 460
                     unset($this->processors['post'][$index]);
@@ -480,7 +480,7 @@  discard block
 block discarded – undo
480 480
                 $this->getDwoo()->getLoader()->loadPlugin($name);
481 481
             }
482 482
             catch (Exception $e) {
483
-                throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
483
+                throw new Exception('Processor '.$name.' could not be found in your plugin directories, please ensure it is in a file named '.$name.'.php in the plugin directory');
484 484
             }
485 485
         }
486 486
 
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
     public function setTemplateSource($newSource, $fromPointer = false)
667 667
     {
668 668
         if ($fromPointer === true) {
669
-            $this->templateSource = substr($this->templateSource, 0, $this->pointer) . $newSource;
669
+            $this->templateSource = substr($this->templateSource, 0, $this->pointer).$newSource;
670 670
         } else {
671 671
             $this->templateSource = $newSource;
672 672
         }
@@ -737,11 +737,11 @@  discard block
 block discarded – undo
737 737
 
738 738
                 if ($this->debug) {
739 739
                     echo "\n";
740
-                    echo 'COMPILER INIT' . "\n";
740
+                    echo 'COMPILER INIT'."\n";
741 741
                 }
742 742
 
743 743
                 if ($this->debug) {
744
-                    echo 'PROCESSING PREPROCESSORS (' . count($this->processors['pre']) . ')' . "\n";
744
+                    echo 'PROCESSING PREPROCESSORS ('.count($this->processors['pre']).')'."\n";
745 745
                 }
746 746
 
747 747
                 // runs preprocessors
@@ -785,23 +785,23 @@  discard block
 block discarded – undo
785 785
             if ($pos === false) {
786 786
                 $this->push(substr($tpl, $ptr), 0);
787 787
                 break;
788
-            } elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
789
-                $this->push(substr($tpl, $ptr, $pos - $ptr - 1) . $this->ld);
790
-                $ptr = $pos + strlen($this->ld);
791
-            } elseif (preg_match('/^' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . 'literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', substr($tpl, $pos), $litOpen)) {
792
-                if (!preg_match('/' . $this->ldr . ($this->allowLooseOpenings ? '\s*' : '') . '\/literal' . ($this->allowLooseOpenings ? '\s*' : '') . $this->rdr . '/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
788
+            } elseif (substr($tpl, $pos-1, 1) === '\\' && substr($tpl, $pos-2, 1) !== '\\') {
789
+                $this->push(substr($tpl, $ptr, $pos-$ptr-1).$this->ld);
790
+                $ptr = $pos+strlen($this->ld);
791
+            } elseif (preg_match('/^'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', substr($tpl, $pos), $litOpen)) {
792
+                if (!preg_match('/'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'\/literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
793 793
                     throw new CompilationException($this, 'The {literal} blocks must be closed explicitly with {/literal}');
794 794
                 }
795 795
                 $endpos = $litClose[0][1];
796
-                $this->push(substr($tpl, $ptr, $pos - $ptr) . substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
797
-                $ptr = $endpos + strlen($litClose[0][0]);
796
+                $this->push(substr($tpl, $ptr, $pos-$ptr).substr($tpl, $pos+strlen($litOpen[0]), $endpos-$pos-strlen($litOpen[0])));
797
+                $ptr = $endpos+strlen($litClose[0][0]);
798 798
             } else {
799
-                if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
800
-                    $this->push(substr($tpl, $ptr, $pos - $ptr - 1));
799
+                if (substr($tpl, $pos-2, 1) === '\\' && substr($tpl, $pos-1, 1) === '\\') {
800
+                    $this->push(substr($tpl, $ptr, $pos-$ptr-1));
801 801
                     $ptr = $pos;
802 802
                 }
803 803
 
804
-                $this->push(substr($tpl, $ptr, $pos - $ptr));
804
+                $this->push(substr($tpl, $ptr, $pos-$ptr));
805 805
                 $ptr = $pos;
806 806
 
807 807
                 $pos += strlen($this->ld);
@@ -819,7 +819,7 @@  discard block
 block discarded – undo
819 819
 
820 820
                 // check that there is an end tag present
821 821
                 if (strpos($tpl, $this->rd, $pos) === false) {
822
-                    throw new CompilationException($this, 'A template tag was not closed, started with "' . substr($tpl, $ptr, 30) . '"');
822
+                    throw new CompilationException($this, 'A template tag was not closed, started with "'.substr($tpl, $ptr, 30).'"');
823 823
                 }
824 824
 
825 825
                 $ptr += strlen($this->ld);
@@ -833,7 +833,7 @@  discard block
 block discarded – undo
833 833
                         continue 2;
834 834
                     }
835 835
 
836
-                    $len = $subptr - $ptr;
836
+                    $len = $subptr-$ptr;
837 837
                     $this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
838 838
                     $ptr += $len;
839 839
 
@@ -847,7 +847,7 @@  discard block
 block discarded – undo
847 847
         $compiled .= $this->removeBlock('TopLevelBlock');
848 848
 
849 849
         if ($this->debug) {
850
-            echo 'PROCESSING POSTPROCESSORS' . "\n";
850
+            echo 'PROCESSING POSTPROCESSORS'."\n";
851 851
         }
852 852
 
853 853
         foreach ($this->processors['post'] as $postProc) {
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
         unset($postProc);
864 864
 
865 865
         if ($this->debug) {
866
-            echo 'COMPILATION COMPLETE : MEM USAGE : ' . memory_get_usage() . "\n";
866
+            echo 'COMPILATION COMPLETE : MEM USAGE : '.memory_get_usage()."\n";
867 867
         }
868 868
 
869 869
         $output = "<?php\n/* template head */\n";
@@ -877,20 +877,20 @@  discard block
 block discarded – undo
877 877
             switch ($type) {
878 878
                 case Core::BLOCK_PLUGIN:
879 879
                 case Core::CLASS_PLUGIN:
880
-                    if (class_exists('Plugin' . $plugin) !== false) {
881
-                        $output .= "if (class_exists('" . "Plugin" . $plugin . "')===false)".
880
+                    if (class_exists('Plugin'.$plugin) !== false) {
881
+                        $output .= "if (class_exists('"."Plugin".$plugin."')===false)".
882 882
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
883 883
                     } else {
884
-                        $output .= "if (class_exists('" . Core::NAMESPACE_PLUGINS_BLOCKS . "Plugin" . $plugin . "')===false)".
884
+                        $output .= "if (class_exists('".Core::NAMESPACE_PLUGINS_BLOCKS."Plugin".$plugin."')===false)".
885 885
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
886 886
                     }
887 887
                     break;
888 888
                 case Core::FUNC_PLUGIN:
889
-                    if (function_exists('Plugin' . $plugin) !== false) {
890
-                        $output .= "if (function_exists('" . "Plugin" . $plugin . "')===false)".
889
+                    if (function_exists('Plugin'.$plugin) !== false) {
890
+                        $output .= "if (function_exists('"."Plugin".$plugin."')===false)".
891 891
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
892 892
                     } else {
893
-                        $output .= "if (function_exists('" . Core::NAMESPACE_PLUGINS_FUNCTIONS . "Plugin" . $plugin . "')===false)".
893
+                        $output .= "if (function_exists('".Core::NAMESPACE_PLUGINS_FUNCTIONS."Plugin".$plugin."')===false)".
894 894
                         "\n\t\$this->getLoader()->loadPlugin('Plugin$plugin');\n";
895 895
                     }
896 896
                     break;
@@ -910,7 +910,7 @@  discard block
 block discarded – undo
910 910
                     $output .= $this->getDwoo()->getPluginProxy()->getLoader($plugin);
911 911
                     break;
912 912
                 default:
913
-                    throw new CompilationException($this, 'Type error for ' . $plugin . ' with type' . $type);
913
+                    throw new CompilationException($this, 'Type error for '.$plugin.' with type'.$type);
914 914
             }
915 915
         }
916 916
 
@@ -921,30 +921,30 @@  discard block
 block discarded – undo
921 921
         }
922 922
         foreach ($this->templatePlugins as $function) {
923 923
             if (isset($function['called']) && $function['called'] === true) {
924
-                $output .= $function['body'] . PHP_EOL;
924
+                $output .= $function['body'].PHP_EOL;
925 925
             }
926 926
         }
927 927
 
928
-        $output .= $compiled . "\n?>";
928
+        $output .= $compiled."\n?>";
929 929
 
930
-        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*' . preg_quote(self::PHP_CLOSE, '/') . preg_quote(self::PHP_OPEN, '/') . ')/', ";\n", $output);
931
-        $output = str_replace(self::PHP_CLOSE . self::PHP_OPEN, "\n", $output);
930
+        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*'.preg_quote(self::PHP_CLOSE, '/').preg_quote(self::PHP_OPEN, '/').')/', ";\n", $output);
931
+        $output = str_replace(self::PHP_CLOSE.self::PHP_OPEN, "\n", $output);
932 932
 
933 933
         // handle <?xml tag at the beginning
934 934
         $output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
935 935
 
936 936
         // add another line break after PHP closing tags that have a line break following,
937 937
         // as we do not know whether it's intended, and PHP will strip it otherwise
938
-        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0' . "\n", $output);
938
+        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0'."\n", $output);
939 939
 
940 940
         if ($this->debug) {
941
-            echo '=============================================================================================' . "\n";
941
+            echo '============================================================================================='."\n";
942 942
             $lines = preg_split('{\r\n|\n|<br />}', $output);
943 943
             array_shift($lines);
944 944
             foreach ($lines as $i => $line) {
945
-                echo ($i + 1) . '. ' . $line . "\r\n";
945
+                echo ($i+1).'. '.$line."\r\n";
946 946
             }
947
-            echo '=============================================================================================' . "\n";
947
+            echo '============================================================================================='."\n";
948 948
         }
949 949
 
950 950
         $this->template = $this->dwoo = null;
@@ -961,13 +961,13 @@  discard block
 block discarded – undo
961 961
     protected function resolveSubTemplateDependencies($function)
962 962
     {
963 963
         if ($this->debug) {
964
-            echo 'Compiler::' . __FUNCTION__ . "\n";
964
+            echo 'Compiler::'.__FUNCTION__."\n";
965 965
         }
966 966
 
967 967
         $body = $this->templatePlugins[$function]['body'];
968 968
         foreach ($this->templatePlugins as $func => $attr) {
969
-            if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS .
970
-            'Plugin' . Core::toCamelCase($func)) !== false) {
969
+            if ($func !== $function && !isset($attr['called']) && strpos($body, Core::NAMESPACE_PLUGINS_FUNCTIONS.
970
+            'Plugin'.Core::toCamelCase($func)) !== false) {
971 971
                 $this->templatePlugins[$func]['called'] = true;
972 972
                 $this->resolveSubTemplateDependencies($func);
973 973
             }
@@ -991,14 +991,14 @@  discard block
 block discarded – undo
991 991
 
992 992
         if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
993 993
             // buffer is not initialized yet (the block has just been created)
994
-            $this->stack[count($this->stack) - 2]['buffer'] .= (string)$content;
994
+            $this->stack[count($this->stack)-2]['buffer'] .= (string) $content;
995 995
             $this->curBlock['buffer'] = '';
996 996
         } else {
997 997
             if (!isset($this->curBlock['buffer'])) {
998 998
                 throw new CompilationException($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
999 999
             }
1000 1000
             // append current content to current block's buffer
1001
-            $this->curBlock['buffer'] .= (string)$content;
1001
+            $this->curBlock['buffer'] .= (string) $content;
1002 1002
         }
1003 1003
         $this->line += $lineCount;
1004 1004
     }
@@ -1068,23 +1068,23 @@  discard block
 block discarded – undo
1068 1068
     public function addBlock($type, array $params, $paramtype)
1069 1069
     {
1070 1070
         if ($this->debug) {
1071
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1071
+            echo 'Compiler::'.__FUNCTION__."\n";
1072 1072
         }
1073 1073
 
1074
-        $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1074
+        $class = Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($type);
1075 1075
         if (class_exists($class) === false) {
1076 1076
             $this->getDwoo()->getLoader()->loadPlugin($type);
1077 1077
         }
1078 1078
         $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1079 1079
 
1080
-        $this->stack[]  = array(
1080
+        $this->stack[] = array(
1081 1081
             'type'   => $type,
1082 1082
             'params' => $params,
1083 1083
             'custom' => false,
1084 1084
             'class'  => $class,
1085 1085
             'buffer' => null
1086 1086
         );
1087
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1087
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1088 1088
 
1089 1089
         return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1090 1090
     }
@@ -1109,14 +1109,14 @@  discard block
 block discarded – undo
1109 1109
 
1110 1110
         $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1111 1111
 
1112
-        $this->stack[]  = array(
1112
+        $this->stack[] = array(
1113 1113
             'type'   => $type,
1114 1114
             'params' => $params,
1115 1115
             'custom' => true,
1116 1116
             'class'  => $class,
1117 1117
             'buffer' => null
1118 1118
         );
1119
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1119
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1120 1120
 
1121 1121
         return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1122 1122
     }
@@ -1131,21 +1131,21 @@  discard block
 block discarded – undo
1131 1131
     public function injectBlock($type, array $params)
1132 1132
     {
1133 1133
         if ($this->debug) {
1134
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1134
+            echo 'Compiler::'.__FUNCTION__."\n";
1135 1135
         }
1136 1136
 
1137
-        $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($type);
1137
+        $class = Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($type);
1138 1138
         if (class_exists($class) === false) {
1139 1139
             $this->getDwoo()->getLoader()->loadPlugin($type);
1140 1140
         }
1141
-        $this->stack[]  = array(
1141
+        $this->stack[] = array(
1142 1142
             'type'   => $type,
1143 1143
             'params' => $params,
1144 1144
             'custom' => false,
1145 1145
             'class'  => $class,
1146 1146
             'buffer' => null
1147 1147
         );
1148
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1148
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1149 1149
     }
1150 1150
 
1151 1151
     /**
@@ -1160,7 +1160,7 @@  discard block
 block discarded – undo
1160 1160
     public function removeBlock($type)
1161 1161
     {
1162 1162
         if ($this->debug) {
1163
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1163
+            echo 'Compiler::'.__FUNCTION__."\n";
1164 1164
         }
1165 1165
 
1166 1166
         $output = '';
@@ -1174,10 +1174,10 @@  discard block
 block discarded – undo
1174 1174
                 if ($top['custom']) {
1175 1175
                     $class = $top['class'];
1176 1176
                 } else {
1177
-                    $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($top['type']);
1177
+                    $class = Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($top['type']);
1178 1178
                 }
1179 1179
                 if (count($this->stack)) {
1180
-                    $this->curBlock = &$this->stack[count($this->stack) - 1];
1180
+                    $this->curBlock = &$this->stack[count($this->stack)-1];
1181 1181
                     $this->push(call_user_func(array(
1182 1182
                         $class,
1183 1183
                         'postProcessing'
@@ -1198,7 +1198,7 @@  discard block
 block discarded – undo
1198 1198
                 }
1199 1199
             }
1200 1200
 
1201
-            throw new CompilationException($this, 'Syntax malformation, a block of type "' . $type . '" was closed but was not opened');
1201
+            throw new CompilationException($this, 'Syntax malformation, a block of type "'.$type.'" was closed but was not opened');
1202 1202
             break;
1203 1203
         }
1204 1204
 
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
             }
1238 1238
         }
1239 1239
 
1240
-        throw new CompilationException($this, 'A parent block of type "' . $type . '" is required and can not be found');
1240
+        throw new CompilationException($this, 'A parent block of type "'.$type.'" is required and can not be found');
1241 1241
     }
1242 1242
 
1243 1243
     /**
@@ -1260,7 +1260,7 @@  discard block
 block discarded – undo
1260 1260
     public function removeTopBlock()
1261 1261
     {
1262 1262
         if ($this->debug) {
1263
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1263
+            echo 'Compiler::'.__FUNCTION__."\n";
1264 1264
         }
1265 1265
 
1266 1266
         $o = array_pop($this->stack);
@@ -1270,10 +1270,10 @@  discard block
 block discarded – undo
1270 1270
         if ($o['custom']) {
1271 1271
             $class = $o['class'];
1272 1272
         } else {
1273
-            $class = Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($o['type']);
1273
+            $class = Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($o['type']);
1274 1274
         }
1275 1275
 
1276
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1276
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1277 1277
 
1278 1278
         return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1279 1279
     }
@@ -1352,7 +1352,7 @@  discard block
 block discarded – undo
1352 1352
     protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1353 1353
     {
1354 1354
         if ($this->debug) {
1355
-            echo 'Compiler::' . __FUNCTION__ . "\n";
1355
+            echo 'Compiler::'.__FUNCTION__."\n";
1356 1356
         }
1357 1357
 
1358 1358
         if ($to === null) {
@@ -1369,14 +1369,14 @@  discard block
 block discarded – undo
1369 1369
                 // end template tag
1370 1370
                 $pointer += strlen($this->rd);
1371 1371
                 if ($this->debug) {
1372
-                    echo 'TEMPLATE PARSING ENDED' . "\n";
1372
+                    echo 'TEMPLATE PARSING ENDED'."\n";
1373 1373
                 }
1374 1374
 
1375 1375
                 return false;
1376 1376
             }
1377
-            ++ $from;
1377
+            ++$from;
1378 1378
             if ($pointer !== null) {
1379
-                ++ $pointer;
1379
+                ++$pointer;
1380 1380
             }
1381 1381
             if ($from >= $to) {
1382 1382
                 if (is_array($parsingParams)) {
@@ -1388,22 +1388,22 @@  discard block
 block discarded – undo
1388 1388
             $first = $in[$from];
1389 1389
         }
1390 1390
 
1391
-        $substr = substr($in, $from, $to - $from);
1391
+        $substr = substr($in, $from, $to-$from);
1392 1392
 
1393 1393
         if ($this->debug) {
1394
-            echo 'PARSE CALL : PARSING "<b>' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . '</b>" @ ' . $from . ':' . $to . ' in ' . $curBlock . ' : pointer=' . $pointer . "\n";
1394
+            echo 'PARSE CALL : PARSING "<b>'.htmlentities(substr($in, $from, min($to-$from, 50))).(($to-$from) > 50 ? '...' : '').'</b>" @ '.$from.':'.$to.' in '.$curBlock.' : pointer='.$pointer."\n";
1395 1395
         }
1396 1396
         $parsed = '';
1397 1397
 
1398 1398
         if ($curBlock === 'root' && $first === '*') {
1399 1399
             $src      = $this->getTemplateSource();
1400
-            $startpos = $this->getPointer() - strlen($this->ld);
1400
+            $startpos = $this->getPointer()-strlen($this->ld);
1401 1401
             if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1402 1402
                 if ($startpos > 0) {
1403 1403
                     do {
1404 1404
                         $char = substr($src, -- $startpos, 1);
1405 1405
                         if ($char == "\n") {
1406
-                            ++ $startpos;
1406
+                            ++$startpos;
1407 1407
                             $whitespaceStart = true;
1408 1408
                             break;
1409 1409
                         }
@@ -1414,12 +1414,12 @@  discard block
 block discarded – undo
1414 1414
                 if (!isset($whitespaceStart)) {
1415 1415
                     $startpos = $this->getPointer();
1416 1416
                 } else {
1417
-                    $pointer -= $this->getPointer() - $startpos;
1417
+                    $pointer -= $this->getPointer()-$startpos;
1418 1418
                 }
1419 1419
 
1420
-                if ($this->allowNestedComments && strpos($src, $this->ld . '*', $this->getPointer()) !== false) {
1421
-                    $comOpen  = $this->ld . '*';
1422
-                    $comClose = '*' . $this->rd;
1420
+                if ($this->allowNestedComments && strpos($src, $this->ld.'*', $this->getPointer()) !== false) {
1421
+                    $comOpen  = $this->ld.'*';
1422
+                    $comClose = '*'.$this->rd;
1423 1423
                     $level    = 1;
1424 1424
                     $ptr      = $this->getPointer();
1425 1425
 
@@ -1429,33 +1429,33 @@  discard block
 block discarded – undo
1429 1429
 
1430 1430
                         if ($open !== false && $close !== false) {
1431 1431
                             if ($open < $close) {
1432
-                                $ptr = $open + strlen($comOpen);
1433
-                                ++ $level;
1432
+                                $ptr = $open+strlen($comOpen);
1433
+                                ++$level;
1434 1434
                             } else {
1435
-                                $ptr = $close + strlen($comClose);
1436
-                                -- $level;
1435
+                                $ptr = $close+strlen($comClose);
1436
+                                --$level;
1437 1437
                             }
1438 1438
                         } elseif ($open !== false) {
1439
-                            $ptr = $open + strlen($comOpen);
1440
-                            ++ $level;
1439
+                            $ptr = $open+strlen($comOpen);
1440
+                            ++$level;
1441 1441
                         } elseif ($close !== false) {
1442
-                            $ptr = $close + strlen($comClose);
1443
-                            -- $level;
1442
+                            $ptr = $close+strlen($comClose);
1443
+                            --$level;
1444 1444
                         } else {
1445 1445
                             $ptr = strlen($src);
1446 1446
                         }
1447 1447
                     }
1448
-                    $endpos = $ptr - strlen('*' . $this->rd);
1448
+                    $endpos = $ptr-strlen('*'.$this->rd);
1449 1449
                 } else {
1450
-                    $endpos = strpos($src, '*' . $this->rd, $startpos);
1450
+                    $endpos = strpos($src, '*'.$this->rd, $startpos);
1451 1451
                     if ($endpos == false) {
1452 1452
                         throw new CompilationException($this, 'Un-ended comment');
1453 1453
                     }
1454 1454
                 }
1455
-                $pointer += $endpos - $startpos + strlen('*' . $this->rd);
1456
-                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*' . $this->rd)), $m)) {
1455
+                $pointer += $endpos-$startpos+strlen('*'.$this->rd);
1456
+                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos+strlen('*'.$this->rd)), $m)) {
1457 1457
                     $pointer += strlen($m[0]);
1458
-                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1458
+                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer'])-($this->getPointer()-$startpos-strlen($this->ld)));
1459 1459
                 }
1460 1460
 
1461 1461
                 return false;
@@ -1472,20 +1472,20 @@  discard block
 block discarded – undo
1472 1472
         } elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1473 1473
             // string
1474 1474
             $out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1475
-        } elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?(' . (is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|') . '\s*\(|\s*' . $this->rdr . '|\s*;)/i', $substr)) {
1475
+        } elseif (preg_match('/^\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?('.(is_array($parsingParams) || $curBlock != 'root' ? '' : '\s+[^(]|').'\s*\(|\s*'.$this->rdr.'|\s*;)/i', $substr)) {
1476 1476
             // func
1477 1477
             $out    = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1478 1478
             $parsed = 'func';
1479 1479
         } elseif ($first === ';') {
1480 1480
             // instruction end
1481 1481
             if ($this->debug) {
1482
-                echo 'END OF INSTRUCTION' . "\n";
1482
+                echo 'END OF INSTRUCTION'."\n";
1483 1483
             }
1484 1484
             if ($pointer !== null) {
1485
-                ++ $pointer;
1485
+                ++$pointer;
1486 1486
             }
1487 1487
 
1488
-            return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1488
+            return $this->parse($in, $from+1, $to, false, 'root', $pointer);
1489 1489
         } elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1490 1490
             // close block
1491 1491
             if (!empty($match[1]) && $match[1] == 'else') {
@@ -1502,13 +1502,13 @@  discard block
 block discarded – undo
1502 1502
                     $pointer -= strlen($match[0]);
1503 1503
                 }
1504 1504
                 if ($this->debug) {
1505
-                    echo 'TOP BLOCK CLOSED' . "\n";
1505
+                    echo 'TOP BLOCK CLOSED'."\n";
1506 1506
                 }
1507 1507
 
1508 1508
                 return $this->removeTopBlock();
1509 1509
             } else {
1510 1510
                 if ($this->debug) {
1511
-                    echo 'BLOCK OF TYPE ' . $match[1] . ' CLOSED' . "\n";
1511
+                    echo 'BLOCK OF TYPE '.$match[1].' CLOSED'."\n";
1512 1512
                 }
1513 1513
 
1514 1514
                 return $this->removeBlock($match[1]);
@@ -1516,19 +1516,19 @@  discard block
 block discarded – undo
1516 1516
         } elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1517 1517
             // end template tag
1518 1518
             if ($this->debug) {
1519
-                echo 'TAG PARSING ENDED' . "\n";
1519
+                echo 'TAG PARSING ENDED'."\n";
1520 1520
             }
1521 1521
             $pointer += strlen($this->rd);
1522 1522
 
1523 1523
             return false;
1524
-        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*=' . ($curBlock === 'array' ? '>?' : '') . ')(?:\s+|[^=]).*#i', $substr, $match)) {
1524
+        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*='.($curBlock === 'array' ? '>?' : '').')(?:\s+|[^=]).*#i', $substr, $match)) {
1525 1525
             // named parameter
1526 1526
             if ($this->debug) {
1527
-                echo 'NAMED PARAM FOUND' . "\n";
1527
+                echo 'NAMED PARAM FOUND'."\n";
1528 1528
             }
1529 1529
             $len = strlen($match[1]);
1530
-            while (substr($in, $from + $len, 1) === ' ') {
1531
-                ++ $len;
1530
+            while (substr($in, $from+$len, 1) === ' ') {
1531
+                ++$len;
1532 1532
             }
1533 1533
             if ($pointer !== null) {
1534 1534
                 $pointer += $len;
@@ -1536,7 +1536,7 @@  discard block
 block discarded – undo
1536 1536
 
1537 1537
             $output = array(
1538 1538
                 trim($match[1], " \t\r\n=>'\""),
1539
-                $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer)
1539
+                $this->parse($in, $from+$len, $to, false, 'namedparam', $pointer)
1540 1540
             );
1541 1541
 
1542 1542
             $parsingParams[] = $output;
@@ -1557,31 +1557,31 @@  discard block
 block discarded – undo
1557 1557
             $out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1558 1558
         } else {
1559 1559
             // parse error
1560
-            throw new CompilationException($this, 'Parse error in "' . substr($in, $from, $to - $from) . '"');
1560
+            throw new CompilationException($this, 'Parse error in "'.substr($in, $from, $to-$from).'"');
1561 1561
         }
1562 1562
 
1563 1563
         if (empty($out)) {
1564 1564
             return '';
1565 1565
         }
1566 1566
 
1567
-        $substr = substr($in, $pointer, $to - $pointer);
1567
+        $substr = substr($in, $pointer, $to-$pointer);
1568 1568
 
1569 1569
         // var parsed, check if any var-extension applies
1570 1570
         if ($parsed === 'var') {
1571 1571
             if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1572 1572
                 if ($this->debug) {
1573
-                    echo 'PARSING POST-VAR EXPRESSION ' . $substr . "\n";
1573
+                    echo 'PARSING POST-VAR EXPRESSION '.$substr."\n";
1574 1574
                 }
1575 1575
                 // parse expressions
1576
-                $pointer += strlen($match[0]) - 1;
1576
+                $pointer += strlen($match[0])-1;
1577 1577
                 if (is_array($parsingParams)) {
1578 1578
                     if ($match[2] == '$') {
1579 1579
                         $expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1580 1580
                     } else {
1581 1581
                         $expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1582 1582
                     }
1583
-                    $out[count($out) - 1][0] .= $match[1] . $expr[0][0];
1584
-                    $out[count($out) - 1][1] .= $match[1] . $expr[0][1];
1583
+                    $out[count($out)-1][0] .= $match[1].$expr[0][0];
1584
+                    $out[count($out)-1][1] .= $match[1].$expr[0][1];
1585 1585
                 } else {
1586 1586
                     if ($match[2] == '$') {
1587 1587
                         $expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
@@ -1589,26 +1589,26 @@  discard block
 block discarded – undo
1589 1589
                         $expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1590 1590
                     }
1591 1591
                     if (is_array($out) && is_array($expr)) {
1592
-                        $out[0] .= $match[1] . $expr[0];
1593
-                        $out[1] .= $match[1] . $expr[1];
1592
+                        $out[0] .= $match[1].$expr[0];
1593
+                        $out[1] .= $match[1].$expr[1];
1594 1594
                     } elseif (is_array($out)) {
1595
-                        $out[0] .= $match[1] . $expr;
1596
-                        $out[1] .= $match[1] . $expr;
1595
+                        $out[0] .= $match[1].$expr;
1596
+                        $out[1] .= $match[1].$expr;
1597 1597
                     } elseif (is_array($expr)) {
1598
-                        $out .= $match[1] . $expr[0];
1598
+                        $out .= $match[1].$expr[0];
1599 1599
                     } else {
1600
-                        $out .= $match[1] . $expr;
1600
+                        $out .= $match[1].$expr;
1601 1601
                     }
1602 1602
                 }
1603 1603
             } elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1604 1604
                 if ($this->debug) {
1605
-                    echo 'PARSING POST-VAR ASSIGNMENT ' . $substr . "\n";
1605
+                    echo 'PARSING POST-VAR ASSIGNMENT '.$substr."\n";
1606 1606
                 }
1607 1607
                 // parse assignment
1608 1608
                 $value    = $match[2];
1609 1609
                 $operator = trim($match[1]);
1610 1610
                 if (substr($value, 0, 1) == '=') {
1611
-                    throw new CompilationException($this, 'Unexpected "=" in <em>' . $substr . '</em>');
1611
+                    throw new CompilationException($this, 'Unexpected "=" in <em>'.$substr.'</em>');
1612 1612
                 }
1613 1613
 
1614 1614
                 if ($pointer !== null) {
@@ -1629,7 +1629,7 @@  discard block
 block discarded – undo
1629 1629
                         throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1630 1630
                     }
1631 1631
 
1632
-                    $parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS . 'PluginIf', 'init'), 1);
1632
+                    $parts  = $this->mapParams($parts, array(Core::NAMESPACE_PLUGINS_BLOCKS.'PluginIf', 'init'), 1);
1633 1633
                     $tokens = $this->getParamTokens($parts);
1634 1634
                     $parts  = $this->getCompiledParams($parts);
1635 1635
 
@@ -1643,14 +1643,14 @@  discard block
 block discarded – undo
1643 1643
                 if ($this->autoEscape) {
1644 1644
                     $out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1645 1645
                 }
1646
-                $out = self::PHP_OPEN . $echo . $out . $operator . implode(' ', $value) . self::PHP_CLOSE;
1646
+                $out = self::PHP_OPEN.$echo.$out.$operator.implode(' ', $value).self::PHP_CLOSE;
1647 1647
             } elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1648 1648
                 // parse namedparam with var as name (only for array)
1649 1649
                 if ($this->debug) {
1650
-                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND' . "\n";
1650
+                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND'."\n";
1651 1651
                 }
1652 1652
                 $len = strlen($match[1]);
1653
-                $var = $out[count($out) - 1];
1653
+                $var = $out[count($out)-1];
1654 1654
                 $pointer += $len;
1655 1655
 
1656 1656
                 $output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
@@ -1665,16 +1665,16 @@  discard block
 block discarded – undo
1665 1665
             // parse modifier on funcs or vars
1666 1666
             $srcPointer = $pointer;
1667 1667
             if (is_array($parsingParams)) {
1668
-                $tmp                     = $this->replaceModifiers(
1668
+                $tmp = $this->replaceModifiers(
1669 1669
                     array(
1670 1670
                     null,
1671 1671
                     null,
1672
-                    $out[count($out) - 1][0],
1672
+                    $out[count($out)-1][0],
1673 1673
                     $match[0]
1674 1674
                     ), $curBlock, $pointer
1675 1675
                 );
1676
-                $out[count($out) - 1][0] = $tmp;
1677
-                $out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1676
+                $out[count($out)-1][0] = $tmp;
1677
+                $out[count($out)-1][1] .= substr($substr, $srcPointer, $srcPointer-$pointer);
1678 1678
             } else {
1679 1679
                 $out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1680 1680
             }
@@ -1686,10 +1686,10 @@  discard block
 block discarded – undo
1686 1686
             $ptr = 0;
1687 1687
 
1688 1688
             if (is_array($parsingParams)) {
1689
-                $output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1689
+                $output = $this->parseMethodCall($out[count($out)-1][1], $match[0], $curBlock, $ptr);
1690 1690
 
1691
-                $out[count($out) - 1][0] = $output;
1692
-                $out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1691
+                $out[count($out)-1][0] = $output;
1692
+                $out[count($out)-1][1] .= substr($match[0], 0, $ptr);
1693 1693
             } else {
1694 1694
                 $out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1695 1695
             }
@@ -1698,7 +1698,7 @@  discard block
 block discarded – undo
1698 1698
         }
1699 1699
 
1700 1700
         if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1701
-            return self::PHP_OPEN . 'echo ' . $out . ';' . self::PHP_CLOSE;
1701
+            return self::PHP_OPEN.'echo '.$out.';'.self::PHP_CLOSE;
1702 1702
         } else {
1703 1703
             return $out;
1704 1704
         }
@@ -1724,11 +1724,11 @@  discard block
 block discarded – undo
1724 1724
     protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1725 1725
     {
1726 1726
         $output = '';
1727
-        $cmdstr = substr($in, $from, $to - $from);
1728
-        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*' . $this->rdr . '|\s*;)?/i', $cmdstr, $match);
1727
+        $cmdstr = substr($in, $from, $to-$from);
1728
+        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*'.$this->rdr.'|\s*;)?/i', $cmdstr, $match);
1729 1729
 
1730 1730
         if (empty($match[1])) {
1731
-            throw new CompilationException($this, 'Parse error, invalid function name : ' . substr($cmdstr, 0, 15));
1731
+            throw new CompilationException($this, 'Parse error, invalid function name : '.substr($cmdstr, 0, 15));
1732 1732
         }
1733 1733
 
1734 1734
         $func = $match[1];
@@ -1738,7 +1738,7 @@  discard block
 block discarded – undo
1738 1738
         }
1739 1739
 
1740 1740
         if ($this->debug) {
1741
-            echo 'FUNC FOUND (' . $func . ')' . "\n";
1741
+            echo 'FUNC FOUND ('.$func.')'."\n";
1742 1742
         }
1743 1743
 
1744 1744
         $paramsep = '';
@@ -1750,11 +1750,11 @@  discard block
 block discarded – undo
1750 1750
             $paramspos = $match[1][0][1];
1751 1751
             $paramsep  = substr($match[1][0][0], - 1) === '(' ? ')' : '';
1752 1752
             if ($paramsep === ')') {
1753
-                $paramspos += strlen($match[1][0][0]) - 1;
1753
+                $paramspos += strlen($match[1][0][0])-1;
1754 1754
                 if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1755 1755
                     $paramsep = '';
1756 1756
                     if (strlen($match[1][0][0]) > 1) {
1757
-                        -- $paramspos;
1757
+                        --$paramspos;
1758 1758
                     }
1759 1759
                 }
1760 1760
             }
@@ -1779,8 +1779,8 @@  discard block
 block discarded – undo
1779 1779
                     return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1780 1780
                 }
1781 1781
             }
1782
-            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1783
-            $paramstr   = substr($cmdstr, $paramspos + 1);
1782
+            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos-strlen($func)));
1783
+            $paramstr   = substr($cmdstr, $paramspos+1);
1784 1784
             if (substr($paramstr, - 1, 1) === $paramsep) {
1785 1785
                 $paramstr = substr($paramstr, 0, - 1);
1786 1786
             }
@@ -1802,36 +1802,36 @@  discard block
 block discarded – undo
1802 1802
 
1803 1803
                             if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1804 1804
                                 if ($this->debug) {
1805
-                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT ' . $ptr . "\n";
1805
+                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT '.$ptr."\n";
1806 1806
                                 }
1807 1807
                                 break 2;
1808 1808
                             } elseif ($paramstr[$ptr] === ';') {
1809
-                                ++ $ptr;
1809
+                                ++$ptr;
1810 1810
                                 if ($this->debug) {
1811
-                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT ' . $ptr . "\n";
1811
+                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT '.$ptr."\n";
1812 1812
                                 }
1813 1813
                                 break 2;
1814 1814
                             } elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1815 1815
                                 if ($this->debug) {
1816
-                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT ' . $ptr . "\n";
1816
+                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT '.$ptr."\n";
1817 1817
                                 }
1818 1818
                                 break 2;
1819 1819
                             } elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1820 1820
                                 if ($this->debug) {
1821
-                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT ' . $ptr . "\n";
1821
+                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT '.$ptr."\n";
1822 1822
                                 }
1823 1823
                                 break 2;
1824 1824
                             }
1825 1825
 
1826 1826
                             if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1827
-                                ++ $ptr;
1827
+                                ++$ptr;
1828 1828
                             } else {
1829 1829
                                 break;
1830 1830
                             }
1831 1831
                         }
1832 1832
 
1833 1833
                         if ($this->debug) {
1834
-                            echo 'FUNC START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
1834
+                            echo 'FUNC START PARAM PARSING WITH POINTER AT '.$ptr."\n";
1835 1835
                         }
1836 1836
 
1837 1837
                         if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
@@ -1843,7 +1843,7 @@  discard block
 block discarded – undo
1843 1843
                         }
1844 1844
 
1845 1845
                         if ($this->debug) {
1846
-                            echo 'PARAM PARSED, POINTER AT ' . $ptr . ' (' . substr($paramstr, $ptr - 1, 3) . ')' . "\n";
1846
+                            echo 'PARAM PARSED, POINTER AT '.$ptr.' ('.substr($paramstr, $ptr-1, 3).')'."\n";
1847 1847
                         }
1848 1848
                     }
1849 1849
                 }
@@ -1867,16 +1867,16 @@  discard block
 block discarded – undo
1867 1867
         }
1868 1868
 
1869 1869
         if ($pointer !== null) {
1870
-            $pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1870
+            $pointer += (isset($paramstr) ? strlen($paramstr) : 0)+(')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1))+strlen($func)+(isset($whitespace) ? $whitespace : 0);
1871 1871
             if ($this->debug) {
1872
-                echo 'FUNC ADDS ' . ((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)) . ' TO POINTER' . "\n";
1872
+                echo 'FUNC ADDS '.((isset($paramstr) ? strlen($paramstr) : 0)+(')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1))+strlen($func)).' TO POINTER'."\n";
1873 1873
             }
1874 1874
         }
1875 1875
 
1876 1876
         if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1877 1877
             // handle static method calls with security policy
1878 1878
             if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1879
-                throw new SecurityException('Call to a disallowed php function : ' . $func);
1879
+                throw new SecurityException('Call to a disallowed php function : '.$func);
1880 1880
             }
1881 1881
             $pluginType = Core::NATIVE_PLUGIN;
1882 1882
         } else {
@@ -1920,14 +1920,14 @@  discard block
 block discarded – undo
1920 1920
                     $this->customPlugins[$func]['function']
1921 1921
                 ), $state);
1922 1922
             } else {
1923
-                if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
1923
+                if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
1924 1924
                     $params = $this->mapParams($params, array(
1925
-                        'Plugin' . Core::toCamelCase($func),
1925
+                        'Plugin'.Core::toCamelCase($func),
1926 1926
                         ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1927 1927
                     ), $state);
1928 1928
                 } else {
1929 1929
                     $params = $this->mapParams($params, array(
1930
-                        Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
1930
+                        Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func),
1931 1931
                         ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'
1932 1932
                     ), $state);
1933 1933
                 }
@@ -1937,23 +1937,21 @@  discard block
 block discarded – undo
1937 1937
                 $params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1938 1938
             } else {
1939 1939
                 // Custom plugin
1940
-                if (function_exists('Plugin' . Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ?
1940
+                if (function_exists('Plugin'.Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ?
1941 1941
                         'Compile' : '')) !== false) {
1942
-                    $params = $this->mapParams($params, 'Plugin' . Core::toCamelCase($func) . (($pluginType &
1942
+                    $params = $this->mapParams($params, 'Plugin'.Core::toCamelCase($func).(($pluginType &
1943 1943
                             Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1944 1944
                 } // Builtin helper plugin
1945
-                elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . (
1945
+                elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).(
1946 1946
                     ($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '')) !== false) {
1947
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase
1948
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1947
+                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1949 1948
                 } // Builtin function plugin
1950 1949
                 else {
1951
-                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
1952
-                        ($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1950
+                    $params = $this->mapParams($params, Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''), $state);
1953 1951
                 }
1954 1952
             }
1955 1953
         } elseif ($pluginType & Core::SMARTY_MODIFIER) {
1956
-            $output = 'smarty_modifier_' . $func . '(' . implode(', ', $params) . ')';
1954
+            $output = 'smarty_modifier_'.$func.'('.implode(', ', $params).')';
1957 1955
         } elseif ($pluginType & Core::PROXY_PLUGIN) {
1958 1956
             $params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
1959 1957
         } elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
@@ -1988,7 +1986,7 @@  discard block
 block discarded – undo
1988 1986
         if ($pluginType & Core::NATIVE_PLUGIN) {
1989 1987
             if ($func === 'do') {
1990 1988
                 if (isset($params['*'])) {
1991
-                    $output = implode(';', $params['*']) . ';';
1989
+                    $output = implode(';', $params['*']).';';
1992 1990
                 } else {
1993 1991
                     $output = '';
1994 1992
                 }
@@ -1996,13 +1994,13 @@  discard block
 block discarded – undo
1996 1994
                 if (is_array($parsingParams) || $curBlock !== 'root') {
1997 1995
                     throw new CompilationException($this, 'Do can not be used inside another function or block');
1998 1996
                 } else {
1999
-                    return self::PHP_OPEN . $output . self::PHP_CLOSE;
1997
+                    return self::PHP_OPEN.$output.self::PHP_CLOSE;
2000 1998
                 }
2001 1999
             } else {
2002 2000
                 if (isset($params['*'])) {
2003
-                    $output = $func . '(' . implode(', ', $params['*']) . ')';
2001
+                    $output = $func.'('.implode(', ', $params['*']).')';
2004 2002
                 } else {
2005
-                    $output = $func . '()';
2003
+                    $output = $func.'()';
2006 2004
                 }
2007 2005
             }
2008 2006
         } elseif ($pluginType & Core::FUNC_PLUGIN) {
@@ -2011,16 +2009,16 @@  discard block
 block discarded – undo
2011 2009
                     $funcCompiler = $this->customPlugins[$func]['callback'];
2012 2010
                 } else {
2013 2011
                     // Custom plugin
2014
-                    if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
2015
-                        $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
2012
+                    if (function_exists('Plugin'.Core::toCamelCase($func).'Compile') !== false) {
2013
+                        $funcCompiler = 'Plugin'.Core::toCamelCase($func).'Compile';
2016 2014
                     } // Builtin helper plugin
2017
-                    elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2015
+                    elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).
2018 2016
                             'Compile') !== false) {
2019
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) .
2017
+                        $funcCompiler = Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).
2020 2018
                             'Compile';
2021 2019
                     } // Builtin function plugin
2022 2020
                     else {
2023
-                        $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
2021
+                        $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).
2024 2022
                             'Compile';
2025 2023
                     }
2026 2024
                 }
@@ -2035,24 +2033,24 @@  discard block
 block discarded – undo
2035 2033
                 if ($pluginType & Core::CUSTOM_PLUGIN) {
2036 2034
                     $callback = $this->customPlugins[$func]['callback'];
2037 2035
                     if ($callback instanceof Closure) {
2038
-                        $output = 'call_user_func($this->getCustomPlugin(\'' . $func . '\'), ' . $params . ')';
2036
+                        $output = 'call_user_func($this->getCustomPlugin(\''.$func.'\'), '.$params.')';
2039 2037
                     } else {
2040
-                        $output = 'call_user_func(\'' . $callback . '\', ' . $params . ')';
2038
+                        $output = 'call_user_func(\''.$callback.'\', '.$params.')';
2041 2039
                     }
2042 2040
                 } else {
2043 2041
                     // Custom plugin
2044
-                    if (function_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2045
-                        $output = 'Plugin' . Core::toCamelCase($func) . '(' . $params .
2042
+                    if (function_exists('Plugin'.Core::toCamelCase($func)) !== false) {
2043
+                        $output = 'Plugin'.Core::toCamelCase($func).'('.$params.
2046 2044
                             ')';
2047 2045
                     } // Builtin helper plugin
2048
-                    elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func)) !==
2046
+                    elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func)) !==
2049 2047
                         false) {
2050
-                        $output = Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($func) . '(' .
2051
-                            $params . ')';
2048
+                        $output = Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($func).'('.
2049
+                            $params.')';
2052 2050
                     } // Builtin function plugin
2053 2051
                     else {
2054
-                        $output = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '(' .
2055
-                            $params . ')';
2052
+                        $output = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).'('.
2053
+                            $params.')';
2056 2054
                     }
2057 2055
                 }
2058 2056
             }
@@ -2062,7 +2060,7 @@  discard block
 block discarded – undo
2062 2060
                     $callback = $this->customPlugins[$func]['callback'];
2063 2061
                     if (!is_array($callback)) {
2064 2062
                         if (!method_exists($callback, 'compile')) {
2065
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2063
+                            throw new Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
2066 2064
                         }
2067 2065
                         if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
2068 2066
                             $funcCompiler = array($callback, 'compile');
@@ -2073,11 +2071,11 @@  discard block
 block discarded – undo
2073 2071
                         $funcCompiler = $callback;
2074 2072
                     }
2075 2073
                 } else {
2076
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2077
-                        $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
2074
+                    if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
2075
+                        $funcCompiler = array('Plugin'.Core::toCamelCase($func), 'compile');
2078 2076
                     } else {
2079 2077
                         $funcCompiler = array(
2080
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
2078
+                            Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func),
2081 2079
                             'compile'
2082 2080
                         );
2083 2081
                     }
@@ -2090,32 +2088,32 @@  discard block
 block discarded – undo
2090 2088
                     $callback = $this->customPlugins[$func]['callback'];
2091 2089
                     if (!is_array($callback)) {
2092 2090
                         if (!method_exists($callback, 'process')) {
2093
-                            throw new Exception('Custom plugin ' . $func . ' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2091
+                            throw new Exception('Custom plugin '.$func.' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
2094 2092
                         }
2095 2093
                         if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
2096
-                            $output = 'call_user_func(array(\'' . $callback . '\', \'process\'), ' . $params . ')';
2094
+                            $output = 'call_user_func(array(\''.$callback.'\', \'process\'), '.$params.')';
2097 2095
                         } else {
2098
-                            $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback . '\'), \'process\'), ' . $params . ')';
2096
+                            $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback.'\'), \'process\'), '.$params.')';
2099 2097
                         }
2100 2098
                     } elseif (is_object($callback[0])) {
2101
-                        $output = 'call_user_func(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), ' . $params . ')';
2099
+                        $output = 'call_user_func(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), '.$params.')';
2102 2100
                     } elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
2103
-                        $output = 'call_user_func(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), ' . $params . ')';
2101
+                        $output = 'call_user_func(array(\''.$callback[0].'\', \''.$callback[1].'\'), '.$params.')';
2104 2102
                     } else {
2105
-                        $output = 'call_user_func(array($this->getObjectPlugin(\'' . $callback[0] . '\'), \'' . $callback[1] . '\'), ' . $params . ')';
2103
+                        $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback[0].'\'), \''.$callback[1].'\'), '.$params.')';
2106 2104
                     }
2107 2105
                     if (empty($params)) {
2108
-                        $output = substr($output, 0, - 3) . ')';
2106
+                        $output = substr($output, 0, - 3).')';
2109 2107
                     }
2110 2108
                 } else {
2111
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
2112
-                        $output = '$this->classCall(\'Plugin' . $func . '\', array(' . $params . '))';
2113
-                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func)) !==
2109
+                    if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
2110
+                        $output = '$this->classCall(\'Plugin'.$func.'\', array('.$params.'))';
2111
+                    } elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func)) !==
2114 2112
                     false) {
2115
-                        $output = '$this->classCall(\'' . Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . $func . '\', 
2116
-                        array(' . $params . '))';
2117
-                    } else{
2118
-                        $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
2113
+                        $output = '$this->classCall(\''.Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.$func.'\', 
2114
+                        array(' . $params.'))';
2115
+                    } else {
2116
+                        $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
2119 2117
                     }
2120 2118
                 }
2121 2119
             }
@@ -2132,21 +2130,21 @@  discard block
 block discarded – undo
2132 2130
                 $callback = $this->customPlugins[$func]['callback'];
2133 2131
                 if (is_array($callback)) {
2134 2132
                     if (is_object($callback[0])) {
2135
-                        $output = 'call_user_func_array(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2133
+                        $output = 'call_user_func_array(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array(array('.$params.'), $this))';
2136 2134
                     } else {
2137
-                        $output = 'call_user_func_array(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(array(' . $params . '), $this))';
2135
+                        $output = 'call_user_func_array(array(\''.$callback[0].'\', \''.$callback[1].'\'), array(array('.$params.'), $this))';
2138 2136
                     }
2139 2137
                 } else {
2140
-                    $output = $callback . '(array(' . $params . '), $this)';
2138
+                    $output = $callback.'(array('.$params.'), $this)';
2141 2139
                 }
2142 2140
             } else {
2143
-                $output = 'smarty_function_' . $func . '(array(' . $params . '), $this)';
2141
+                $output = 'smarty_function_'.$func.'(array('.$params.'), $this)';
2144 2142
             }
2145 2143
         } elseif ($pluginType & Core::TEMPLATE_PLUGIN) {
2146 2144
             array_unshift($params, '$this');
2147 2145
             $params                                 = self::implode_r($params);
2148
-            $output                                 = 'Plugin' . Core::toCamelCase($func) .
2149
-                $this->templatePlugins[$func]['uuid'] . '(' . $params . ')';
2146
+            $output                                 = 'Plugin'.Core::toCamelCase($func).
2147
+                $this->templatePlugins[$func]['uuid'].'('.$params.')';
2150 2148
             $this->templatePlugins[$func]['called'] = true;
2151 2149
         }
2152 2150
 
@@ -2178,29 +2176,29 @@  discard block
 block discarded – undo
2178 2176
      */
2179 2177
     protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2180 2178
     {
2181
-        $substr = substr($in, $from, $to - $from);
2179
+        $substr = substr($in, $from, $to-$from);
2182 2180
         $first  = $substr[0];
2183 2181
 
2184 2182
         if ($this->debug) {
2185
-            echo 'STRING FOUND (in ' . htmlentities(substr($in, $from, min($to - $from, 50))) . (($to - $from) > 50 ? '...' : '') . ')' . "\n";
2183
+            echo 'STRING FOUND (in '.htmlentities(substr($in, $from, min($to-$from, 50))).(($to-$from) > 50 ? '...' : '').')'."\n";
2186 2184
         }
2187 2185
         $strend = false;
2188
-        $o      = $from + 1;
2186
+        $o      = $from+1;
2189 2187
         while ($strend === false) {
2190 2188
             $strend = strpos($in, $first, $o);
2191 2189
             if ($strend === false) {
2192
-                throw new CompilationException($this, 'Unfinished string, started with ' . substr($in, $from, $to - $from));
2190
+                throw new CompilationException($this, 'Unfinished string, started with '.substr($in, $from, $to-$from));
2193 2191
             }
2194
-            if (substr($in, $strend - 1, 1) === '\\') {
2195
-                $o      = $strend + 1;
2192
+            if (substr($in, $strend-1, 1) === '\\') {
2193
+                $o      = $strend+1;
2196 2194
                 $strend = false;
2197 2195
             }
2198 2196
         }
2199 2197
         if ($this->debug) {
2200
-            echo 'STRING DELIMITED: ' . substr($in, $from, $strend + 1 - $from) . "\n";
2198
+            echo 'STRING DELIMITED: '.substr($in, $from, $strend+1-$from)."\n";
2201 2199
         }
2202 2200
 
2203
-        $srcOutput = substr($in, $from, $strend + 1 - $from);
2201
+        $srcOutput = substr($in, $from, $strend+1-$from);
2204 2202
 
2205 2203
         if ($pointer !== null) {
2206 2204
             $pointer += strlen($srcOutput);
@@ -2209,13 +2207,13 @@  discard block
 block discarded – undo
2209 2207
         $output = $this->replaceStringVars($srcOutput, $first);
2210 2208
 
2211 2209
         // handle modifiers
2212
-        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2210
+        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend+1-$from), $match)) {
2213 2211
             $modstr = $match[1];
2214 2212
 
2215 2213
             if ($curBlock === 'root' && substr($modstr, - 1) === '}') {
2216 2214
                 $modstr = substr($modstr, 0, - 1);
2217 2215
             }
2218
-            $modstr = str_replace('\\' . $first, $first, $modstr);
2216
+            $modstr = str_replace('\\'.$first, $first, $modstr);
2219 2217
             $ptr    = 0;
2220 2218
             $output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2221 2219
 
@@ -2223,7 +2221,7 @@  discard block
 block discarded – undo
2223 2221
             if ($pointer !== null) {
2224 2222
                 $pointer += $ptr;
2225 2223
             }
2226
-            $srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2224
+            $srcOutput .= substr($substr, $strend+1-$from, $ptr);
2227 2225
         }
2228 2226
 
2229 2227
         if (is_array($parsingParams)) {
@@ -2254,10 +2252,10 @@  discard block
 block discarded – undo
2254 2252
      */
2255 2253
     protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2256 2254
     {
2257
-        $substr = substr($in, $from, $to - $from);
2255
+        $substr = substr($in, $from, $to-$from);
2258 2256
 
2259 2257
         if ($this->debug) {
2260
-            echo 'CONST FOUND : ' . $substr . "\n";
2258
+            echo 'CONST FOUND : '.$substr."\n";
2261 2259
         }
2262 2260
 
2263 2261
         if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
@@ -2296,7 +2294,7 @@  discard block
 block discarded – undo
2296 2294
         }
2297 2295
 
2298 2296
         if ($curBlock !== 'root') {
2299
-            $output = '(defined("' . $key . '") ? ' . $key . ' : null)';
2297
+            $output = '(defined("'.$key.'") ? '.$key.' : null)';
2300 2298
         } else {
2301 2299
             $output = $key;
2302 2300
         }
@@ -2322,13 +2320,13 @@  discard block
 block discarded – undo
2322 2320
     protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2323 2321
     {
2324 2322
         $methodCall = '';
2325
-        $substr     = substr($in, $from, $to - $from);
2323
+        $substr     = substr($in, $from, $to-$from);
2326 2324
 
2327 2325
         if (preg_match(
2328
-            '#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)' . // var key
2329
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()') . // method call
2330
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()') . // simple math expressions
2331
-            ($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())') . // modifiers
2326
+            '#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)'.// var key
2327
+            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()').// method call
2328
+            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()').// simple math expressions
2329
+            ($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())').// modifiers
2332 2330
             '#i', $substr, $match
2333 2331
         )) {
2334 2332
             $key = substr($match[1], 1);
@@ -2340,13 +2338,13 @@  discard block
 block discarded – undo
2340 2338
 
2341 2339
             if (substr($key, - 1) == '.') {
2342 2340
                 $key = substr($key, 0, - 1);
2343
-                -- $matchedLength;
2341
+                --$matchedLength;
2344 2342
             }
2345 2343
 
2346 2344
             if ($hasMethodCall) {
2347
-                $matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2348
-                $key        = substr($match[1], 1, strrpos($match[1], '->') - 1);
2349
-                $methodCall = substr($match[1], strrpos($match[1], '->')) . $match[3];
2345
+                $matchedLength -= strlen($match[3])+strlen(substr($match[1], strrpos($match[1], '->')));
2346
+                $key        = substr($match[1], 1, strrpos($match[1], '->')-1);
2347
+                $methodCall = substr($match[1], strrpos($match[1], '->')).$match[3];
2350 2348
             }
2351 2349
 
2352 2350
             if ($hasModifiers) {
@@ -2362,9 +2360,9 @@  discard block
 block discarded – undo
2362 2360
 
2363 2361
             if ($this->debug) {
2364 2362
                 if ($hasMethodCall) {
2365
-                    echo 'METHOD CALL FOUND : $' . $key . substr($methodCall, 0, 30) . "\n";
2363
+                    echo 'METHOD CALL FOUND : $'.$key.substr($methodCall, 0, 30)."\n";
2366 2364
                 } else {
2367
-                    echo 'VAR FOUND : $' . $key . "\n";
2365
+                    echo 'VAR FOUND : $'.$key."\n";
2368 2366
                 }
2369 2367
             }
2370 2368
 
@@ -2375,7 +2373,7 @@  discard block
 block discarded – undo
2375 2373
                 $uid           = 0;
2376 2374
                 $parsed        = array($uid => '');
2377 2375
                 $current       = &$parsed;
2378
-                $curTxt        = &$parsed[$uid ++];
2376
+                $curTxt        = &$parsed[$uid++];
2379 2377
                 $tree          = array();
2380 2378
                 $chars         = str_split($key, 1);
2381 2379
                 $inSplittedVar = false;
@@ -2384,33 +2382,33 @@  discard block
 block discarded – undo
2384 2382
                 while (($char = array_shift($chars)) !== null) {
2385 2383
                     if ($char === '[') {
2386 2384
                         if (count($tree) > 0) {
2387
-                            ++ $bracketCount;
2385
+                            ++$bracketCount;
2388 2386
                         } else {
2389 2387
                             $tree[]        = &$current;
2390
-                            $current[$uid] = array($uid + 1 => '');
2391
-                            $current       = &$current[$uid ++];
2392
-                            $curTxt        = &$current[$uid ++];
2388
+                            $current[$uid] = array($uid+1 => '');
2389
+                            $current       = &$current[$uid++];
2390
+                            $curTxt        = &$current[$uid++];
2393 2391
                             continue;
2394 2392
                         }
2395 2393
                     } elseif ($char === ']') {
2396 2394
                         if ($bracketCount > 0) {
2397
-                            -- $bracketCount;
2395
+                            --$bracketCount;
2398 2396
                         } else {
2399
-                            $current = &$tree[count($tree) - 1];
2397
+                            $current = &$tree[count($tree)-1];
2400 2398
                             array_pop($tree);
2401 2399
                             if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2402 2400
                                 $current[$uid] = '';
2403
-                                $curTxt        = &$current[$uid ++];
2401
+                                $curTxt        = &$current[$uid++];
2404 2402
                             }
2405 2403
                             continue;
2406 2404
                         }
2407 2405
                     } elseif ($char === '$') {
2408 2406
                         if (count($tree) == 0) {
2409
-                            $curTxt        = &$current[$uid ++];
2407
+                            $curTxt        = &$current[$uid++];
2410 2408
                             $inSplittedVar = true;
2411 2409
                         }
2412 2410
                     } elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2413
-                        $curTxt        = &$current[$uid ++];
2411
+                        $curTxt        = &$current[$uid++];
2414 2412
                         $inSplittedVar = false;
2415 2413
                     }
2416 2414
 
@@ -2419,16 +2417,16 @@  discard block
 block discarded – undo
2419 2417
                 unset($uid, $current, $curTxt, $tree, $chars);
2420 2418
 
2421 2419
                 if ($this->debug) {
2422
-                    echo 'RECURSIVE VAR REPLACEMENT : ' . $key . "\n";
2420
+                    echo 'RECURSIVE VAR REPLACEMENT : '.$key."\n";
2423 2421
                 }
2424 2422
 
2425 2423
                 $key = $this->flattenVarTree($parsed);
2426 2424
 
2427 2425
                 if ($this->debug) {
2428
-                    echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2426
+                    echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2429 2427
                 }
2430 2428
 
2431
-                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("' . $key . '")');
2429
+                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("'.$key.'")');
2432 2430
             } else {
2433 2431
                 $output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2434 2432
             }
@@ -2453,10 +2451,10 @@  discard block
 block discarded – undo
2453 2451
                     if (substr($expMatch[2][$k], 0, 1) === '=') {
2454 2452
                         $assign = true;
2455 2453
                         if ($operator === '=') {
2456
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, can not use "==" in expressions');
2454
+                            throw new CompilationException($this, 'Invalid expression <em>'.$substr.'</em>, can not use "==" in expressions');
2457 2455
                         }
2458 2456
                         if ($curBlock !== 'root') {
2459
-                            throw new CompilationException($this, 'Invalid expression <em>' . $substr . '</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2457
+                            throw new CompilationException($this, 'Invalid expression <em>'.$substr.'</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2460 2458
                         }
2461 2459
                         $operator .= '=';
2462 2460
                         $expMatch[2][$k] = substr($expMatch[2][$k], 1);
@@ -2467,22 +2465,22 @@  discard block
 block discarded – undo
2467 2465
                         $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2468 2466
                     }
2469 2467
                     if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2470
-                        $output = '(' . $output . $operator . $operator . ')';
2468
+                        $output = '('.$output.$operator.$operator.')';
2471 2469
                         break;
2472 2470
                     } elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2473
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2471
+                        $output = '('.$output.' '.$operator.' '.$this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2474 2472
                     } elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2475
-                        $output = '(' . $output . ' ' . $operator . ' ' . $this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression') . ')';
2473
+                        $output = '('.$output.' '.$operator.' '.$this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2476 2474
                     } elseif (!empty($expMatch[2][$k])) {
2477
-                        $output = '(' . $output . ' ' . $operator . ' ' . str_replace(',', '.', $expMatch[2][$k]) . ')';
2475
+                        $output = '('.$output.' '.$operator.' '.str_replace(',', '.', $expMatch[2][$k]).')';
2478 2476
                     } else {
2479
-                        throw new CompilationException($this, 'Unfinished expression <em>' . $substr . '</em>, missing var or number after math operator');
2477
+                        throw new CompilationException($this, 'Unfinished expression <em>'.$substr.'</em>, missing var or number after math operator');
2480 2478
                     }
2481 2479
                 }
2482 2480
             }
2483 2481
 
2484 2482
             if ($this->autoEscape === true && $curBlock !== 'condition') {
2485
-                $output = '(is_string($tmp=' . $output . ') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2483
+                $output = '(is_string($tmp='.$output.') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2486 2484
             }
2487 2485
 
2488 2486
             // handle modifiers
@@ -2506,7 +2504,7 @@  discard block
 block discarded – undo
2506 2504
             } elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2507 2505
                 return $output;
2508 2506
             } elseif (isset($assign)) {
2509
-                return self::PHP_OPEN . $output . ';' . self::PHP_CLOSE;
2507
+                return self::PHP_OPEN.$output.';'.self::PHP_CLOSE;
2510 2508
             } else {
2511 2509
                 return $output;
2512 2510
             }
@@ -2514,7 +2512,7 @@  discard block
 block discarded – undo
2514 2512
             if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2515 2513
                 return array(0, '');
2516 2514
             } else {
2517
-                throw new CompilationException($this, 'Invalid variable name <em>' . $substr . '</em>');
2515
+                throw new CompilationException($this, 'Invalid variable name <em>'.$substr.'</em>');
2518 2516
             }
2519 2517
         }
2520 2518
     }
@@ -2569,16 +2567,16 @@  discard block
 block discarded – undo
2569 2567
             if (empty($methMatch[2])) {
2570 2568
                 // property
2571 2569
                 if ($curBlock === 'root') {
2572
-                    $output .= '->' . $methMatch[1];
2570
+                    $output .= '->'.$methMatch[1];
2573 2571
                 } else {
2574
-                    $output = '(($tmp = ' . $output . ') ? $tmp->' . $methMatch[1] . ' : null)';
2572
+                    $output = '(($tmp = '.$output.') ? $tmp->'.$methMatch[1].' : null)';
2575 2573
                 }
2576 2574
                 $ptr += strlen($methMatch[1]);
2577 2575
             } else {
2578 2576
                 // method
2579 2577
                 if (substr($methMatch[2], 0, 2) === '()') {
2580
-                    $parsedCall = $methMatch[1] . '()';
2581
-                    $ptr += strlen($methMatch[1]) + 2;
2578
+                    $parsedCall = $methMatch[1].'()';
2579
+                    $ptr += strlen($methMatch[1])+2;
2582 2580
                 } else {
2583 2581
                     $parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2584 2582
                 }
@@ -2587,15 +2585,15 @@  discard block
 block discarded – undo
2587 2585
                     $method = strtolower(substr($parsedCall, 0, $argPos));
2588 2586
                     $args   = substr($parsedCall, $argPos);
2589 2587
                     if ($curBlock === 'root') {
2590
-                        $output = '$this->getSecurityPolicy()->callMethod($this, ' . $output . ', ' . var_export($method, true) . ', array' . $args . ')';
2588
+                        $output = '$this->getSecurityPolicy()->callMethod($this, '.$output.', '.var_export($method, true).', array'.$args.')';
2591 2589
                     } else {
2592
-                        $output = '(($tmp = ' . $output . ') ? $this->getSecurityPolicy()->callMethod($this, $tmp, ' . var_export($method, true) . ', array' . $args . ') : null)';
2590
+                        $output = '(($tmp = '.$output.') ? $this->getSecurityPolicy()->callMethod($this, $tmp, '.var_export($method, true).', array'.$args.') : null)';
2593 2591
                     }
2594 2592
                 } else {
2595 2593
                     if ($curBlock === 'root') {
2596
-                        $output .= '->' . $parsedCall;
2594
+                        $output .= '->'.$parsedCall;
2597 2595
                     } else {
2598
-                        $output = '(($tmp = ' . $output . ') ? $tmp->' . $parsedCall . ' : null)';
2596
+                        $output = '(($tmp = '.$output.') ? $tmp->'.$parsedCall.' : null)';
2599 2597
                     }
2600 2598
                 }
2601 2599
             }
@@ -2621,21 +2619,21 @@  discard block
 block discarded – undo
2621 2619
             return '$this->scope';
2622 2620
         }
2623 2621
         if (substr($key, 0, 1) === '.') {
2624
-            $key = 'dwoo' . $key;
2622
+            $key = 'dwoo'.$key;
2625 2623
         }
2626 2624
         if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2627 2625
             $global = strtoupper($m[1]);
2628 2626
             if ($global === 'COOKIES') {
2629 2627
                 $global = 'COOKIE';
2630 2628
             }
2631
-            $key = '$_' . $global;
2629
+            $key = '$_'.$global;
2632 2630
             foreach (explode('.', ltrim($m[2], '.')) as $part) {
2633
-                $key .= '[' . var_export($part, true) . ']';
2631
+                $key .= '['.var_export($part, true).']';
2634 2632
             }
2635 2633
             if ($curBlock === 'root') {
2636 2634
                 $output = $key;
2637 2635
             } else {
2638
-                $output = '(isset(' . $key . ')?' . $key . ':null)';
2636
+                $output = '(isset('.$key.')?'.$key.':null)';
2639 2637
             }
2640 2638
         } elseif (preg_match('#dwoo\.const\.([a-z0-9_:]+)#i', $key, $m)) {
2641 2639
             return $this->parseConstKey($m[1], $curBlock);
@@ -2651,9 +2649,9 @@  discard block
 block discarded – undo
2651 2649
                     $output = '$tmp_key';
2652 2650
                 } else {
2653 2651
                     if ($curBlock === 'root') {
2654
-                        $output = '$this->scope["' . $key . '"]';
2652
+                        $output = '$this->scope["'.$key.'"]';
2655 2653
                     } else {
2656
-                        $output = '(isset($this->scope["' . $key . '"]) ? $this->scope["' . $key . '"] : null)';
2654
+                        $output = '(isset($this->scope["'.$key.'"]) ? $this->scope["'.$key.'"] : null)';
2657 2655
                     }
2658 2656
                 }
2659 2657
             } else {
@@ -2664,7 +2662,7 @@  discard block
 block discarded – undo
2664 2662
                     $parentCnt = 0;
2665 2663
 
2666 2664
                     while (true) {
2667
-                        ++ $parentCnt;
2665
+                        ++$parentCnt;
2668 2666
                         array_shift($m[2]);
2669 2667
                         array_shift($m[1]);
2670 2668
                         if (current($m[2]) === '_parent') {
@@ -2673,7 +2671,7 @@  discard block
 block discarded – undo
2673 2671
                         break;
2674 2672
                     }
2675 2673
 
2676
-                    $output = '$this->readParentVar(' . $parentCnt . ')';
2674
+                    $output = '$this->readParentVar('.$parentCnt.')';
2677 2675
                 } else {
2678 2676
                     if ($i === 'dwoo') {
2679 2677
                         $output = '$this->globals';
@@ -2692,28 +2690,28 @@  discard block
 block discarded – undo
2692 2690
                     while (count($m[1]) && $m[1][0] !== '->') {
2693 2691
                         $m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2694 2692
                         if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2695
-                            $output .= '[' . $m[2][0] . ']';
2693
+                            $output .= '['.$m[2][0].']';
2696 2694
                         } else {
2697
-                            $output .= '["' . $m[2][0] . '"]';
2695
+                            $output .= '["'.$m[2][0].'"]';
2698 2696
                         }
2699 2697
                         array_shift($m[2]);
2700 2698
                         array_shift($m[1]);
2701 2699
                     }
2702 2700
 
2703 2701
                     if ($curBlock !== 'root') {
2704
-                        $output = '(isset(' . $output . ') ? ' . $output . ':null)';
2702
+                        $output = '(isset('.$output.') ? '.$output.':null)';
2705 2703
                     }
2706 2704
                 }
2707 2705
 
2708 2706
                 if (count($m[2])) {
2709 2707
                     unset($m[0]);
2710
-                    $output = '$this->readVarInto(' . str_replace("\n", '', var_export($m, true)) . ', ' . $output . ', ' . ($curBlock == 'root' ? 'false' : 'true') . ')';
2708
+                    $output = '$this->readVarInto('.str_replace("\n", '', var_export($m, true)).', '.$output.', '.($curBlock == 'root' ? 'false' : 'true').')';
2711 2709
                 }
2712 2710
             }
2713 2711
         } else {
2714 2712
             preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2715 2713
             unset($m[0]);
2716
-            $output = '$this->readVar(' . str_replace("\n", '', var_export($m, true)) . ')';
2714
+            $output = '$this->readVar('.str_replace("\n", '', var_export($m, true)).')';
2717 2715
         }
2718 2716
 
2719 2717
         return $output;
@@ -2733,38 +2731,38 @@  discard block
 block discarded – undo
2733 2731
         $out = $recursed ? '".$this->readVarInto(' : '';
2734 2732
         foreach ($tree as $bit) {
2735 2733
             if (is_array($bit)) {
2736
-                $out .= '.' . $this->flattenVarTree($bit, false);
2734
+                $out .= '.'.$this->flattenVarTree($bit, false);
2737 2735
             } else {
2738 2736
                 $key = str_replace('"', '\\"', $bit);
2739 2737
 
2740 2738
                 if (substr($key, 0, 1) === '$') {
2741
-                    $out .= '".' . $this->parseVar($key, 0, strlen($key), false, 'variable') . '."';
2739
+                    $out .= '".'.$this->parseVar($key, 0, strlen($key), false, 'variable').'."';
2742 2740
                 } else {
2743 2741
                     $cnt = substr_count($key, '$');
2744 2742
 
2745 2743
                     if ($this->debug) {
2746
-                        echo 'PARSING SUBVARS IN : ' . $key . "\n";
2744
+                        echo 'PARSING SUBVARS IN : '.$key."\n";
2747 2745
                     }
2748 2746
                     if ($cnt > 0) {
2749
-                        while (-- $cnt >= 0) {
2747
+                        while (--$cnt >= 0) {
2750 2748
                             if (isset($last)) {
2751
-                                $last = strrpos($key, '$', - (strlen($key) - $last + 1));
2749
+                                $last = strrpos($key, '$', - (strlen($key)-$last+1));
2752 2750
                             } else {
2753 2751
                                 $last = strrpos($key, '$');
2754 2752
                             }
2755
-                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2753
+                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*'.'((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2756 2754
 
2757 2755
                             $len = strlen($submatch[0]);
2758 2756
                             $key = substr_replace(
2759 2757
                                 $key, preg_replace_callback(
2760
-                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)' . '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2758
+                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)'.'((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', array(
2761 2759
                                         $this,
2762 2760
                                         'replaceVarKeyHelper'
2763 2761
                                     ), substr($key, $last, $len)
2764 2762
                                 ), $last, $len
2765 2763
                             );
2766 2764
                             if ($this->debug) {
2767
-                                echo 'RECURSIVE VAR REPLACEMENT DONE : ' . $key . "\n";
2765
+                                echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2768 2766
                             }
2769 2767
                         }
2770 2768
                         unset($last);
@@ -2790,7 +2788,7 @@  discard block
 block discarded – undo
2790 2788
      */
2791 2789
     protected function replaceVarKeyHelper($match)
2792 2790
     {
2793
-        return '".' . $this->parseVar($match[0], 0, strlen($match[0]), false, 'variable') . '."';
2791
+        return '".'.$this->parseVar($match[0], 0, strlen($match[0]), false, 'variable').'."';
2794 2792
     }
2795 2793
 
2796 2794
     /**
@@ -2810,7 +2808,7 @@  discard block
 block discarded – undo
2810 2808
      */
2811 2809
     protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2812 2810
     {
2813
-        $substr = substr($in, $from, $to - $from);
2811
+        $substr = substr($in, $from, $to-$from);
2814 2812
 
2815 2813
         $end = strlen($substr);
2816 2814
 
@@ -2884,48 +2882,48 @@  discard block
 block discarded – undo
2884 2882
 
2885 2883
         if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2886 2884
             if ($this->debug) {
2887
-                echo 'BOOLEAN(FALSE) PARSED' . "\n";
2885
+                echo 'BOOLEAN(FALSE) PARSED'."\n";
2888 2886
             }
2889 2887
             $substr = 'false';
2890 2888
             $type   = self::T_BOOL;
2891 2889
         } elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2892 2890
             if ($this->debug) {
2893
-                echo 'BOOLEAN(TRUE) PARSED' . "\n";
2891
+                echo 'BOOLEAN(TRUE) PARSED'."\n";
2894 2892
             }
2895 2893
             $substr = 'true';
2896 2894
             $type   = self::T_BOOL;
2897 2895
         } elseif ($substr === 'null' || $substr === 'NULL') {
2898 2896
             if ($this->debug) {
2899
-                echo 'NULL PARSED' . "\n";
2897
+                echo 'NULL PARSED'."\n";
2900 2898
             }
2901 2899
             $substr = 'null';
2902 2900
             $type   = self::T_NULL;
2903 2901
         } elseif (is_numeric($substr)) {
2904
-            $substr = (float)$substr;
2905
-            if ((int)$substr == $substr) {
2906
-                $substr = (int)$substr;
2902
+            $substr = (float) $substr;
2903
+            if ((int) $substr == $substr) {
2904
+                $substr = (int) $substr;
2907 2905
             }
2908 2906
             $type = self::T_NUMERIC;
2909 2907
             if ($this->debug) {
2910
-                echo 'NUMBER (' . $substr . ') PARSED' . "\n";
2908
+                echo 'NUMBER ('.$substr.') PARSED'."\n";
2911 2909
             }
2912 2910
         } elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2913 2911
             if ($this->debug) {
2914 2912
                 echo 'SIMPLE MATH PARSED . "\n"';
2915 2913
             }
2916 2914
             $type   = self::T_MATH;
2917
-            $substr = '(' . $substr . ')';
2915
+            $substr = '('.$substr.')';
2918 2916
         } elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2919 2917
             if ($this->debug) {
2920
-                echo 'BREAKCHAR (' . $substr . ') PARSED' . "\n";
2918
+                echo 'BREAKCHAR ('.$substr.') PARSED'."\n";
2921 2919
             }
2922 2920
             $type = self::T_BREAKCHAR;
2923 2921
             //$substr = '"'.$substr.'"';
2924 2922
         } else {
2925
-            $substr = $this->replaceStringVars('\'' . str_replace('\'', '\\\'', $substr) . '\'', '\'', $curBlock);
2923
+            $substr = $this->replaceStringVars('\''.str_replace('\'', '\\\'', $substr).'\'', '\'', $curBlock);
2926 2924
             $type   = self::T_UNQUOTED_STRING;
2927 2925
             if ($this->debug) {
2928
-                echo 'BLABBER (' . $substr . ') CASTED AS STRING' . "\n";
2926
+                echo 'BLABBER ('.$substr.') CASTED AS STRING'."\n";
2929 2927
             }
2930 2928
         }
2931 2929
 
@@ -2955,28 +2953,28 @@  discard block
 block discarded – undo
2955 2953
     {
2956 2954
         $pos = 0;
2957 2955
         if ($this->debug) {
2958
-            echo 'STRING VAR REPLACEMENT : ' . $string . "\n";
2956
+            echo 'STRING VAR REPLACEMENT : '.$string."\n";
2959 2957
         }
2960 2958
         // replace vars
2961 2959
         while (($pos = strpos($string, '$', $pos)) !== false) {
2962
-            $prev = substr($string, $pos - 1, 1);
2960
+            $prev = substr($string, $pos-1, 1);
2963 2961
             if ($prev === '\\') {
2964
-                ++ $pos;
2962
+                ++$pos;
2965 2963
                 continue;
2966 2964
             }
2967 2965
 
2968 2966
             $var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2969 2967
             $len = $var[0];
2970
-            $var = $this->parse(str_replace('\\' . $first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2968
+            $var = $this->parse(str_replace('\\'.$first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2971 2969
 
2972
-            if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
2973
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos - 1, $len + 2);
2970
+            if ($prev === '`' && substr($string, $pos+$len, 1) === '`') {
2971
+                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos-1, $len+2);
2974 2972
             } else {
2975
-                $string = substr_replace($string, $first . '.' . $var[1] . '.' . $first, $pos, $len);
2973
+                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos, $len);
2976 2974
             }
2977
-            $pos += strlen($var[1]) + 2;
2975
+            $pos += strlen($var[1])+2;
2978 2976
             if ($this->debug) {
2979
-                echo 'STRING VAR REPLACEMENT DONE : ' . $string . "\n";
2977
+                echo 'STRING VAR REPLACEMENT DONE : '.$string."\n";
2980 2978
             }
2981 2979
         }
2982 2980
 
@@ -3012,7 +3010,7 @@  discard block
 block discarded – undo
3012 3010
     protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
3013 3011
     {
3014 3012
         if ($this->debug) {
3015
-            echo 'PARSING MODIFIERS : ' . $m[3] . "\n";
3013
+            echo 'PARSING MODIFIERS : '.$m[3]."\n";
3016 3014
         }
3017 3015
 
3018 3016
         if ($pointer !== null) {
@@ -3036,7 +3034,7 @@  discard block
 block discarded – undo
3036 3034
             }
3037 3035
             if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
3038 3036
                 if ($this->debug) {
3039
-                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND' . "\n";
3037
+                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND'."\n";
3040 3038
                 }
3041 3039
                 $continue = false;
3042 3040
                 if ($pointer !== null) {
@@ -3047,7 +3045,7 @@  discard block
 block discarded – undo
3047 3045
             $cmdstr   = $cmdstrsrc;
3048 3046
             $paramsep = ':';
3049 3047
             if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
3050
-                throw new CompilationException($this, 'Invalid modifier name, started with : ' . substr($cmdstr, 0, 10));
3048
+                throw new CompilationException($this, 'Invalid modifier name, started with : '.substr($cmdstr, 0, 10));
3051 3049
             }
3052 3050
             $paramspos = !empty($match[2]) ? strlen($match[1]) : false;
3053 3051
             $func      = $match[1];
@@ -3057,10 +3055,10 @@  discard block
 block discarded – undo
3057 3055
                 $cmdstrsrc = substr($cmdstrsrc, strlen($func));
3058 3056
                 $params    = array();
3059 3057
                 if ($this->debug) {
3060
-                    echo 'MODIFIER (' . $func . ') CALLED WITH NO PARAMS' . "\n";
3058
+                    echo 'MODIFIER ('.$func.') CALLED WITH NO PARAMS'."\n";
3061 3059
                 }
3062 3060
             } else {
3063
-                $paramstr = substr($cmdstr, $paramspos + 1);
3061
+                $paramstr = substr($cmdstr, $paramspos+1);
3064 3062
                 if (substr($paramstr, - 1, 1) === $paramsep) {
3065 3063
                     $paramstr = substr($paramstr, 0, - 1);
3066 3064
                 }
@@ -3069,41 +3067,41 @@  discard block
 block discarded – undo
3069 3067
                 $params = array();
3070 3068
                 while ($ptr < strlen($paramstr)) {
3071 3069
                     if ($this->debug) {
3072
-                        echo 'MODIFIER (' . $func . ') START PARAM PARSING WITH POINTER AT ' . $ptr . "\n";
3070
+                        echo 'MODIFIER ('.$func.') START PARAM PARSING WITH POINTER AT '.$ptr."\n";
3073 3071
                     }
3074 3072
                     if ($this->debug) {
3075
-                        echo $paramstr . '--' . $ptr . '--' . strlen($paramstr) . '--modifier' . "\n";
3073
+                        echo $paramstr.'--'.$ptr.'--'.strlen($paramstr).'--modifier'."\n";
3076 3074
                     }
3077 3075
                     $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
3078 3076
                     if ($this->debug) {
3079
-                        echo 'PARAM PARSED, POINTER AT ' . $ptr . "\n";
3077
+                        echo 'PARAM PARSED, POINTER AT '.$ptr."\n";
3080 3078
                     }
3081 3079
 
3082 3080
                     if ($ptr >= strlen($paramstr)) {
3083 3081
                         if ($this->debug) {
3084
-                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED' . "\n";
3082
+                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED'."\n";
3085 3083
                         }
3086 3084
                         break;
3087 3085
                     }
3088 3086
 
3089 3087
                     if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
3090 3088
                         if ($this->debug) {
3091
-                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT ' . $ptr . "\n";
3089
+                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT '.$ptr."\n";
3092 3090
                         }
3093 3091
                         if ($paramstr[$ptr] !== '|') {
3094 3092
                             $continue = false;
3095 3093
                             if ($pointer !== null) {
3096
-                                $pointer -= strlen($paramstr) - $ptr;
3094
+                                $pointer -= strlen($paramstr)-$ptr;
3097 3095
                             }
3098 3096
                         }
3099
-                        ++ $ptr;
3097
+                        ++$ptr;
3100 3098
                         break;
3101 3099
                     }
3102 3100
                     if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
3103
-                        ++ $ptr;
3101
+                        ++$ptr;
3104 3102
                     }
3105 3103
                 }
3106
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
3104
+                $cmdstrsrc = substr($cmdstrsrc, strlen($func)+1+$ptr);
3107 3105
                 foreach ($params as $k => $p) {
3108 3106
                     if (is_array($p) && is_array($p[1])) {
3109 3107
                         $state |= 2;
@@ -3143,9 +3141,9 @@  discard block
 block discarded – undo
3143 3141
                 $params = self::implode_r($params);
3144 3142
 
3145 3143
                 if ($mapped) {
3146
-                    $output = '$this->arrayMap(\'' . $func . '\', array(' . $params . '))';
3144
+                    $output = '$this->arrayMap(\''.$func.'\', array('.$params.'))';
3147 3145
                 } else {
3148
-                    $output = $func . '(' . $params . ')';
3146
+                    $output = $func.'('.$params.')';
3149 3147
                 }
3150 3148
             } elseif ($pluginType & Core::PROXY_PLUGIN) {
3151 3149
                 $params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
@@ -3163,36 +3161,36 @@  discard block
 block discarded – undo
3163 3161
                     $callback = $this->customPlugins[$func]['callback'];
3164 3162
                     if (is_array($callback)) {
3165 3163
                         if (is_object($callback[0])) {
3166
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3164
+                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
3167 3165
                         } else {
3168
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3166
+                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
3169 3167
                         }
3170 3168
                     } elseif ($mapped) {
3171
-                        $output = '$this->arrayMap(\'' . $callback . '\', array(' . $params . '))';
3169
+                        $output = '$this->arrayMap(\''.$callback.'\', array('.$params.'))';
3172 3170
                     } else {
3173
-                        $output = $callback . '(' . $params . ')';
3171
+                        $output = $callback.'('.$params.')';
3174 3172
                     }
3175 3173
                 } elseif ($mapped) {
3176
-                    $output = '$this->arrayMap(\'smarty_modifier_' . $func . '\', array(' . $params . '))';
3174
+                    $output = '$this->arrayMap(\'smarty_modifier_'.$func.'\', array('.$params.'))';
3177 3175
                 } else {
3178
-                    $output = 'smarty_modifier_' . $func . '(' . $params . ')';
3176
+                    $output = 'smarty_modifier_'.$func.'('.$params.')';
3179 3177
                 }
3180 3178
             } else {
3181 3179
                 if ($pluginType & Core::CUSTOM_PLUGIN) {
3182 3180
                     $callback   = $this->customPlugins[$func]['callback'];
3183 3181
                     $pluginName = $callback;
3184 3182
                 } else {
3185
-                    if (class_exists('Plugin' . Core::toCamelCase($func)) !== false || function_exists('Plugin' .
3186
-                            Core::toCamelCase($func) . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3183
+                    if (class_exists('Plugin'.Core::toCamelCase($func)) !== false || function_exists('Plugin'.
3184
+                            Core::toCamelCase($func).(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : ''))
3187 3185
                         !== false) {
3188
-                        $pluginName = 'Plugin' . Core::toCamelCase($func);
3186
+                        $pluginName = 'Plugin'.Core::toCamelCase($func);
3189 3187
                     } else {
3190
-                        $pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func);
3188
+                        $pluginName = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func);
3191 3189
                     }
3192 3190
                     if ($pluginType & Core::CLASS_PLUGIN) {
3193 3191
                         $callback = array($pluginName, ($pluginType & Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3194 3192
                     } else {
3195
-                        $callback = $pluginName . (($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3193
+                        $callback = $pluginName.(($pluginType & Core::COMPILABLE_PLUGIN) ? 'Compile' : '');
3196 3194
                     }
3197 3195
                 }
3198 3196
                 $params = $this->mapParams($params, $callback, $state);
@@ -3209,10 +3207,10 @@  discard block
 block discarded – undo
3209 3207
                         if ($pluginType & Core::CUSTOM_PLUGIN) {
3210 3208
                             $funcCompiler = $this->customPlugins[$func]['callback'];
3211 3209
                         } else {
3212
-                            if (function_exists('Plugin' . Core::toCamelCase($func) . 'Compile') !== false) {
3213
-                                $funcCompiler = 'Plugin' . Core::toCamelCase($func) . 'Compile';
3210
+                            if (function_exists('Plugin'.Core::toCamelCase($func).'Compile') !== false) {
3211
+                                $funcCompiler = 'Plugin'.Core::toCamelCase($func).'Compile';
3214 3212
                             } else {
3215
-                                $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) .
3213
+                                $funcCompiler = Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).
3216 3214
                                     'Compile';
3217 3215
                             }
3218 3216
                         }
@@ -3223,9 +3221,9 @@  discard block
 block discarded – undo
3223 3221
 
3224 3222
                         $params = self::implode_r($params);
3225 3223
                         if ($mapped) {
3226
-                            $output = '$this->arrayMap(\'' . $pluginName . '\', array(' . $params . '))';
3224
+                            $output = '$this->arrayMap(\''.$pluginName.'\', array('.$params.'))';
3227 3225
                         } else {
3228
-                            $output = $pluginName . '(' . $params . ')';
3226
+                            $output = $pluginName.'('.$params.')';
3229 3227
                         }
3230 3228
                     }
3231 3229
                 } else {
@@ -3237,7 +3235,7 @@  discard block
 block discarded – undo
3237 3235
                             $callback = $this->customPlugins[$func]['callback'];
3238 3236
                             if (!is_array($callback)) {
3239 3237
                                 if (!method_exists($callback, 'compile')) {
3240
-                                    throw new Exception('Custom plugin ' . $func . ' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3238
+                                    throw new Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3241 3239
                                 }
3242 3240
                                 if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3243 3241
                                     $funcCompiler = array($callback, 'compile');
@@ -3248,11 +3246,11 @@  discard block
 block discarded – undo
3248 3246
                                 $funcCompiler = $callback;
3249 3247
                             }
3250 3248
                         } else {
3251
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3252
-                                $funcCompiler = array('Plugin' . Core::toCamelCase($func), 'compile');
3249
+                            if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
3250
+                                $funcCompiler = array('Plugin'.Core::toCamelCase($func), 'compile');
3253 3251
                             } else {
3254 3252
                                 $funcCompiler = array(
3255
-                                    Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func),
3253
+                                    Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func),
3256 3254
                                     'compile'
3257 3255
                                 );
3258 3256
                             }
@@ -3264,19 +3262,19 @@  discard block
 block discarded – undo
3264 3262
 
3265 3263
                         if ($pluginType & Core::CUSTOM_PLUGIN) {
3266 3264
                             if (is_object($callback[0])) {
3267
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array($this->plugins[\'' . $func . '\'][\'callback\'][0], \'' . $callback[1] . '\'), array(' . $params . '))';
3265
+                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
3268 3266
                             } else {
3269
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array') . '(array(\'' . $callback[0] . '\', \'' . $callback[1] . '\'), array(' . $params . '))';
3267
+                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
3270 3268
                             }
3271 3269
                         } elseif ($mapped) {
3272 3270
                             $output = '$this->arrayMap(array($this->getObjectPlugin(\''.
3273
-                                Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($func) . '\'), 
3274
-                            \'process\'), array(' . $params . '))';
3271
+                                Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($func).'\'), 
3272
+                            \'process\'), array(' . $params.'))';
3275 3273
                         } else {
3276
-                            if (class_exists('Plugin' . Core::toCamelCase($func)) !== false) {
3277
-                                $output = '$this->classCall(\'Plugin' . Core::toCamelCase($func) . '\', array(' . $params . '))';
3274
+                            if (class_exists('Plugin'.Core::toCamelCase($func)) !== false) {
3275
+                                $output = '$this->classCall(\'Plugin'.Core::toCamelCase($func).'\', array('.$params.'))';
3278 3276
                             } else {
3279
-                                $output = '$this->classCall(\'' . $func . '\', array(' . $params . '))';
3277
+                                $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
3280 3278
                             }
3281 3279
                         }
3282 3280
                     }
@@ -3289,7 +3287,7 @@  discard block
 block discarded – undo
3289 3287
         } elseif ($curBlock === 'var' || $m[1] === null) {
3290 3288
             return $output;
3291 3289
         } elseif ($curBlock === 'string' || $curBlock === 'root') {
3292
-            return $m[1] . '.' . $output . '.' . $m[1] . (isset($add) ? $add : null);
3290
+            return $m[1].'.'.$output.'.'.$m[1].(isset($add) ? $add : null);
3293 3291
         }
3294 3292
 
3295 3293
         return '';
@@ -3312,14 +3310,14 @@  discard block
 block discarded – undo
3312 3310
             if (is_array($p)) {
3313 3311
                 $out2 = 'array(';
3314 3312
                 foreach ($p as $k2 => $v) {
3315
-                    $out2 .= var_export($k2, true) . ' => ' . (is_array($v) ? 'array(' . self::implode_r($v, true) . ')' : $v) . ', ';
3313
+                    $out2 .= var_export($k2, true).' => '.(is_array($v) ? 'array('.self::implode_r($v, true).')' : $v).', ';
3316 3314
                 }
3317
-                $p = rtrim($out2, ', ') . ')';
3315
+                $p = rtrim($out2, ', ').')';
3318 3316
             }
3319 3317
             if ($recursiveCall) {
3320
-                $out .= var_export($k, true) . ' => ' . $p . ', ';
3318
+                $out .= var_export($k, true).' => '.$p.', ';
3321 3319
             } else {
3322
-                $out .= $p . ', ';
3320
+                $out .= $p.', ';
3323 3321
             }
3324 3322
         }
3325 3323
 
@@ -3343,7 +3341,7 @@  discard block
 block discarded – undo
3343 3341
         if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) || ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3344 3342
             $phpFunc = true;
3345 3343
         } elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3346
-            throw new SecurityException('Call to a disallowed php function : ' . $name);
3344
+            throw new SecurityException('Call to a disallowed php function : '.$name);
3347 3345
         }
3348 3346
 
3349 3347
         while ($pluginType <= 0) {
@@ -3354,61 +3352,60 @@  discard block
 block discarded – undo
3354 3352
             elseif (isset($this->customPlugins[$name])) {
3355 3353
                 $pluginType = $this->customPlugins[$name]['type'] | Core::CUSTOM_PLUGIN;
3356 3354
             } // Class blocks plugin
3357
-            elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), false) !==
3355
+            elseif (class_exists(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($name), false) !==
3358 3356
                 false) {
3359
-                if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3357
+                if (is_subclass_of(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($name), 'Dwoo\Block\Plugin')) {
3360 3358
                     $pluginType = Core::BLOCK_PLUGIN;
3361 3359
                 } else {
3362 3360
                     $pluginType = Core::CLASS_PLUGIN;
3363 3361
                 }
3364
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . Core::toCamelCase($name));
3362
+                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.Core::toCamelCase($name));
3365 3363
                 if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3366 3364
                     $pluginType |= Core::COMPILABLE_PLUGIN;
3367 3365
                 }
3368 3366
             } // Class functions plugin
3369
-            elseif(class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name), false) !==
3367
+            elseif (class_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name), false) !==
3370 3368
                 false) {
3371 3369
                 $pluginType = Core::CLASS_PLUGIN;
3372
-                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name));
3370
+                $interfaces = class_implements(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name));
3373 3371
                 if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3374 3372
                     $pluginType |= Core::COMPILABLE_PLUGIN;
3375 3373
                 }
3376 3374
             } // Class without namespace
3377
-            elseif(class_exists('Plugin' . Core::toCamelCase($name), false) !== false) {
3375
+            elseif (class_exists('Plugin'.Core::toCamelCase($name), false) !== false) {
3378 3376
                 $pluginType = Core::CLASS_PLUGIN;
3379
-                $interfaces = class_implements('Plugin' . Core::toCamelCase($name));
3377
+                $interfaces = class_implements('Plugin'.Core::toCamelCase($name));
3380 3378
                 if (in_array('Dwoo\ICompilable', $interfaces) !== false || in_array('Dwoo\ICompilable\Block', $interfaces) !== false) {
3381 3379
                     $pluginType |= Core::COMPILABLE_PLUGIN;
3382 3380
                 }
3383 3381
             } // Function plugin (with/without namespaces)
3384
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase
3385
-                    ($name)) !==
3386
-                false || function_exists('Plugin' . Core::toCamelCase($name)) !== false) {
3382
+            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name)) !==
3383
+                false || function_exists('Plugin'.Core::toCamelCase($name)) !== false) {
3387 3384
                 $pluginType = Core::FUNC_PLUGIN;
3388 3385
             } // Function plugin compile (with/without namespaces)
3389
-            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin' . Core::toCamelCase($name) .
3390
-                    'Compile') !== false || function_exists('Plugin' . Core::toCamelCase($name) . 'Compile') !==
3386
+            elseif (function_exists(Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin'.Core::toCamelCase($name).
3387
+                    'Compile') !== false || function_exists('Plugin'.Core::toCamelCase($name).'Compile') !==
3391 3388
                 false) {
3392 3389
                 $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3393 3390
             } // Helper plugin compile
3394
-            elseif(function_exists(Core::NAMESPACE_PLUGINS_HELPERS . 'Plugin' . Core::toCamelCase($name) . 'Compile')
3391
+            elseif (function_exists(Core::NAMESPACE_PLUGINS_HELPERS.'Plugin'.Core::toCamelCase($name).'Compile')
3395 3392
                 !== false) {
3396 3393
                 $pluginType = Core::FUNC_PLUGIN | Core::COMPILABLE_PLUGIN;
3397 3394
             } // Smarty modifier
3398
-            elseif (function_exists('smarty_modifier_' . $name) !== false) {
3395
+            elseif (function_exists('smarty_modifier_'.$name) !== false) {
3399 3396
                 $pluginType = Core::SMARTY_MODIFIER;
3400 3397
             } // Smarty function
3401
-            elseif (function_exists('smarty_function_' . $name) !== false) {
3398
+            elseif (function_exists('smarty_function_'.$name) !== false) {
3402 3399
                 $pluginType = Core::SMARTY_FUNCTION;
3403 3400
             } // Smarty block
3404
-            elseif (function_exists('smarty_block_' . $name) !== false) {
3401
+            elseif (function_exists('smarty_block_'.$name) !== false) {
3405 3402
                 $pluginType = Core::SMARTY_BLOCK;
3406 3403
             } // Everything else
3407 3404
             else {
3408 3405
                 if ($pluginType === - 1) {
3409 3406
                     try {
3410 3407
                         $this->getDwoo()->getLoader()->loadPlugin(
3411
-                            'Plugin' . Core::toCamelCase($name));
3408
+                            'Plugin'.Core::toCamelCase($name));
3412 3409
                     }
3413 3410
                     catch (Exception $e) {
3414 3411
                         if (isset($phpFunc)) {
@@ -3421,9 +3418,9 @@  discard block
 block discarded – undo
3421 3418
                         }
3422 3419
                     }
3423 3420
                 } else {
3424
-                    throw new Exception('Plugin "' . $name . '" could not be found, type:' . $pluginType);
3421
+                    throw new Exception('Plugin "'.$name.'" could not be found, type:'.$pluginType);
3425 3422
                 }
3426
-                ++ $pluginType;
3423
+                ++$pluginType;
3427 3424
             }
3428 3425
         }
3429 3426
 
@@ -3498,9 +3495,9 @@  discard block
 block discarded – undo
3498 3495
                 if (count($ps) === 0) {
3499 3496
                     if ($v[1] === false) {
3500 3497
                         throw new CompilationException(
3501
-                            $this, 'Rest argument missing for ' . str_replace(
3498
+                            $this, 'Rest argument missing for '.str_replace(
3502 3499
                                 array(
3503
-                                    Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3500
+                                    Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin',
3504 3501
                                 'Compile'
3505 3502
                                 ), '', (is_array($callback) ? $callback[0] : $callback)
3506 3503
                             )
@@ -3533,7 +3530,7 @@  discard block
 block discarded – undo
3533 3530
                 // parameter is not defined and not optional, throw error
3534 3531
                 if (is_array($callback)) {
3535 3532
                     if (is_object($callback[0])) {
3536
-                        $name = get_class($callback[0]) . '::' . $callback[1];
3533
+                        $name = get_class($callback[0]).'::'.$callback[1];
3537 3534
                     } else {
3538 3535
                         $name = $callback[0];
3539 3536
                     }
@@ -3542,9 +3539,9 @@  discard block
 block discarded – undo
3542 3539
                 }
3543 3540
 
3544 3541
                 throw new CompilationException(
3545
-                    $this, 'Argument ' . $k . '/' . $v[0] . ' missing for ' . str_replace(
3542
+                    $this, 'Argument '.$k.'/'.$v[0].' missing for '.str_replace(
3546 3543
                         array(
3547
-                            Core::NAMESPACE_PLUGINS_FUNCTIONS . 'Plugin',
3544
+                            Core::NAMESPACE_PLUGINS_FUNCTIONS.'Plugin',
3548 3545
                         'Compile'
3549 3546
                         ), '', $name
3550 3547
                     )
Please login to merge, or discard this patch.
Braces   +3 added lines, -6 removed lines patch added patch discarded remove patch
@@ -478,8 +478,7 @@  discard block
 block discarded – undo
478 478
         if (!class_exists($class) && !function_exists($class)) {
479 479
             try {
480 480
                 $this->getDwoo()->getLoader()->loadPlugin($name);
481
-            }
482
-            catch (Exception $e) {
481
+            } catch (Exception $e) {
483 482
                 throw new Exception('Processor ' . $name . ' could not be found in your plugin directories, please ensure it is in a file named ' . $name . '.php in the plugin directory');
484 483
             }
485 484
         }
@@ -1624,8 +1623,7 @@  discard block
 block discarded – undo
1624 1623
                     // load if plugin
1625 1624
                     try {
1626 1625
                         $this->getPluginType('if');
1627
-                    }
1628
-                    catch (Exception $e) {
1626
+                    } catch (Exception $e) {
1629 1627
                         throw new CompilationException($this, 'Assignments require the "if" plugin to be accessible');
1630 1628
                     }
1631 1629
 
@@ -3409,8 +3407,7 @@  discard block
 block discarded – undo
3409 3407
                     try {
3410 3408
                         $this->getDwoo()->getLoader()->loadPlugin(
3411 3409
                             'Plugin' . Core::toCamelCase($name));
3412
-                    }
3413
-                    catch (Exception $e) {
3410
+                    } catch (Exception $e) {
3414 3411
                         if (isset($phpFunc)) {
3415 3412
                             $pluginType = Core::NATIVE_PLUGIN;
3416 3413
                         } elseif (is_object($this->getDwoo()->getPluginProxy()) && $this->getDwoo()->getPluginProxy()->handles($name)) {
Please login to merge, or discard this patch.
lib/Dwoo/Core.php 4 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
      * Adds a filter to this Dwoo instance, it will be used to filter the output of all the templates rendered by this
537 537
      * instance.
538 538
      *
539
-     * @param mixed $callback a callback or a filter name if it is autoloaded from a plugin directory
539
+     * @param Smarty\Filter\Adapter $callback a callback or a filter name if it is autoloaded from a plugin directory
540 540
      * @param bool  $autoload if true, the first parameter must be a filter name from one of the plugin directories
541 541
      *
542 542
      * @return void
@@ -1547,7 +1547,7 @@  discard block
 block discarded – undo
1547 1547
      * @param mixed  $value the value to assign
1548 1548
      * @param string $scope the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1549 1549
      *
1550
-     * @return bool true if assigned correctly or false if a problem occured while parsing the var string
1550
+     * @return null|false true if assigned correctly or false if a problem occured while parsing the var string
1551 1551
      */
1552 1552
     public function assignInScope($value, $scope)
1553 1553
     {
Please login to merge, or discard this patch.
Indentation   +1671 added lines, -1671 removed lines patch added patch discarded remove patch
@@ -44,1683 +44,1683 @@
 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.0';
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 = 130;
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
-    public $globals;
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
-     * Defines how long (in seconds) the cached files must remain valid.
135
-     * can be overriden on a per-template basis
136
-     * -1 = never delete
137
-     * 0 = disabled
138
-     * >0 = duration in seconds
139
-     *
140
-     * @var int
141
-     */
142
-    protected $cacheTime = 0;
143
-
144
-    /**
145
-     * Security policy object.
146
-     *
147
-     * @var SecurityPolicy
148
-     */
149
-    protected $securityPolicy = null;
150
-
151
-    /**
152
-     * Stores the custom plugins callbacks.
153
-     *
154
-     * @see addPlugin
155
-     * @see removePlugin
156
-     * @var array
157
-     */
158
-    protected $plugins = array();
159
-
160
-    /**
161
-     * Stores the filter callbacks.
162
-     *
163
-     * @see addFilter
164
-     * @see removeFilter
165
-     * @var array
166
-     */
167
-    protected $filters = array();
168
-
169
-    /**
170
-     * Stores the resource types and associated
171
-     * classes / compiler classes.
172
-     *
173
-     * @var array
174
-     */
175
-    protected $resources = array(
176
-        'file'   => array(
177
-            'class'    => 'Dwoo\Template\File',
178
-            'compiler' => null,
179
-        ),
180
-        'string' => array(
181
-            'class'    => 'Dwoo\Template\String',
182
-            'compiler' => null,
183
-        ),
184
-    );
185
-
186
-    /**
187
-     * The dwoo loader object used to load plugins by this dwoo instance.
188
-     *
189
-     * @var ILoader
190
-     */
191
-    protected $loader = null;
192
-
193
-    /**
194
-     * Currently rendered template, set to null when not-rendering.
195
-     *
196
-     * @var ITemplate
197
-     */
198
-    protected $template = null;
199
-
200
-    /**
201
-     * Stores the instances of the class plugins during template runtime.
202
-     *
203
-     * @var array
204
-     */
205
-    protected $runtimePlugins;
206
-
207
-    /**
208
-     * Stores the returned values during template runtime.
209
-     *
210
-     * @var array
211
-     */
212
-    protected $returnData;
213
-
214
-    /**
215
-     * Stores the data during template runtime.
216
-     *
217
-     * @var array
218
-     */
219
-    public $data;
220
-
221
-    /**
222
-     * Stores the current scope during template runtime.
223
-     * this should ideally not be accessed directly from outside template code
224
-     *
225
-     * @var mixed
226
-     */
227
-    public $scope;
228
-
229
-    /**
230
-     * Stores the scope tree during template runtime.
231
-     *
232
-     * @var array
233
-     */
234
-    protected $scopeTree;
235
-
236
-    /**
237
-     * Stores the block plugins stack during template runtime.
238
-     *
239
-     * @var array
240
-     */
241
-    protected $stack;
242
-
243
-    /**
244
-     * Stores the current block plugin at the top of the stack during template runtime.
245
-     *
246
-     * @var BlockPlugin
247
-     */
248
-    protected $curBlock;
249
-
250
-    /**
251
-     * Stores the output buffer during template runtime.
252
-     *
253
-     * @var string
254
-     */
255
-    protected $buffer;
256
-
257
-    /**
258
-     * Stores plugin proxy.
259
-     *
260
-     * @var IPluginProxy
261
-     */
262
-    protected $pluginProxy;
263
-
264
-    /**
265
-     * Constructor, sets the cache and compile dir to the default values if not provided.
266
-     *
267
-     * @param string $compileDir path to the compiled directory, defaults to lib/compiled
268
-     * @param string $cacheDir   path to the cache directory, defaults to lib/cache
269
-     */
270
-    public function __construct($compileDir = null, $cacheDir = null)
271
-    {
272
-        if ($compileDir !== null) {
273
-            $this->setCompileDir($compileDir);
274
-        }
275
-        if ($cacheDir !== null) {
276
-            $this->setCacheDir($cacheDir);
277
-        }
278
-        $this->initGlobals();
279
-    }
280
-
281
-    /**
282
-     * Resets some runtime variables to allow a cloned object to be used to render sub-templates.
283
-     *
284
-     * @return void
285
-     */
286
-    public function __clone()
287
-    {
288
-        $this->template = null;
289
-        unset($this->data);
290
-        unset($this->returnData);
291
-    }
292
-
293
-    /**
294
-     * Returns the given template rendered using the provided data and optional compiler.
295
-     *
296
-     * @param mixed     $_tpl      template, can either be a ITemplate object (i.e. TemplateFile), a
297
-     *                             valid path to a template, or a template as a string it is recommended to
298
-     *                             provide a ITemplate as it will probably make things faster, especially if
299
-     *                             you render a template multiple times
300
-     * @param mixed     $data      the data to use, can either be a IDataProvider object (i.e. Data) or
301
-     *                             an associative array. if you're rendering the template from cache, it can be
302
-     *                             left null
303
-     * @param ICompiler $_compiler the compiler that must be used to compile the template, if left empty a default
304
-     *                             Compiler will be used
305
-     *
306
-     * @return string|void or the template output if $output is false
307
-     * @throws Exception
308
-     */
309
-    public function get($_tpl, $data = array(), $_compiler = null)
310
-    {
311
-        // a render call came from within a template, so we need a new dwoo instance in order to avoid breaking this one
312
-        if ($this->template instanceof ITemplate) {
313
-            $clone = clone $this;
314
-
315
-            return $clone->get($_tpl, $data, $_compiler);
316
-        }
317
-
318
-        // auto-create template if required
319
-        if ($_tpl instanceof ITemplate) {
320
-            // valid, skip
321
-        } elseif (is_string($_tpl) && file_exists($_tpl)) {
322
-            $_tpl = new TemplateFile($_tpl);
323
-        } else {
324
-            throw new Exception(
325
-                '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.0';
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 = 130;
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
+	public $globals;
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
+	 * Defines how long (in seconds) the cached files must remain valid.
135
+	 * can be overriden on a per-template basis
136
+	 * -1 = never delete
137
+	 * 0 = disabled
138
+	 * >0 = duration in seconds
139
+	 *
140
+	 * @var int
141
+	 */
142
+	protected $cacheTime = 0;
143
+
144
+	/**
145
+	 * Security policy object.
146
+	 *
147
+	 * @var SecurityPolicy
148
+	 */
149
+	protected $securityPolicy = null;
150
+
151
+	/**
152
+	 * Stores the custom plugins callbacks.
153
+	 *
154
+	 * @see addPlugin
155
+	 * @see removePlugin
156
+	 * @var array
157
+	 */
158
+	protected $plugins = array();
159
+
160
+	/**
161
+	 * Stores the filter callbacks.
162
+	 *
163
+	 * @see addFilter
164
+	 * @see removeFilter
165
+	 * @var array
166
+	 */
167
+	protected $filters = array();
168
+
169
+	/**
170
+	 * Stores the resource types and associated
171
+	 * classes / compiler classes.
172
+	 *
173
+	 * @var array
174
+	 */
175
+	protected $resources = array(
176
+		'file'   => array(
177
+			'class'    => 'Dwoo\Template\File',
178
+			'compiler' => null,
179
+		),
180
+		'string' => array(
181
+			'class'    => 'Dwoo\Template\String',
182
+			'compiler' => null,
183
+		),
184
+	);
185
+
186
+	/**
187
+	 * The dwoo loader object used to load plugins by this dwoo instance.
188
+	 *
189
+	 * @var ILoader
190
+	 */
191
+	protected $loader = null;
192
+
193
+	/**
194
+	 * Currently rendered template, set to null when not-rendering.
195
+	 *
196
+	 * @var ITemplate
197
+	 */
198
+	protected $template = null;
199
+
200
+	/**
201
+	 * Stores the instances of the class plugins during template runtime.
202
+	 *
203
+	 * @var array
204
+	 */
205
+	protected $runtimePlugins;
206
+
207
+	/**
208
+	 * Stores the returned values during template runtime.
209
+	 *
210
+	 * @var array
211
+	 */
212
+	protected $returnData;
213
+
214
+	/**
215
+	 * Stores the data during template runtime.
216
+	 *
217
+	 * @var array
218
+	 */
219
+	public $data;
220
+
221
+	/**
222
+	 * Stores the current scope during template runtime.
223
+	 * this should ideally not be accessed directly from outside template code
224
+	 *
225
+	 * @var mixed
226
+	 */
227
+	public $scope;
228
+
229
+	/**
230
+	 * Stores the scope tree during template runtime.
231
+	 *
232
+	 * @var array
233
+	 */
234
+	protected $scopeTree;
235
+
236
+	/**
237
+	 * Stores the block plugins stack during template runtime.
238
+	 *
239
+	 * @var array
240
+	 */
241
+	protected $stack;
242
+
243
+	/**
244
+	 * Stores the current block plugin at the top of the stack during template runtime.
245
+	 *
246
+	 * @var BlockPlugin
247
+	 */
248
+	protected $curBlock;
249
+
250
+	/**
251
+	 * Stores the output buffer during template runtime.
252
+	 *
253
+	 * @var string
254
+	 */
255
+	protected $buffer;
256
+
257
+	/**
258
+	 * Stores plugin proxy.
259
+	 *
260
+	 * @var IPluginProxy
261
+	 */
262
+	protected $pluginProxy;
263
+
264
+	/**
265
+	 * Constructor, sets the cache and compile dir to the default values if not provided.
266
+	 *
267
+	 * @param string $compileDir path to the compiled directory, defaults to lib/compiled
268
+	 * @param string $cacheDir   path to the cache directory, defaults to lib/cache
269
+	 */
270
+	public function __construct($compileDir = null, $cacheDir = null)
271
+	{
272
+		if ($compileDir !== null) {
273
+			$this->setCompileDir($compileDir);
274
+		}
275
+		if ($cacheDir !== null) {
276
+			$this->setCacheDir($cacheDir);
277
+		}
278
+		$this->initGlobals();
279
+	}
280
+
281
+	/**
282
+	 * Resets some runtime variables to allow a cloned object to be used to render sub-templates.
283
+	 *
284
+	 * @return void
285
+	 */
286
+	public function __clone()
287
+	{
288
+		$this->template = null;
289
+		unset($this->data);
290
+		unset($this->returnData);
291
+	}
292
+
293
+	/**
294
+	 * Returns the given template rendered using the provided data and optional compiler.
295
+	 *
296
+	 * @param mixed     $_tpl      template, can either be a ITemplate object (i.e. TemplateFile), a
297
+	 *                             valid path to a template, or a template as a string it is recommended to
298
+	 *                             provide a ITemplate as it will probably make things faster, especially if
299
+	 *                             you render a template multiple times
300
+	 * @param mixed     $data      the data to use, can either be a IDataProvider object (i.e. Data) or
301
+	 *                             an associative array. if you're rendering the template from cache, it can be
302
+	 *                             left null
303
+	 * @param ICompiler $_compiler the compiler that must be used to compile the template, if left empty a default
304
+	 *                             Compiler will be used
305
+	 *
306
+	 * @return string|void or the template output if $output is false
307
+	 * @throws Exception
308
+	 */
309
+	public function get($_tpl, $data = array(), $_compiler = null)
310
+	{
311
+		// a render call came from within a template, so we need a new dwoo instance in order to avoid breaking this one
312
+		if ($this->template instanceof ITemplate) {
313
+			$clone = clone $this;
314
+
315
+			return $clone->get($_tpl, $data, $_compiler);
316
+		}
317
+
318
+		// auto-create template if required
319
+		if ($_tpl instanceof ITemplate) {
320
+			// valid, skip
321
+		} elseif (is_string($_tpl) && file_exists($_tpl)) {
322
+			$_tpl = new TemplateFile($_tpl);
323
+		} else {
324
+			throw new Exception(
325
+				'Dwoo->get\'s first argument must be a ITemplate (i.e. TemplateFile) or 
326 326
             a valid path to a template file', E_USER_NOTICE
327
-            );
328
-        }
329
-
330
-        // save the current template, enters render mode at the same time
331
-        // if another rendering is requested it will be proxied to a new Core(instance
332
-        $this->template = $_tpl;
333
-
334
-        // load data
335
-        if ($data instanceof IDataProvider) {
336
-            $this->data = $data->getData();
337
-        } elseif (is_array($data)) {
338
-            $this->data = $data;
339
-        } elseif ($data instanceof ArrayAccess) {
340
-            $this->data = $data;
341
-        } else {
342
-            throw new Exception(
343
-                'Dwoo->get/Dwoo->output\'s data argument must be a IDataProvider object (i.e. Data) or
327
+			);
328
+		}
329
+
330
+		// save the current template, enters render mode at the same time
331
+		// if another rendering is requested it will be proxied to a new Core(instance
332
+		$this->template = $_tpl;
333
+
334
+		// load data
335
+		if ($data instanceof IDataProvider) {
336
+			$this->data = $data->getData();
337
+		} elseif (is_array($data)) {
338
+			$this->data = $data;
339
+		} elseif ($data instanceof ArrayAccess) {
340
+			$this->data = $data;
341
+		} else {
342
+			throw new Exception(
343
+				'Dwoo->get/Dwoo->output\'s data argument must be a IDataProvider object (i.e. Data) or
344 344
             an associative array', E_USER_NOTICE
345
-            );
346
-        }
347
-
348
-        $this->globals['template'] = $_tpl->getName();
349
-        $this->initRuntimeVars($_tpl);
350
-
351
-        // try to get cached template
352
-        $file        = $_tpl->getCachedTemplate($this);
353
-        $doCache     = $file === true;
354
-        $cacheLoaded = is_string($file);
355
-
356
-        if ($cacheLoaded === true) {
357
-            // cache is present, run it
358
-            ob_start();
359
-            include $file;
360
-            $this->template = null;
361
-
362
-            return ob_get_clean();
363
-        } else {
364
-            $dynamicId = uniqid();
365
-
366
-            // render template
367
-            $compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
368
-            $out              = include $compiledTemplate;
369
-
370
-            // template returned false so it needs to be recompiled
371
-            if ($out === false) {
372
-                $_tpl->forceCompilation();
373
-                $compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
374
-                $out              = include $compiledTemplate;
375
-            }
376
-
377
-            if ($doCache === true) {
378
-                $out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*' . $dynamicId . '*/ echo \'$1\'; ?>', $out);
379
-                if (!class_exists(self::NAMESPACE_PLUGINS_BLOCKS . 'PluginDynamic')) {
380
-                    $this->getLoader()->loadPlugin('PluginDynamic');
381
-                }
382
-                $out = PluginDynamic::unescape($out, $dynamicId, $compiledTemplate);
383
-            }
384
-
385
-            // process filters
386
-            foreach ($this->filters as $filter) {
387
-                if (is_array($filter) && $filter[0] instanceof Filter) {
388
-                    $out = call_user_func($filter, $out);
389
-                } else {
390
-                    $out = call_user_func($filter, $this, $out);
391
-                }
392
-            }
393
-
394
-            if ($doCache === true) {
395
-                // building cache
396
-                $file = $_tpl->cache($this, $out);
397
-
398
-                // run it from the cache to be sure dynamics are rendered
399
-                ob_start();
400
-                include $file;
401
-                // exit render mode
402
-                $this->template = null;
403
-
404
-                return ob_get_clean();
405
-            } else {
406
-                // no need to build cache
407
-                // exit render mode
408
-                $this->template = null;
409
-
410
-                return $out;
411
-            }
412
-        }
413
-    }
414
-
415
-    /**
416
-     * Re-initializes the globals array before each template run.
417
-     * this method is only callede once when the Dwoo object is created
418
-     *
419
-     * @return void
420
-     */
421
-    protected function initGlobals()
422
-    {
423
-        $this->globals = array(
424
-            'version' => self::VERSION,
425
-            'ad'      => '<a href="http://dwoo.org/">Powered by Dwoo</a>',
426
-            'now'     => $_SERVER['REQUEST_TIME'],
427
-            'charset' => $this->charset,
428
-        );
429
-    }
430
-
431
-    /**
432
-     * Re-initializes the runtime variables before each template run.
433
-     * override this method to inject data in the globals array if needed, this
434
-     * method is called before each template execution
435
-     *
436
-     * @param ITemplate $tpl the template that is going to be rendered
437
-     *
438
-     * @return void
439
-     */
440
-    protected function initRuntimeVars(ITemplate $tpl)
441
-    {
442
-        $this->runtimePlugins = array();
443
-        $this->scope          = &$this->data;
444
-        $this->scopeTree      = array();
445
-        $this->stack          = array();
446
-        $this->curBlock       = null;
447
-        $this->buffer         = '';
448
-        $this->returnData     = array();
449
-    }
450
-
451
-    /**
452
-     * Adds a custom plugin that is not in one of the plugin directories.
453
-     *
454
-     * @param string   $name       the plugin name to be used in the templates
455
-     * @param callback $callback   the plugin callback, either a function name,
456
-     *                             a class name or an array containing an object
457
-     *                             or class name and a method name
458
-     * @param bool     $compilable if set to true, the plugin is assumed to be compilable
459
-     *
460
-     * @return void
461
-     * @throws Exception
462
-     */
463
-    public function addPlugin($name, $callback, $compilable = false)
464
-    {
465
-        $compilable = $compilable ? self::COMPILABLE_PLUGIN : 0;
466
-        if (is_array($callback)) {
467
-            if (is_subclass_of(is_object($callback[0]) ? get_class($callback[0]) : $callback[0], 'Dwoo\Block\Plugin')) {
468
-                $this->plugins[$name] = array(
469
-                    'type'     => self::BLOCK_PLUGIN | $compilable,
470
-                    'callback' => $callback,
471
-                    'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0])
472
-                );
473
-            } else {
474
-                $this->plugins[$name] = array(
475
-                    'type'     => self::CLASS_PLUGIN | $compilable,
476
-                    'callback' => $callback,
477
-                    'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]),
478
-                    'function' => $callback[1]
479
-                );
480
-            }
481
-        } elseif (is_string($callback)) {
482
-            if (class_exists($callback)) {
483
-                if (is_subclass_of($callback, 'Dwoo\Block\Plugin')) {
484
-                    $this->plugins[$name] = array(
485
-                        'type'     => self::BLOCK_PLUGIN | $compilable,
486
-                        'callback' => $callback,
487
-                        'class'    => $callback
488
-                    );
489
-                } else {
490
-                    $this->plugins[$name] = array(
491
-                        'type'     => self::CLASS_PLUGIN | $compilable,
492
-                        'callback' => $callback,
493
-                        'class'    => $callback,
494
-                        'function' => ($compilable ? 'compile' : 'process')
495
-                    );
496
-                }
497
-            } elseif (function_exists($callback)) {
498
-                $this->plugins[$name] = array(
499
-                    'type'     => self::FUNC_PLUGIN | $compilable,
500
-                    'callback' => $callback
501
-                );
502
-            } else {
503
-                throw new Exception(
504
-                    'Callback could not be processed correctly, please check that the function/class 
345
+			);
346
+		}
347
+
348
+		$this->globals['template'] = $_tpl->getName();
349
+		$this->initRuntimeVars($_tpl);
350
+
351
+		// try to get cached template
352
+		$file        = $_tpl->getCachedTemplate($this);
353
+		$doCache     = $file === true;
354
+		$cacheLoaded = is_string($file);
355
+
356
+		if ($cacheLoaded === true) {
357
+			// cache is present, run it
358
+			ob_start();
359
+			include $file;
360
+			$this->template = null;
361
+
362
+			return ob_get_clean();
363
+		} else {
364
+			$dynamicId = uniqid();
365
+
366
+			// render template
367
+			$compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
368
+			$out              = include $compiledTemplate;
369
+
370
+			// template returned false so it needs to be recompiled
371
+			if ($out === false) {
372
+				$_tpl->forceCompilation();
373
+				$compiledTemplate = $_tpl->getCompiledTemplate($this, $_compiler);
374
+				$out              = include $compiledTemplate;
375
+			}
376
+
377
+			if ($doCache === true) {
378
+				$out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*' . $dynamicId . '*/ echo \'$1\'; ?>', $out);
379
+				if (!class_exists(self::NAMESPACE_PLUGINS_BLOCKS . 'PluginDynamic')) {
380
+					$this->getLoader()->loadPlugin('PluginDynamic');
381
+				}
382
+				$out = PluginDynamic::unescape($out, $dynamicId, $compiledTemplate);
383
+			}
384
+
385
+			// process filters
386
+			foreach ($this->filters as $filter) {
387
+				if (is_array($filter) && $filter[0] instanceof Filter) {
388
+					$out = call_user_func($filter, $out);
389
+				} else {
390
+					$out = call_user_func($filter, $this, $out);
391
+				}
392
+			}
393
+
394
+			if ($doCache === true) {
395
+				// building cache
396
+				$file = $_tpl->cache($this, $out);
397
+
398
+				// run it from the cache to be sure dynamics are rendered
399
+				ob_start();
400
+				include $file;
401
+				// exit render mode
402
+				$this->template = null;
403
+
404
+				return ob_get_clean();
405
+			} else {
406
+				// no need to build cache
407
+				// exit render mode
408
+				$this->template = null;
409
+
410
+				return $out;
411
+			}
412
+		}
413
+	}
414
+
415
+	/**
416
+	 * Re-initializes the globals array before each template run.
417
+	 * this method is only callede once when the Dwoo object is created
418
+	 *
419
+	 * @return void
420
+	 */
421
+	protected function initGlobals()
422
+	{
423
+		$this->globals = array(
424
+			'version' => self::VERSION,
425
+			'ad'      => '<a href="http://dwoo.org/">Powered by Dwoo</a>',
426
+			'now'     => $_SERVER['REQUEST_TIME'],
427
+			'charset' => $this->charset,
428
+		);
429
+	}
430
+
431
+	/**
432
+	 * Re-initializes the runtime variables before each template run.
433
+	 * override this method to inject data in the globals array if needed, this
434
+	 * method is called before each template execution
435
+	 *
436
+	 * @param ITemplate $tpl the template that is going to be rendered
437
+	 *
438
+	 * @return void
439
+	 */
440
+	protected function initRuntimeVars(ITemplate $tpl)
441
+	{
442
+		$this->runtimePlugins = array();
443
+		$this->scope          = &$this->data;
444
+		$this->scopeTree      = array();
445
+		$this->stack          = array();
446
+		$this->curBlock       = null;
447
+		$this->buffer         = '';
448
+		$this->returnData     = array();
449
+	}
450
+
451
+	/**
452
+	 * Adds a custom plugin that is not in one of the plugin directories.
453
+	 *
454
+	 * @param string   $name       the plugin name to be used in the templates
455
+	 * @param callback $callback   the plugin callback, either a function name,
456
+	 *                             a class name or an array containing an object
457
+	 *                             or class name and a method name
458
+	 * @param bool     $compilable if set to true, the plugin is assumed to be compilable
459
+	 *
460
+	 * @return void
461
+	 * @throws Exception
462
+	 */
463
+	public function addPlugin($name, $callback, $compilable = false)
464
+	{
465
+		$compilable = $compilable ? self::COMPILABLE_PLUGIN : 0;
466
+		if (is_array($callback)) {
467
+			if (is_subclass_of(is_object($callback[0]) ? get_class($callback[0]) : $callback[0], 'Dwoo\Block\Plugin')) {
468
+				$this->plugins[$name] = array(
469
+					'type'     => self::BLOCK_PLUGIN | $compilable,
470
+					'callback' => $callback,
471
+					'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0])
472
+				);
473
+			} else {
474
+				$this->plugins[$name] = array(
475
+					'type'     => self::CLASS_PLUGIN | $compilable,
476
+					'callback' => $callback,
477
+					'class'    => (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]),
478
+					'function' => $callback[1]
479
+				);
480
+			}
481
+		} elseif (is_string($callback)) {
482
+			if (class_exists($callback)) {
483
+				if (is_subclass_of($callback, 'Dwoo\Block\Plugin')) {
484
+					$this->plugins[$name] = array(
485
+						'type'     => self::BLOCK_PLUGIN | $compilable,
486
+						'callback' => $callback,
487
+						'class'    => $callback
488
+					);
489
+				} else {
490
+					$this->plugins[$name] = array(
491
+						'type'     => self::CLASS_PLUGIN | $compilable,
492
+						'callback' => $callback,
493
+						'class'    => $callback,
494
+						'function' => ($compilable ? 'compile' : 'process')
495
+					);
496
+				}
497
+			} elseif (function_exists($callback)) {
498
+				$this->plugins[$name] = array(
499
+					'type'     => self::FUNC_PLUGIN | $compilable,
500
+					'callback' => $callback
501
+				);
502
+			} else {
503
+				throw new Exception(
504
+					'Callback could not be processed correctly, please check that the function/class 
505 505
                 you used exists'
506
-                );
507
-            }
508
-        } elseif ($callback instanceof Closure) {
509
-            $this->plugins[$name] = array(
510
-                'type'     => self::FUNC_PLUGIN | $compilable,
511
-                'callback' => $callback
512
-            );
513
-        } else {
514
-            throw new Exception(
515
-                'Callback could not be processed correctly, please check that the function/class you 
506
+				);
507
+			}
508
+		} elseif ($callback instanceof Closure) {
509
+			$this->plugins[$name] = array(
510
+				'type'     => self::FUNC_PLUGIN | $compilable,
511
+				'callback' => $callback
512
+			);
513
+		} else {
514
+			throw new Exception(
515
+				'Callback could not be processed correctly, please check that the function/class you 
516 516
             used exists'
517
-            );
518
-        }
519
-    }
520
-
521
-    /**
522
-     * Removes a custom plugin.
523
-     *
524
-     * @param string $name the plugin name
525
-     *
526
-     * @return void
527
-     */
528
-    public function removePlugin($name)
529
-    {
530
-        if (isset($this->plugins[$name])) {
531
-            unset($this->plugins[$name]);
532
-        }
533
-    }
534
-
535
-    /**
536
-     * Adds a filter to this Dwoo instance, it will be used to filter the output of all the templates rendered by this
537
-     * instance.
538
-     *
539
-     * @param mixed $callback a callback or a filter name if it is autoloaded from a plugin directory
540
-     * @param bool  $autoload if true, the first parameter must be a filter name from one of the plugin directories
541
-     *
542
-     * @return void
543
-     * @throws Exception
544
-     */
545
-    public function addFilter($callback, $autoload = false)
546
-    {
547
-        if ($autoload) {
548
-            $class = self::NAMESPACE_PLUGINS_FILTERS . self::toCamelCase($callback);
549
-            if (!class_exists($class) && !function_exists($class)) {
550
-                try {
551
-                    $this->getLoader()->loadPlugin($callback);
552
-                }
553
-                catch (Exception $e) {
554
-                    if (strstr($callback, self::NAMESPACE_PLUGINS_FILTERS)) {
555
-                        throw new Exception(
556
-                            'Wrong filter name : ' . $callback . ', the "Dwoo_Filter_" prefix should 
517
+			);
518
+		}
519
+	}
520
+
521
+	/**
522
+	 * Removes a custom plugin.
523
+	 *
524
+	 * @param string $name the plugin name
525
+	 *
526
+	 * @return void
527
+	 */
528
+	public function removePlugin($name)
529
+	{
530
+		if (isset($this->plugins[$name])) {
531
+			unset($this->plugins[$name]);
532
+		}
533
+	}
534
+
535
+	/**
536
+	 * Adds a filter to this Dwoo instance, it will be used to filter the output of all the templates rendered by this
537
+	 * instance.
538
+	 *
539
+	 * @param mixed $callback a callback or a filter name if it is autoloaded from a plugin directory
540
+	 * @param bool  $autoload if true, the first parameter must be a filter name from one of the plugin directories
541
+	 *
542
+	 * @return void
543
+	 * @throws Exception
544
+	 */
545
+	public function addFilter($callback, $autoload = false)
546
+	{
547
+		if ($autoload) {
548
+			$class = self::NAMESPACE_PLUGINS_FILTERS . self::toCamelCase($callback);
549
+			if (!class_exists($class) && !function_exists($class)) {
550
+				try {
551
+					$this->getLoader()->loadPlugin($callback);
552
+				}
553
+				catch (Exception $e) {
554
+					if (strstr($callback, self::NAMESPACE_PLUGINS_FILTERS)) {
555
+						throw new Exception(
556
+							'Wrong filter name : ' . $callback . ', the "Dwoo_Filter_" prefix should 
557 557
                         not be used, please only use "' . str_replace('Dwoo_Filter_', '', $callback) . '"'
558
-                        );
559
-                    } else {
560
-                        throw new Exception(
561
-                            'Wrong filter name : ' . $callback . ', when using autoload the filter must
558
+						);
559
+					} else {
560
+						throw new Exception(
561
+							'Wrong filter name : ' . $callback . ', when using autoload the filter must
562 562
                          be in one of your plugin dir as "name.php" containig a class or function named
563 563
                          "Dwoo_Filter_name"'
564
-                        );
565
-                    }
566
-                }
567
-            }
568
-
569
-            if (class_exists($class)) {
570
-                $callback = array(new $class($this), 'process');
571
-            } elseif (function_exists($class)) {
572
-                $callback = $class;
573
-            } else {
574
-                throw new Exception(
575
-                    'Wrong filter name : ' . $callback . ', when using autoload the filter must be in
564
+						);
565
+					}
566
+				}
567
+			}
568
+
569
+			if (class_exists($class)) {
570
+				$callback = array(new $class($this), 'process');
571
+			} elseif (function_exists($class)) {
572
+				$callback = $class;
573
+			} else {
574
+				throw new Exception(
575
+					'Wrong filter name : ' . $callback . ', when using autoload the filter must be in
576 576
                 one of your plugin dir as "name.php" containig a class or function named "Dwoo_Filter_name"'
577
-                );
578
-            }
579
-
580
-            $this->filters[] = $callback;
581
-        } else {
582
-            $this->filters[] = $callback;
583
-        }
584
-    }
585
-
586
-    /**
587
-     * Removes a filter.
588
-     *
589
-     * @param mixed $callback callback or filter name if it was autoloaded
590
-     *
591
-     * @return void
592
-     */
593
-    public function removeFilter($callback)
594
-    {
595
-        if (($index = array_search(self::NAMESPACE_PLUGINS_FILTERS. 'Filter' . self::toCamelCase($callback), $this->filters,
596
-                true)) !==
597
-            false) {
598
-            unset($this->filters[$index]);
599
-        } elseif (($index = array_search($callback, $this->filters, true)) !== false) {
600
-            unset($this->filters[$index]);
601
-        } else {
602
-            $class = self::NAMESPACE_PLUGINS_FILTERS . 'Filter' . $callback;
603
-            foreach ($this->filters as $index => $filter) {
604
-                if (is_array($filter) && $filter[0] instanceof $class) {
605
-                    unset($this->filters[$index]);
606
-                    break;
607
-                }
608
-            }
609
-        }
610
-    }
611
-
612
-    /**
613
-     * Adds a resource or overrides a default one.
614
-     *
615
-     * @param string   $name            the resource name
616
-     * @param string   $class           the resource class (which must implement ITemplate)
617
-     * @param callback $compilerFactory the compiler factory callback, a function that must return a compiler instance
618
-     *                                  used to compile this resource, if none is provided. by default it will produce
619
-     *                                  a Compiler object
620
-     *
621
-     * @return void
622
-     * @throws Exception
623
-     */
624
-    public function addResource($name, $class, $compilerFactory = null)
625
-    {
626
-        if (strlen($name) < 2) {
627
-            throw new Exception('Resource names must be at least two-character long to avoid conflicts with Windows paths');
628
-        }
629
-
630
-        if (!class_exists($class)) {
631
-            throw new Exception('Resource class does not exist');
632
-        }
633
-
634
-        $interfaces = class_implements($class);
635
-        if (in_array('Dwoo\ITemplate', $interfaces) === false) {
636
-            throw new Exception('Resource class must implement ITemplate');
637
-        }
638
-
639
-        $this->resources[$name] = array(
640
-            'class'    => $class,
641
-            'compiler' => $compilerFactory
642
-        );
643
-    }
644
-
645
-    /**
646
-     * Removes a custom resource.
647
-     *
648
-     * @param string $name the resource name
649
-     *
650
-     * @return void
651
-     */
652
-    public function removeResource($name)
653
-    {
654
-        unset($this->resources[$name]);
655
-        if ($name === 'file') {
656
-            $this->resources['file'] = array(
657
-                'class'    => 'Dwoo\Template\File',
658
-                'compiler' => null
659
-            );
660
-        }
661
-    }
662
-
663
-    /**
664
-     * Sets the loader object to use to load plugins.
665
-     *
666
-     * @param ILoader $loader loader
667
-     *
668
-     * @return void
669
-     */
670
-    public function setLoader(ILoader $loader)
671
-    {
672
-        $this->loader = $loader;
673
-    }
674
-
675
-    /**
676
-     * Returns the current loader object or a default one if none is currently found.
677
-     *
678
-     * @return ILoader|Loader
679
-     */
680
-    public function getLoader()
681
-    {
682
-        if ($this->loader === null) {
683
-            $this->loader = new Loader($this->getCompileDir());
684
-        }
685
-
686
-        return $this->loader;
687
-    }
688
-
689
-    /**
690
-     * Returns the custom plugins loaded.
691
-     * Used by the ITemplate classes to pass the custom plugins to their ICompiler instance.
692
-     *
693
-     * @return array
694
-     */
695
-    public function getCustomPlugins()
696
-    {
697
-        return $this->plugins;
698
-    }
699
-
700
-    /**
701
-     * Return a specified custom plugin loaded by his name.
702
-     * Used by the compiler, for executing a Closure.
703
-     *
704
-     * @param string $name
705
-     *
706
-     * @return mixed|null
707
-     */
708
-    public function getCustomPlugin($name)
709
-    {
710
-        if (isset($this->plugins[$name])) {
711
-            return $this->plugins[$name]['callback'];
712
-        }
713
-
714
-        return null;
715
-    }
716
-
717
-    /**
718
-     * Returns the cache directory with a trailing DIRECTORY_SEPARATOR.
719
-     *
720
-     * @return string
721
-     */
722
-    public function getCacheDir()
723
-    {
724
-        if ($this->cacheDir === null) {
725
-            $this->setCacheDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR);
726
-        }
727
-
728
-        return $this->cacheDir;
729
-    }
730
-
731
-    /**
732
-     * Sets the cache directory and automatically appends a DIRECTORY_SEPARATOR.
733
-     *
734
-     * @param string $dir the cache directory
735
-     *
736
-     * @return void
737
-     * @throws Exception
738
-     */
739
-    public function setCacheDir($dir)
740
-    {
741
-        $this->cacheDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
742
-        if (is_writable($this->cacheDir) === false) {
743
-            throw new Exception('The cache directory must be writable, chmod "' . $this->cacheDir . '" to make it writable');
744
-        }
745
-    }
746
-
747
-    /**
748
-     * Returns the compile directory with a trailing DIRECTORY_SEPARATOR.
749
-     *
750
-     * @return string
751
-     */
752
-    public function getCompileDir()
753
-    {
754
-        if ($this->compileDir === null) {
755
-            $this->setCompileDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR);
756
-        }
757
-
758
-        return $this->compileDir;
759
-    }
760
-
761
-    /**
762
-     * Sets the compile directory and automatically appends a DIRECTORY_SEPARATOR.
763
-     *
764
-     * @param string $dir the compile directory
765
-     *
766
-     * @return void
767
-     * @throws Exception
768
-     */
769
-    public function setCompileDir($dir)
770
-    {
771
-        $this->compileDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
772
-        if (is_writable($this->compileDir) === false) {
773
-            throw new Exception('The compile directory must be writable, chmod "' . $this->compileDir . '" to make it writable');
774
-        }
775
-    }
776
-
777
-    /**
778
-     * Returns the default cache time that is used with templates that do not have a cache time set.
779
-     *
780
-     * @return int the duration in seconds
781
-     */
782
-    public function getCacheTime()
783
-    {
784
-        return $this->cacheTime;
785
-    }
786
-
787
-    /**
788
-     * Sets the default cache time to use with templates that do not have a cache time set.
789
-     *
790
-     * @param int $seconds the duration in seconds
791
-     *
792
-     * @return void
793
-     */
794
-    public function setCacheTime($seconds)
795
-    {
796
-        $this->cacheTime = (int)$seconds;
797
-    }
798
-
799
-    /**
800
-     * Returns the character set used by the string manipulation plugins.
801
-     * the charset is automatically lowercased
802
-     *
803
-     * @return string
804
-     */
805
-    public function getCharset()
806
-    {
807
-        return $this->charset;
808
-    }
809
-
810
-    /**
811
-     * Sets the character set used by the string manipulation plugins.
812
-     * the charset will be automatically lowercased
813
-     *
814
-     * @param string $charset the character set
815
-     *
816
-     * @return void
817
-     */
818
-    public function setCharset($charset)
819
-    {
820
-        $this->charset = strtolower((string)$charset);
821
-    }
822
-
823
-    /**
824
-     * Returns the current template being rendered, when applicable, or null.
825
-     *
826
-     * @return ITemplate|null
827
-     */
828
-    public function getTemplate()
829
-    {
830
-        return $this->template;
831
-    }
832
-
833
-    /**
834
-     * Sets the current template being rendered.
835
-     *
836
-     * @param ITemplate $tpl template object
837
-     *
838
-     * @return void
839
-     */
840
-    public function setTemplate(ITemplate $tpl)
841
-    {
842
-        $this->template = $tpl;
843
-    }
844
-
845
-    /**
846
-     * Sets the default compiler factory function for the given resource name.
847
-     * a compiler factory must return a ICompiler object pre-configured to fit your needs
848
-     *
849
-     * @param string   $resourceName    the resource name (i.e. file, string)
850
-     * @param callback $compilerFactory the compiler factory callback
851
-     *
852
-     * @return void
853
-     */
854
-    public function setDefaultCompilerFactory($resourceName, $compilerFactory)
855
-    {
856
-        $this->resources[$resourceName]['compiler'] = $compilerFactory;
857
-    }
858
-
859
-    /**
860
-     * Returns the default compiler factory function for the given resource name.
861
-     *
862
-     * @param string $resourceName the resource name
863
-     *
864
-     * @return callback the compiler factory callback
865
-     */
866
-    public function getDefaultCompilerFactory($resourceName)
867
-    {
868
-        return $this->resources[$resourceName]['compiler'];
869
-    }
870
-
871
-    /**
872
-     * Sets the security policy object to enforce some php security settings.
873
-     * use this if untrusted persons can modify templates
874
-     *
875
-     * @param SecurityPolicy $policy the security policy object
876
-     *
877
-     * @return void
878
-     */
879
-    public function setSecurityPolicy(SecurityPolicy $policy = null)
880
-    {
881
-        $this->securityPolicy = $policy;
882
-    }
883
-
884
-    /**
885
-     * Returns the current security policy object or null by default.
886
-     *
887
-     * @return SecurityPolicy|null the security policy object if any
888
-     */
889
-    public function getSecurityPolicy()
890
-    {
891
-        return $this->securityPolicy;
892
-    }
893
-
894
-    /**
895
-     * Sets the object that must be used as a plugin proxy when plugin can't be found
896
-     * by dwoo's loader.
897
-     *
898
-     * @param IPluginProxy $pluginProxy the proxy object
899
-     *
900
-     * @return void
901
-     */
902
-    public function setPluginProxy(IPluginProxy $pluginProxy)
903
-    {
904
-        $this->pluginProxy = $pluginProxy;
905
-    }
906
-
907
-    /**
908
-     * Returns the current plugin proxy object or null by default.
909
-     *
910
-     * @return IPluginProxy
911
-     */
912
-    public function getPluginProxy()
913
-    {
914
-        return $this->pluginProxy;
915
-    }
916
-
917
-    /**
918
-     * Checks whether the given template is cached or not.
919
-     *
920
-     * @param ITemplate $tpl the template object
921
-     *
922
-     * @return bool
923
-     */
924
-    public function isCached(ITemplate $tpl)
925
-    {
926
-        return is_string($tpl->getCachedTemplate($this));
927
-    }
928
-
929
-    /**
930
-     * Clear templates inside the compiled directory.
931
-     *
932
-     * @return int
933
-     */
934
-    public function clearCompiled()
935
-    {
936
-        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCompileDir()), \RecursiveIteratorIterator::SELF_FIRST);
937
-        $count    = 0;
938
-        foreach ($iterator as $file) {
939
-            if ($file->isFile()) {
940
-                $count += unlink($file->__toString()) ? 1 : 0;
941
-            }
942
-        }
943
-
944
-        return $count;
945
-    }
946
-
947
-    /**
948
-     * Clears the cached templates if they are older than the given time.
949
-     *
950
-     * @param int $olderThan minimum time (in seconds) required for a cached template to be cleared
951
-     *
952
-     * @return int the amount of templates cleared
953
-     */
954
-    public function clearCache($olderThan = - 1)
955
-    {
956
-        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCacheDir()), \RecursiveIteratorIterator::SELF_FIRST);
957
-        $expired  = time() - $olderThan;
958
-        $count    = 0;
959
-        foreach ($iterator as $file) {
960
-            if ($file->isFile() && $file->getCTime() < $expired) {
961
-                $count += unlink((string)$file) ? 1 : 0;
962
-            }
963
-        }
964
-
965
-        return $count;
966
-    }
967
-
968
-    /**
969
-     * Fetches a template object of the given resource.
970
-     *
971
-     * @param string    $resourceName   the resource name (i.e. file, string)
972
-     * @param string    $resourceId     the resource identifier (i.e. file path)
973
-     * @param int       $cacheTime      the cache time setting for this resource
974
-     * @param string    $cacheId        the unique cache identifier
975
-     * @param string    $compileId      the unique compiler identifier
976
-     * @param ITemplate $parentTemplate the parent template
977
-     *
978
-     * @return ITemplate
979
-     * @throws Exception
980
-     */
981
-    public function templateFactory($resourceName, $resourceId, $cacheTime = null, $cacheId = null, $compileId = null, ITemplate $parentTemplate = null)
982
-    {
983
-        if (isset($this->resources[$resourceName])) {
984
-            /**
985
-             * Interface ITemplate
986
-             *
987
-             * @var ITemplate $class
988
-             */
989
-            $class = $this->resources[$resourceName]['class'];
990
-
991
-            return $class::templateFactory($this, $resourceId, $cacheTime, $cacheId, $compileId, $parentTemplate);
992
-        }
993
-
994
-        throw new Exception('Unknown resource type : ' . $resourceName);
995
-    }
996
-
997
-    /**
998
-     * Checks if the input is an array or arrayaccess object, optionally it can also check if it's
999
-     * empty.
1000
-     *
1001
-     * @param mixed $value        the variable to check
1002
-     * @param bool  $checkIsEmpty if true, the function will also check if the array|arrayaccess is empty,
1003
-     *                            and return true only if it's not empty
1004
-     *
1005
-     * @return int|bool true if it's an array|arrayaccess (or the item count if $checkIsEmpty is true) or false if it's
1006
-     *                  not an array|arrayaccess (or 0 if $checkIsEmpty is true)
1007
-     */
1008
-    public function isArray($value, $checkIsEmpty = false)
1009
-    {
1010
-        if (is_array($value) === true || $value instanceof ArrayAccess) {
1011
-            if ($checkIsEmpty === false) {
1012
-                return true;
1013
-            }
1014
-
1015
-            return $this->count($value);
1016
-        }
1017
-
1018
-        return false;
1019
-    }
1020
-
1021
-    /**
1022
-     * Checks if the input is an array or a traversable object, optionally it can also check if it's
1023
-     * empty.
1024
-     *
1025
-     * @param mixed $value        the variable to check
1026
-     * @param bool  $checkIsEmpty if true, the function will also check if the array|traversable is empty,
1027
-     *                            and return true only if it's not empty
1028
-     *
1029
-     * @return int|bool true if it's an array|traversable (or the item count if $checkIsEmpty is true) or false if it's
1030
-     *                  not an array|traversable (or 0 if $checkIsEmpty is true)
1031
-     */
1032
-    public function isTraversable($value, $checkIsEmpty = false)
1033
-    {
1034
-        if (is_array($value) === true) {
1035
-            if ($checkIsEmpty === false) {
1036
-                return true;
1037
-            } else {
1038
-                return count($value) > 0;
1039
-            }
1040
-        } elseif ($value instanceof Traversable) {
1041
-            if ($checkIsEmpty === false) {
1042
-                return true;
1043
-            } else {
1044
-                return $this->count($value);
1045
-            }
1046
-        }
1047
-
1048
-        return false;
1049
-    }
1050
-
1051
-    /**
1052
-     * Counts an array or arrayaccess/traversable object.
1053
-     *
1054
-     * @param mixed $value the value to count
1055
-     *
1056
-     * @return int|bool the count for arrays and objects that implement countable, true for other objects that don't,
1057
-     *                  and 0 for empty elements
1058
-     */
1059
-    public function count($value)
1060
-    {
1061
-        if (is_array($value) === true || $value instanceof Countable) {
1062
-            return count($value);
1063
-        } elseif ($value instanceof ArrayAccess) {
1064
-            if ($value->offsetExists(0)) {
1065
-                return true;
1066
-            }
1067
-        } elseif ($value instanceof Iterator) {
1068
-            $value->rewind();
1069
-            if ($value->valid()) {
1070
-                return true;
1071
-            }
1072
-        } elseif ($value instanceof Traversable) {
1073
-            foreach ($value as $dummy) {
1074
-                return true;
1075
-            }
1076
-        }
1077
-
1078
-        return 0;
1079
-    }
1080
-
1081
-    /**
1082
-     * Triggers a dwoo error.
1083
-     *
1084
-     * @param string $message the error message
1085
-     * @param int    $level   the error level, one of the PHP's E_* constants
1086
-     *
1087
-     * @return void
1088
-     */
1089
-    public function triggerError($message, $level = E_USER_NOTICE)
1090
-    {
1091
-        if (!($tplIdentifier = $this->template->getResourceIdentifier())) {
1092
-            $tplIdentifier = $this->template->getResourceName();
1093
-        }
1094
-        trigger_error('Dwoo error (in ' . $tplIdentifier . ') : ' . $message, $level);
1095
-    }
1096
-
1097
-    /**
1098
-     * Adds a block to the block stack.
1099
-     *
1100
-     * @param string $blockName the block name (without Dwoo_Plugin_ prefix)
1101
-     * @param array  $args      the arguments to be passed to the block's init() function
1102
-     *
1103
-     * @return BlockPlugin the newly created block
1104
-     */
1105
-    public function addStack($blockName, array $args = array())
1106
-    {
1107
-        if (isset($this->plugins[$blockName])) {
1108
-            $class = $this->plugins[$blockName]['class'];
1109
-        } else {
1110
-            $class = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . self::toCamelCase($blockName);
1111
-        }
1112
-
1113
-        if ($this->curBlock !== null) {
1114
-            $this->curBlock->buffer(ob_get_contents());
1115
-            ob_clean();
1116
-        } else {
1117
-            $this->buffer .= ob_get_contents();
1118
-            ob_clean();
1119
-        }
1120
-
1121
-        $block = new $class($this);
1122
-
1123
-        call_user_func_array(array($block, 'init'), $args);
1124
-
1125
-        $this->stack[] = $this->curBlock = $block;
1126
-
1127
-        return $block;
1128
-    }
1129
-
1130
-    /**
1131
-     * Removes the plugin at the top of the block stack.
1132
-     * Calls the block buffer() function, followed by a call to end() and finally a call to process()
1133
-     *
1134
-     * @return void
1135
-     */
1136
-    public function delStack()
1137
-    {
1138
-        $args = func_get_args();
1139
-
1140
-        $this->curBlock->buffer(ob_get_contents());
1141
-        ob_clean();
1142
-
1143
-        call_user_func_array(array($this->curBlock, 'end'), $args);
1144
-
1145
-        $tmp = array_pop($this->stack);
1146
-
1147
-        if (count($this->stack) > 0) {
1148
-            $this->curBlock = end($this->stack);
1149
-            $this->curBlock->buffer($tmp->process());
1150
-        } else {
1151
-            if ($this->buffer !== '') {
1152
-                echo $this->buffer;
1153
-                $this->buffer = '';
1154
-            }
1155
-            $this->curBlock = null;
1156
-            echo $tmp->process();
1157
-        }
1158
-
1159
-        unset($tmp);
1160
-    }
1161
-
1162
-    /**
1163
-     * Returns the parent block of the given block.
1164
-     *
1165
-     * @param BlockPlugin $block the block class plugin
1166
-     *
1167
-     * @return BlockPlugin|false if the given block isn't in the stack
1168
-     */
1169
-    public function getParentBlock(BlockPlugin $block)
1170
-    {
1171
-        $index = array_search($block, $this->stack, true);
1172
-        if ($index !== false && $index > 0) {
1173
-            return $this->stack[$index - 1];
1174
-        }
1175
-
1176
-        return false;
1177
-    }
1178
-
1179
-    /**
1180
-     * Finds the closest block of the given type, starting at the top of the stack.
1181
-     *
1182
-     * @param string $type the type of plugin you want to find
1183
-     *
1184
-     * @return BlockPlugin|false if no plugin of such type is in the stack
1185
-     */
1186
-    public function findBlock($type)
1187
-    {
1188
-        if (isset($this->plugins[$type])) {
1189
-            $type = $this->plugins[$type]['class'];
1190
-        } else {
1191
-            $type = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin_' . str_replace(self::NAMESPACE_PLUGINS_BLOCKS.'Plugin',
1192
-                    '', $type);
1193
-        }
1194
-
1195
-        $keys = array_keys($this->stack);
1196
-        while (($key = array_pop($keys)) !== false) {
1197
-            if ($this->stack[$key] instanceof $type) {
1198
-                return $this->stack[$key];
1199
-            }
1200
-        }
1201
-
1202
-        return false;
1203
-    }
1204
-
1205
-    /**
1206
-     * Returns a Plugin of the given class.
1207
-     * this is so a single instance of every class plugin is created at each template run,
1208
-     * allowing class plugins to have "per-template-run" static variables
1209
-     *
1210
-     * @param string $class the class name
1211
-     *
1212
-     * @return mixed an object of the given class
1213
-     */
1214
-    public function getObjectPlugin($class)
1215
-    {
1216
-        if (isset($this->runtimePlugins[$class])) {
1217
-            return $this->runtimePlugins[$class];
1218
-        }
1219
-
1220
-        return $this->runtimePlugins[$class] = new $class($this);
1221
-    }
1222
-
1223
-    /**
1224
-     * Calls the process() method of the given class-plugin name.
1225
-     *
1226
-     * @param string $plugName the class plugin name (without Dwoo_Plugin_ prefix)
1227
-     * @param array  $params   an array of parameters to send to the process() method
1228
-     *
1229
-     * @return string the process() return value
1230
-     */
1231
-    public function classCall($plugName, array $params = array())
1232
-    {
1233
-        $class  = self::toCamelCase($plugName);
1234
-        $plugin = $this->getObjectPlugin($class);
1235
-
1236
-        return call_user_func_array(array($plugin, 'process'), $params);
1237
-    }
1238
-
1239
-    /**
1240
-     * Calls a php function.
1241
-     *
1242
-     * @param string $callback the function to call
1243
-     * @param array  $params   an array of parameters to send to the function
1244
-     *
1245
-     * @return mixed the return value of the called function
1246
-     */
1247
-    public function arrayMap($callback, array $params)
1248
-    {
1249
-        if ($params[0] === $this) {
1250
-            $addThis = true;
1251
-            array_shift($params);
1252
-        }
1253
-        if ((is_array($params[0]) || ($params[0] instanceof Iterator && $params[0] instanceof ArrayAccess))) {
1254
-            if (empty($params[0])) {
1255
-                return $params[0];
1256
-            }
1257
-
1258
-            // array map
1259
-            $out = array();
1260
-            $cnt = count($params);
1261
-
1262
-            if (isset($addThis)) {
1263
-                array_unshift($params, $this);
1264
-                $items = $params[1];
1265
-                $keys  = array_keys($items);
1266
-
1267
-                if (is_string($callback) === false) {
1268
-                    while (($i = array_shift($keys)) !== null) {
1269
-                        $out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1270
-                    }
1271
-                } elseif ($cnt === 1) {
1272
-                    while (($i = array_shift($keys)) !== null) {
1273
-                        $out[] = $callback($this, $items[$i]);
1274
-                    }
1275
-                } elseif ($cnt === 2) {
1276
-                    while (($i = array_shift($keys)) !== null) {
1277
-                        $out[] = $callback($this, $items[$i], $params[2]);
1278
-                    }
1279
-                } elseif ($cnt === 3) {
1280
-                    while (($i = array_shift($keys)) !== null) {
1281
-                        $out[] = $callback($this, $items[$i], $params[2], $params[3]);
1282
-                    }
1283
-                } else {
1284
-                    while (($i = array_shift($keys)) !== null) {
1285
-                        $out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1286
-                    }
1287
-                }
1288
-            } else {
1289
-                $items = $params[0];
1290
-                $keys  = array_keys($items);
1291
-
1292
-                if (is_string($callback) === false) {
1293
-                    while (($i = array_shift($keys)) !== null) {
1294
-                        $out[] = call_user_func_array($callback, array($items[$i]) + $params);
1295
-                    }
1296
-                } elseif ($cnt === 1) {
1297
-                    while (($i = array_shift($keys)) !== null) {
1298
-                        $out[] = $callback($items[$i]);
1299
-                    }
1300
-                } elseif ($cnt === 2) {
1301
-                    while (($i = array_shift($keys)) !== null) {
1302
-                        $out[] = $callback($items[$i], $params[1]);
1303
-                    }
1304
-                } elseif ($cnt === 3) {
1305
-                    while (($i = array_shift($keys)) !== null) {
1306
-                        $out[] = $callback($items[$i], $params[1], $params[2]);
1307
-                    }
1308
-                } elseif ($cnt === 4) {
1309
-                    while (($i = array_shift($keys)) !== null) {
1310
-                        $out[] = $callback($items[$i], $params[1], $params[2], $params[3]);
1311
-                    }
1312
-                } else {
1313
-                    while (($i = array_shift($keys)) !== null) {
1314
-                        $out[] = call_user_func_array($callback, array($items[$i]) + $params);
1315
-                    }
1316
-                }
1317
-            }
1318
-
1319
-            return $out;
1320
-        } else {
1321
-            return $params[0];
1322
-        }
1323
-    }
1324
-
1325
-    /**
1326
-     * Reads a variable into the given data array.
1327
-     *
1328
-     * @param string $varstr   the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1329
-     * @param mixed  $data     the data array or object to read from
1330
-     * @param bool   $safeRead if true, the function will check whether the index exists to prevent any notices from
1331
-     *                         being output
1332
-     *
1333
-     * @return mixed
1334
-     */
1335
-    public function readVarInto($varstr, $data, $safeRead = false)
1336
-    {
1337
-        if ($data === null) {
1338
-            return null;
1339
-        }
1340
-
1341
-        if (is_array($varstr) === false) {
1342
-            preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1343
-        } else {
1344
-            $m = $varstr;
1345
-        }
1346
-        unset($varstr);
1347
-
1348
-        while (list($k, $sep) = each($m[1])) {
1349
-            if ($sep === '.' || $sep === '[' || $sep === '') {
1350
-                // strip enclosing quotes if present
1351
-                $m[2][$k] = preg_replace('#^(["\']?)(.*?)\1$#', '$2', $m[2][$k]);
1352
-
1353
-                if ((is_array($data) || $data instanceof ArrayAccess) && ($safeRead === false || isset($data[$m[2][$k]]))) {
1354
-                    $data = $data[$m[2][$k]];
1355
-                } else {
1356
-                    return null;
1357
-                }
1358
-            } else {
1359
-                if (is_object($data) && ($safeRead === false || isset($data->$m[2][$k]))) {
1360
-                    $data = $data->$m[2][$k];
1361
-                } else {
1362
-                    return null;
1363
-                }
1364
-            }
1365
-        }
1366
-
1367
-        return $data;
1368
-    }
1369
-
1370
-    /**
1371
-     * Reads a variable into the parent scope.
1372
-     *
1373
-     * @param int    $parentLevels the amount of parent levels to go from the current scope
1374
-     * @param string $varstr       the variable string, using dwoo variable syntax (i.e.
1375
-     *                             "var.subvar[subsubvar]->property")
1376
-     *
1377
-     * @return mixed
1378
-     */
1379
-    public function readParentVar($parentLevels, $varstr = null)
1380
-    {
1381
-        $tree = $this->scopeTree;
1382
-        $cur  = $this->data;
1383
-
1384
-        while ($parentLevels -- !== 0) {
1385
-            array_pop($tree);
1386
-        }
1387
-
1388
-        while (($i = array_shift($tree)) !== null) {
1389
-            if (is_object($cur)) {
1390
-                $cur = $cur->$i;
1391
-            } else {
1392
-                $cur = $cur[$i];
1393
-            }
1394
-        }
1395
-
1396
-        if ($varstr !== null) {
1397
-            return $this->readVarInto($varstr, $cur);
1398
-        } else {
1399
-            return $cur;
1400
-        }
1401
-    }
1402
-
1403
-    /**
1404
-     * Reads a variable into the current scope.
1405
-     *
1406
-     * @param string $varstr the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1407
-     *
1408
-     * @return mixed
1409
-     */
1410
-    public function readVar($varstr)
1411
-    {
1412
-        if (is_array($varstr) === true) {
1413
-            $m = $varstr;
1414
-            unset($varstr);
1415
-        } else {
1416
-            if (strstr($varstr, '.') === false && strstr($varstr, '[') === false && strstr($varstr, '->') === false) {
1417
-                if ($varstr === 'dwoo') {
1418
-                    return $this->globals;
1419
-                } elseif ($varstr === '__' || $varstr === '_root') {
1420
-                    return $this->data;
1421
-                } elseif ($varstr === '_' || $varstr === '_parent') {
1422
-                    $varstr = '.' . $varstr;
1423
-                    $tree   = $this->scopeTree;
1424
-                    $cur    = $this->data;
1425
-                    array_pop($tree);
1426
-
1427
-                    while (($i = array_shift($tree)) !== null) {
1428
-                        if (is_object($cur)) {
1429
-                            $cur = $cur->$i;
1430
-                        } else {
1431
-                            $cur = $cur[$i];
1432
-                        }
1433
-                    }
1434
-
1435
-                    return $cur;
1436
-                }
1437
-
1438
-                $cur = $this->scope;
1439
-
1440
-                if (isset($cur[$varstr])) {
1441
-                    return $cur[$varstr];
1442
-                } else {
1443
-                    return null;
1444
-                }
1445
-            }
1446
-
1447
-            if (substr($varstr, 0, 1) === '.') {
1448
-                $varstr = 'dwoo' . $varstr;
1449
-            }
1450
-
1451
-            preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1452
-        }
1453
-
1454
-        $i = $m[2][0];
1455
-        if ($i === 'dwoo') {
1456
-            $cur = $this->globals;
1457
-            array_shift($m[2]);
1458
-            array_shift($m[1]);
1459
-            switch ($m[2][0]) {
1460
-            case 'get':
1461
-                $cur = $_GET;
1462
-                break;
1463
-            case 'post':
1464
-                $cur = $_POST;
1465
-                break;
1466
-            case 'session':
1467
-                $cur = $_SESSION;
1468
-                break;
1469
-            case 'cookies':
1470
-            case 'cookie':
1471
-                $cur = $_COOKIE;
1472
-                break;
1473
-            case 'server':
1474
-                $cur = $_SERVER;
1475
-                break;
1476
-            case 'env':
1477
-                $cur = $_ENV;
1478
-                break;
1479
-            case 'request':
1480
-                $cur = $_REQUEST;
1481
-                break;
1482
-            case 'const':
1483
-                array_shift($m[2]);
1484
-                if (defined($m[2][0])) {
1485
-                    return constant($m[2][0]);
1486
-                } else {
1487
-                    return null;
1488
-                }
1489
-            }
1490
-            if ($cur !== $this->globals) {
1491
-                array_shift($m[2]);
1492
-                array_shift($m[1]);
1493
-            }
1494
-        } elseif ($i === '__' || $i === '_root') {
1495
-            $cur = $this->data;
1496
-            array_shift($m[2]);
1497
-            array_shift($m[1]);
1498
-        } elseif ($i === '_' || $i === '_parent') {
1499
-            $tree = $this->scopeTree;
1500
-            $cur  = $this->data;
1501
-
1502
-            while (true) {
1503
-                array_pop($tree);
1504
-                array_shift($m[2]);
1505
-                array_shift($m[1]);
1506
-                if (current($m[2]) === '_' || current($m[2]) === '_parent') {
1507
-                    continue;
1508
-                }
1509
-
1510
-                while (($i = array_shift($tree)) !== null) {
1511
-                    if (is_object($cur)) {
1512
-                        $cur = $cur->$i;
1513
-                    } else {
1514
-                        $cur = $cur[$i];
1515
-                    }
1516
-                }
1517
-                break;
1518
-            }
1519
-        } else {
1520
-            $cur = $this->scope;
1521
-        }
1522
-
1523
-        while (list($k, $sep) = each($m[1])) {
1524
-            if ($sep === '.' || $sep === '[' || $sep === '') {
1525
-                if ((is_array($cur) || $cur instanceof ArrayAccess) && isset($cur[$m[2][$k]])) {
1526
-                    $cur = $cur[$m[2][$k]];
1527
-                } else {
1528
-                    return null;
1529
-                }
1530
-            } elseif ($sep === '->') {
1531
-                if (is_object($cur)) {
1532
-                    $cur = $cur->$m[2][$k];
1533
-                } else {
1534
-                    return null;
1535
-                }
1536
-            } else {
1537
-                return null;
1538
-            }
1539
-        }
1540
-
1541
-        return $cur;
1542
-    }
1543
-
1544
-    /**
1545
-     * Assign the value to the given variable.
1546
-     *
1547
-     * @param mixed  $value the value to assign
1548
-     * @param string $scope the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1549
-     *
1550
-     * @return bool true if assigned correctly or false if a problem occured while parsing the var string
1551
-     */
1552
-    public function assignInScope($value, $scope)
1553
-    {
1554
-        if (!is_string($scope)) {
1555
-            $this->triggerError('Assignments must be done into strings, (' . gettype($scope) . ') ' . var_export($scope, true) . ' given', E_USER_ERROR);
1556
-        }
1557
-        if (strstr($scope, '.') === false && strstr($scope, '->') === false) {
1558
-            $this->scope[$scope] = $value;
1559
-        } else {
1560
-            // TODO handle _root/_parent scopes ?
1561
-            preg_match_all('#(\[|->|\.)?([^.[\]-]+)\]?#i', $scope, $m);
1562
-
1563
-            $cur  = &$this->scope;
1564
-            $last = array(
1565
-                array_pop($m[1]),
1566
-                array_pop($m[2])
1567
-            );
1568
-
1569
-            while (list($k, $sep) = each($m[1])) {
1570
-                if ($sep === '.' || $sep === '[' || $sep === '') {
1571
-                    if (is_array($cur) === false) {
1572
-                        $cur = array();
1573
-                    }
1574
-                    $cur = &$cur[$m[2][$k]];
1575
-                } elseif ($sep === '->') {
1576
-                    if (is_object($cur) === false) {
1577
-                        $cur = new stdClass();
1578
-                    }
1579
-                    $cur = &$cur->$m[2][$k];
1580
-                } else {
1581
-                    return false;
1582
-                }
1583
-            }
1584
-
1585
-            if ($last[0] === '.' || $last[0] === '[' || $last[0] === '') {
1586
-                if (is_array($cur) === false) {
1587
-                    $cur = array();
1588
-                }
1589
-                $cur[$last[1]] = $value;
1590
-            } elseif ($last[0] === '->') {
1591
-                if (is_object($cur) === false) {
1592
-                    $cur = new stdClass();
1593
-                }
1594
-                $cur->$last[1] = $value;
1595
-            } else {
1596
-                return false;
1597
-            }
1598
-        }
1599
-    }
1600
-
1601
-    /**
1602
-     * Sets the scope to the given scope string or array.
1603
-     *
1604
-     * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1605
-     * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1606
-     *
1607
-     * @return array the current scope tree
1608
-     */
1609
-    public function setScope($scope, $absolute = false)
1610
-    {
1611
-        $old = $this->scopeTree;
1612
-
1613
-        if (is_string($scope) === true) {
1614
-            $scope = explode('.', $scope);
1615
-        }
1616
-
1617
-        if ($absolute === true) {
1618
-            $this->scope     = &$this->data;
1619
-            $this->scopeTree = array();
1620
-        }
1621
-
1622
-        while (($bit = array_shift($scope)) !== null) {
1623
-            if ($bit === '_' || $bit === '_parent') {
1624
-                array_pop($this->scopeTree);
1625
-                $this->scope = &$this->data;
1626
-                $cnt         = count($this->scopeTree);
1627
-                for ($i = 0; $i < $cnt; ++ $i) {
1628
-                    $this->scope = &$this->scope[$this->scopeTree[$i]];
1629
-                }
1630
-            } elseif ($bit === '__' || $bit === '_root') {
1631
-                $this->scope     = &$this->data;
1632
-                $this->scopeTree = array();
1633
-            } elseif (isset($this->scope[$bit])) {
1634
-                if ($this->scope instanceof ArrayAccess) {
1635
-                    $tmp         = $this->scope[$bit];
1636
-                    $this->scope = &$tmp;
1637
-                } else {
1638
-                    $this->scope = &$this->scope[$bit];
1639
-                }
1640
-                $this->scopeTree[] = $bit;
1641
-            } else {
1642
-                unset($this->scope);
1643
-                $this->scope = null;
1644
-            }
1645
-        }
1646
-
1647
-        return $old;
1648
-    }
1649
-
1650
-    /**
1651
-     * Returns the entire data array.
1652
-     *
1653
-     * @return array
1654
-     */
1655
-    public function getData()
1656
-    {
1657
-        return $this->data;
1658
-    }
1659
-
1660
-    /**
1661
-     * Sets a return value for the currently running template.
1662
-     *
1663
-     * @param string $name  var name
1664
-     * @param mixed  $value var value
1665
-     *
1666
-     * @return void
1667
-     */
1668
-    public function setReturnValue($name, $value)
1669
-    {
1670
-        $this->returnData[$name] = $value;
1671
-    }
1672
-
1673
-    /**
1674
-     * Retrieves the return values set by the template.
1675
-     *
1676
-     * @return array
1677
-     */
1678
-    public function getReturnValues()
1679
-    {
1680
-        return $this->returnData;
1681
-    }
1682
-
1683
-    /**
1684
-     * Returns a reference to the current scope.
1685
-     *
1686
-     * @return mixed
1687
-     */
1688
-    public function &getScope()
1689
-    {
1690
-        return $this->scope;
1691
-    }
1692
-
1693
-    /**
1694
-     * Redirects all calls to unexisting to plugin proxy.
1695
-     *
1696
-     * @param string $method the method name
1697
-     * @param array  $args   array of arguments
1698
-     *
1699
-     * @return mixed
1700
-     * @throws Exception
1701
-     */
1702
-    public function __call($method, $args)
1703
-    {
1704
-        $proxy = $this->getPluginProxy();
1705
-        if (!$proxy) {
1706
-            throw new Exception('Call to undefined method ' . __CLASS__ . '::' . $method . '()');
1707
-        }
1708
-
1709
-        return call_user_func_array($proxy->getCallback($method), $args);
1710
-    }
1711
-
1712
-    /**
1713
-     * Convert plugin name from `auto_escape` to `AutoEscape`.
1714
-     * @param string $input
1715
-     * @param string $separator
1716
-     *
1717
-     * @return mixed
1718
-     */
1719
-    public static function toCamelCase($input, $separator = '_')
1720
-    {
1721
-        return join(array_map('ucfirst', explode($separator, $input)));
1722
-
1723
-        // TODO >= PHP5.4.32
1724
-        //return str_replace($separator, '', ucwords($input, $separator));
1725
-    }
577
+				);
578
+			}
579
+
580
+			$this->filters[] = $callback;
581
+		} else {
582
+			$this->filters[] = $callback;
583
+		}
584
+	}
585
+
586
+	/**
587
+	 * Removes a filter.
588
+	 *
589
+	 * @param mixed $callback callback or filter name if it was autoloaded
590
+	 *
591
+	 * @return void
592
+	 */
593
+	public function removeFilter($callback)
594
+	{
595
+		if (($index = array_search(self::NAMESPACE_PLUGINS_FILTERS. 'Filter' . self::toCamelCase($callback), $this->filters,
596
+				true)) !==
597
+			false) {
598
+			unset($this->filters[$index]);
599
+		} elseif (($index = array_search($callback, $this->filters, true)) !== false) {
600
+			unset($this->filters[$index]);
601
+		} else {
602
+			$class = self::NAMESPACE_PLUGINS_FILTERS . 'Filter' . $callback;
603
+			foreach ($this->filters as $index => $filter) {
604
+				if (is_array($filter) && $filter[0] instanceof $class) {
605
+					unset($this->filters[$index]);
606
+					break;
607
+				}
608
+			}
609
+		}
610
+	}
611
+
612
+	/**
613
+	 * Adds a resource or overrides a default one.
614
+	 *
615
+	 * @param string   $name            the resource name
616
+	 * @param string   $class           the resource class (which must implement ITemplate)
617
+	 * @param callback $compilerFactory the compiler factory callback, a function that must return a compiler instance
618
+	 *                                  used to compile this resource, if none is provided. by default it will produce
619
+	 *                                  a Compiler object
620
+	 *
621
+	 * @return void
622
+	 * @throws Exception
623
+	 */
624
+	public function addResource($name, $class, $compilerFactory = null)
625
+	{
626
+		if (strlen($name) < 2) {
627
+			throw new Exception('Resource names must be at least two-character long to avoid conflicts with Windows paths');
628
+		}
629
+
630
+		if (!class_exists($class)) {
631
+			throw new Exception('Resource class does not exist');
632
+		}
633
+
634
+		$interfaces = class_implements($class);
635
+		if (in_array('Dwoo\ITemplate', $interfaces) === false) {
636
+			throw new Exception('Resource class must implement ITemplate');
637
+		}
638
+
639
+		$this->resources[$name] = array(
640
+			'class'    => $class,
641
+			'compiler' => $compilerFactory
642
+		);
643
+	}
644
+
645
+	/**
646
+	 * Removes a custom resource.
647
+	 *
648
+	 * @param string $name the resource name
649
+	 *
650
+	 * @return void
651
+	 */
652
+	public function removeResource($name)
653
+	{
654
+		unset($this->resources[$name]);
655
+		if ($name === 'file') {
656
+			$this->resources['file'] = array(
657
+				'class'    => 'Dwoo\Template\File',
658
+				'compiler' => null
659
+			);
660
+		}
661
+	}
662
+
663
+	/**
664
+	 * Sets the loader object to use to load plugins.
665
+	 *
666
+	 * @param ILoader $loader loader
667
+	 *
668
+	 * @return void
669
+	 */
670
+	public function setLoader(ILoader $loader)
671
+	{
672
+		$this->loader = $loader;
673
+	}
674
+
675
+	/**
676
+	 * Returns the current loader object or a default one if none is currently found.
677
+	 *
678
+	 * @return ILoader|Loader
679
+	 */
680
+	public function getLoader()
681
+	{
682
+		if ($this->loader === null) {
683
+			$this->loader = new Loader($this->getCompileDir());
684
+		}
685
+
686
+		return $this->loader;
687
+	}
688
+
689
+	/**
690
+	 * Returns the custom plugins loaded.
691
+	 * Used by the ITemplate classes to pass the custom plugins to their ICompiler instance.
692
+	 *
693
+	 * @return array
694
+	 */
695
+	public function getCustomPlugins()
696
+	{
697
+		return $this->plugins;
698
+	}
699
+
700
+	/**
701
+	 * Return a specified custom plugin loaded by his name.
702
+	 * Used by the compiler, for executing a Closure.
703
+	 *
704
+	 * @param string $name
705
+	 *
706
+	 * @return mixed|null
707
+	 */
708
+	public function getCustomPlugin($name)
709
+	{
710
+		if (isset($this->plugins[$name])) {
711
+			return $this->plugins[$name]['callback'];
712
+		}
713
+
714
+		return null;
715
+	}
716
+
717
+	/**
718
+	 * Returns the cache directory with a trailing DIRECTORY_SEPARATOR.
719
+	 *
720
+	 * @return string
721
+	 */
722
+	public function getCacheDir()
723
+	{
724
+		if ($this->cacheDir === null) {
725
+			$this->setCacheDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR);
726
+		}
727
+
728
+		return $this->cacheDir;
729
+	}
730
+
731
+	/**
732
+	 * Sets the cache directory and automatically appends a DIRECTORY_SEPARATOR.
733
+	 *
734
+	 * @param string $dir the cache directory
735
+	 *
736
+	 * @return void
737
+	 * @throws Exception
738
+	 */
739
+	public function setCacheDir($dir)
740
+	{
741
+		$this->cacheDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
742
+		if (is_writable($this->cacheDir) === false) {
743
+			throw new Exception('The cache directory must be writable, chmod "' . $this->cacheDir . '" to make it writable');
744
+		}
745
+	}
746
+
747
+	/**
748
+	 * Returns the compile directory with a trailing DIRECTORY_SEPARATOR.
749
+	 *
750
+	 * @return string
751
+	 */
752
+	public function getCompileDir()
753
+	{
754
+		if ($this->compileDir === null) {
755
+			$this->setCompileDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR);
756
+		}
757
+
758
+		return $this->compileDir;
759
+	}
760
+
761
+	/**
762
+	 * Sets the compile directory and automatically appends a DIRECTORY_SEPARATOR.
763
+	 *
764
+	 * @param string $dir the compile directory
765
+	 *
766
+	 * @return void
767
+	 * @throws Exception
768
+	 */
769
+	public function setCompileDir($dir)
770
+	{
771
+		$this->compileDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
772
+		if (is_writable($this->compileDir) === false) {
773
+			throw new Exception('The compile directory must be writable, chmod "' . $this->compileDir . '" to make it writable');
774
+		}
775
+	}
776
+
777
+	/**
778
+	 * Returns the default cache time that is used with templates that do not have a cache time set.
779
+	 *
780
+	 * @return int the duration in seconds
781
+	 */
782
+	public function getCacheTime()
783
+	{
784
+		return $this->cacheTime;
785
+	}
786
+
787
+	/**
788
+	 * Sets the default cache time to use with templates that do not have a cache time set.
789
+	 *
790
+	 * @param int $seconds the duration in seconds
791
+	 *
792
+	 * @return void
793
+	 */
794
+	public function setCacheTime($seconds)
795
+	{
796
+		$this->cacheTime = (int)$seconds;
797
+	}
798
+
799
+	/**
800
+	 * Returns the character set used by the string manipulation plugins.
801
+	 * the charset is automatically lowercased
802
+	 *
803
+	 * @return string
804
+	 */
805
+	public function getCharset()
806
+	{
807
+		return $this->charset;
808
+	}
809
+
810
+	/**
811
+	 * Sets the character set used by the string manipulation plugins.
812
+	 * the charset will be automatically lowercased
813
+	 *
814
+	 * @param string $charset the character set
815
+	 *
816
+	 * @return void
817
+	 */
818
+	public function setCharset($charset)
819
+	{
820
+		$this->charset = strtolower((string)$charset);
821
+	}
822
+
823
+	/**
824
+	 * Returns the current template being rendered, when applicable, or null.
825
+	 *
826
+	 * @return ITemplate|null
827
+	 */
828
+	public function getTemplate()
829
+	{
830
+		return $this->template;
831
+	}
832
+
833
+	/**
834
+	 * Sets the current template being rendered.
835
+	 *
836
+	 * @param ITemplate $tpl template object
837
+	 *
838
+	 * @return void
839
+	 */
840
+	public function setTemplate(ITemplate $tpl)
841
+	{
842
+		$this->template = $tpl;
843
+	}
844
+
845
+	/**
846
+	 * Sets the default compiler factory function for the given resource name.
847
+	 * a compiler factory must return a ICompiler object pre-configured to fit your needs
848
+	 *
849
+	 * @param string   $resourceName    the resource name (i.e. file, string)
850
+	 * @param callback $compilerFactory the compiler factory callback
851
+	 *
852
+	 * @return void
853
+	 */
854
+	public function setDefaultCompilerFactory($resourceName, $compilerFactory)
855
+	{
856
+		$this->resources[$resourceName]['compiler'] = $compilerFactory;
857
+	}
858
+
859
+	/**
860
+	 * Returns the default compiler factory function for the given resource name.
861
+	 *
862
+	 * @param string $resourceName the resource name
863
+	 *
864
+	 * @return callback the compiler factory callback
865
+	 */
866
+	public function getDefaultCompilerFactory($resourceName)
867
+	{
868
+		return $this->resources[$resourceName]['compiler'];
869
+	}
870
+
871
+	/**
872
+	 * Sets the security policy object to enforce some php security settings.
873
+	 * use this if untrusted persons can modify templates
874
+	 *
875
+	 * @param SecurityPolicy $policy the security policy object
876
+	 *
877
+	 * @return void
878
+	 */
879
+	public function setSecurityPolicy(SecurityPolicy $policy = null)
880
+	{
881
+		$this->securityPolicy = $policy;
882
+	}
883
+
884
+	/**
885
+	 * Returns the current security policy object or null by default.
886
+	 *
887
+	 * @return SecurityPolicy|null the security policy object if any
888
+	 */
889
+	public function getSecurityPolicy()
890
+	{
891
+		return $this->securityPolicy;
892
+	}
893
+
894
+	/**
895
+	 * Sets the object that must be used as a plugin proxy when plugin can't be found
896
+	 * by dwoo's loader.
897
+	 *
898
+	 * @param IPluginProxy $pluginProxy the proxy object
899
+	 *
900
+	 * @return void
901
+	 */
902
+	public function setPluginProxy(IPluginProxy $pluginProxy)
903
+	{
904
+		$this->pluginProxy = $pluginProxy;
905
+	}
906
+
907
+	/**
908
+	 * Returns the current plugin proxy object or null by default.
909
+	 *
910
+	 * @return IPluginProxy
911
+	 */
912
+	public function getPluginProxy()
913
+	{
914
+		return $this->pluginProxy;
915
+	}
916
+
917
+	/**
918
+	 * Checks whether the given template is cached or not.
919
+	 *
920
+	 * @param ITemplate $tpl the template object
921
+	 *
922
+	 * @return bool
923
+	 */
924
+	public function isCached(ITemplate $tpl)
925
+	{
926
+		return is_string($tpl->getCachedTemplate($this));
927
+	}
928
+
929
+	/**
930
+	 * Clear templates inside the compiled directory.
931
+	 *
932
+	 * @return int
933
+	 */
934
+	public function clearCompiled()
935
+	{
936
+		$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCompileDir()), \RecursiveIteratorIterator::SELF_FIRST);
937
+		$count    = 0;
938
+		foreach ($iterator as $file) {
939
+			if ($file->isFile()) {
940
+				$count += unlink($file->__toString()) ? 1 : 0;
941
+			}
942
+		}
943
+
944
+		return $count;
945
+	}
946
+
947
+	/**
948
+	 * Clears the cached templates if they are older than the given time.
949
+	 *
950
+	 * @param int $olderThan minimum time (in seconds) required for a cached template to be cleared
951
+	 *
952
+	 * @return int the amount of templates cleared
953
+	 */
954
+	public function clearCache($olderThan = - 1)
955
+	{
956
+		$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCacheDir()), \RecursiveIteratorIterator::SELF_FIRST);
957
+		$expired  = time() - $olderThan;
958
+		$count    = 0;
959
+		foreach ($iterator as $file) {
960
+			if ($file->isFile() && $file->getCTime() < $expired) {
961
+				$count += unlink((string)$file) ? 1 : 0;
962
+			}
963
+		}
964
+
965
+		return $count;
966
+	}
967
+
968
+	/**
969
+	 * Fetches a template object of the given resource.
970
+	 *
971
+	 * @param string    $resourceName   the resource name (i.e. file, string)
972
+	 * @param string    $resourceId     the resource identifier (i.e. file path)
973
+	 * @param int       $cacheTime      the cache time setting for this resource
974
+	 * @param string    $cacheId        the unique cache identifier
975
+	 * @param string    $compileId      the unique compiler identifier
976
+	 * @param ITemplate $parentTemplate the parent template
977
+	 *
978
+	 * @return ITemplate
979
+	 * @throws Exception
980
+	 */
981
+	public function templateFactory($resourceName, $resourceId, $cacheTime = null, $cacheId = null, $compileId = null, ITemplate $parentTemplate = null)
982
+	{
983
+		if (isset($this->resources[$resourceName])) {
984
+			/**
985
+			 * Interface ITemplate
986
+			 *
987
+			 * @var ITemplate $class
988
+			 */
989
+			$class = $this->resources[$resourceName]['class'];
990
+
991
+			return $class::templateFactory($this, $resourceId, $cacheTime, $cacheId, $compileId, $parentTemplate);
992
+		}
993
+
994
+		throw new Exception('Unknown resource type : ' . $resourceName);
995
+	}
996
+
997
+	/**
998
+	 * Checks if the input is an array or arrayaccess object, optionally it can also check if it's
999
+	 * empty.
1000
+	 *
1001
+	 * @param mixed $value        the variable to check
1002
+	 * @param bool  $checkIsEmpty if true, the function will also check if the array|arrayaccess is empty,
1003
+	 *                            and return true only if it's not empty
1004
+	 *
1005
+	 * @return int|bool true if it's an array|arrayaccess (or the item count if $checkIsEmpty is true) or false if it's
1006
+	 *                  not an array|arrayaccess (or 0 if $checkIsEmpty is true)
1007
+	 */
1008
+	public function isArray($value, $checkIsEmpty = false)
1009
+	{
1010
+		if (is_array($value) === true || $value instanceof ArrayAccess) {
1011
+			if ($checkIsEmpty === false) {
1012
+				return true;
1013
+			}
1014
+
1015
+			return $this->count($value);
1016
+		}
1017
+
1018
+		return false;
1019
+	}
1020
+
1021
+	/**
1022
+	 * Checks if the input is an array or a traversable object, optionally it can also check if it's
1023
+	 * empty.
1024
+	 *
1025
+	 * @param mixed $value        the variable to check
1026
+	 * @param bool  $checkIsEmpty if true, the function will also check if the array|traversable is empty,
1027
+	 *                            and return true only if it's not empty
1028
+	 *
1029
+	 * @return int|bool true if it's an array|traversable (or the item count if $checkIsEmpty is true) or false if it's
1030
+	 *                  not an array|traversable (or 0 if $checkIsEmpty is true)
1031
+	 */
1032
+	public function isTraversable($value, $checkIsEmpty = false)
1033
+	{
1034
+		if (is_array($value) === true) {
1035
+			if ($checkIsEmpty === false) {
1036
+				return true;
1037
+			} else {
1038
+				return count($value) > 0;
1039
+			}
1040
+		} elseif ($value instanceof Traversable) {
1041
+			if ($checkIsEmpty === false) {
1042
+				return true;
1043
+			} else {
1044
+				return $this->count($value);
1045
+			}
1046
+		}
1047
+
1048
+		return false;
1049
+	}
1050
+
1051
+	/**
1052
+	 * Counts an array or arrayaccess/traversable object.
1053
+	 *
1054
+	 * @param mixed $value the value to count
1055
+	 *
1056
+	 * @return int|bool the count for arrays and objects that implement countable, true for other objects that don't,
1057
+	 *                  and 0 for empty elements
1058
+	 */
1059
+	public function count($value)
1060
+	{
1061
+		if (is_array($value) === true || $value instanceof Countable) {
1062
+			return count($value);
1063
+		} elseif ($value instanceof ArrayAccess) {
1064
+			if ($value->offsetExists(0)) {
1065
+				return true;
1066
+			}
1067
+		} elseif ($value instanceof Iterator) {
1068
+			$value->rewind();
1069
+			if ($value->valid()) {
1070
+				return true;
1071
+			}
1072
+		} elseif ($value instanceof Traversable) {
1073
+			foreach ($value as $dummy) {
1074
+				return true;
1075
+			}
1076
+		}
1077
+
1078
+		return 0;
1079
+	}
1080
+
1081
+	/**
1082
+	 * Triggers a dwoo error.
1083
+	 *
1084
+	 * @param string $message the error message
1085
+	 * @param int    $level   the error level, one of the PHP's E_* constants
1086
+	 *
1087
+	 * @return void
1088
+	 */
1089
+	public function triggerError($message, $level = E_USER_NOTICE)
1090
+	{
1091
+		if (!($tplIdentifier = $this->template->getResourceIdentifier())) {
1092
+			$tplIdentifier = $this->template->getResourceName();
1093
+		}
1094
+		trigger_error('Dwoo error (in ' . $tplIdentifier . ') : ' . $message, $level);
1095
+	}
1096
+
1097
+	/**
1098
+	 * Adds a block to the block stack.
1099
+	 *
1100
+	 * @param string $blockName the block name (without Dwoo_Plugin_ prefix)
1101
+	 * @param array  $args      the arguments to be passed to the block's init() function
1102
+	 *
1103
+	 * @return BlockPlugin the newly created block
1104
+	 */
1105
+	public function addStack($blockName, array $args = array())
1106
+	{
1107
+		if (isset($this->plugins[$blockName])) {
1108
+			$class = $this->plugins[$blockName]['class'];
1109
+		} else {
1110
+			$class = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . self::toCamelCase($blockName);
1111
+		}
1112
+
1113
+		if ($this->curBlock !== null) {
1114
+			$this->curBlock->buffer(ob_get_contents());
1115
+			ob_clean();
1116
+		} else {
1117
+			$this->buffer .= ob_get_contents();
1118
+			ob_clean();
1119
+		}
1120
+
1121
+		$block = new $class($this);
1122
+
1123
+		call_user_func_array(array($block, 'init'), $args);
1124
+
1125
+		$this->stack[] = $this->curBlock = $block;
1126
+
1127
+		return $block;
1128
+	}
1129
+
1130
+	/**
1131
+	 * Removes the plugin at the top of the block stack.
1132
+	 * Calls the block buffer() function, followed by a call to end() and finally a call to process()
1133
+	 *
1134
+	 * @return void
1135
+	 */
1136
+	public function delStack()
1137
+	{
1138
+		$args = func_get_args();
1139
+
1140
+		$this->curBlock->buffer(ob_get_contents());
1141
+		ob_clean();
1142
+
1143
+		call_user_func_array(array($this->curBlock, 'end'), $args);
1144
+
1145
+		$tmp = array_pop($this->stack);
1146
+
1147
+		if (count($this->stack) > 0) {
1148
+			$this->curBlock = end($this->stack);
1149
+			$this->curBlock->buffer($tmp->process());
1150
+		} else {
1151
+			if ($this->buffer !== '') {
1152
+				echo $this->buffer;
1153
+				$this->buffer = '';
1154
+			}
1155
+			$this->curBlock = null;
1156
+			echo $tmp->process();
1157
+		}
1158
+
1159
+		unset($tmp);
1160
+	}
1161
+
1162
+	/**
1163
+	 * Returns the parent block of the given block.
1164
+	 *
1165
+	 * @param BlockPlugin $block the block class plugin
1166
+	 *
1167
+	 * @return BlockPlugin|false if the given block isn't in the stack
1168
+	 */
1169
+	public function getParentBlock(BlockPlugin $block)
1170
+	{
1171
+		$index = array_search($block, $this->stack, true);
1172
+		if ($index !== false && $index > 0) {
1173
+			return $this->stack[$index - 1];
1174
+		}
1175
+
1176
+		return false;
1177
+	}
1178
+
1179
+	/**
1180
+	 * Finds the closest block of the given type, starting at the top of the stack.
1181
+	 *
1182
+	 * @param string $type the type of plugin you want to find
1183
+	 *
1184
+	 * @return BlockPlugin|false if no plugin of such type is in the stack
1185
+	 */
1186
+	public function findBlock($type)
1187
+	{
1188
+		if (isset($this->plugins[$type])) {
1189
+			$type = $this->plugins[$type]['class'];
1190
+		} else {
1191
+			$type = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin_' . str_replace(self::NAMESPACE_PLUGINS_BLOCKS.'Plugin',
1192
+					'', $type);
1193
+		}
1194
+
1195
+		$keys = array_keys($this->stack);
1196
+		while (($key = array_pop($keys)) !== false) {
1197
+			if ($this->stack[$key] instanceof $type) {
1198
+				return $this->stack[$key];
1199
+			}
1200
+		}
1201
+
1202
+		return false;
1203
+	}
1204
+
1205
+	/**
1206
+	 * Returns a Plugin of the given class.
1207
+	 * this is so a single instance of every class plugin is created at each template run,
1208
+	 * allowing class plugins to have "per-template-run" static variables
1209
+	 *
1210
+	 * @param string $class the class name
1211
+	 *
1212
+	 * @return mixed an object of the given class
1213
+	 */
1214
+	public function getObjectPlugin($class)
1215
+	{
1216
+		if (isset($this->runtimePlugins[$class])) {
1217
+			return $this->runtimePlugins[$class];
1218
+		}
1219
+
1220
+		return $this->runtimePlugins[$class] = new $class($this);
1221
+	}
1222
+
1223
+	/**
1224
+	 * Calls the process() method of the given class-plugin name.
1225
+	 *
1226
+	 * @param string $plugName the class plugin name (without Dwoo_Plugin_ prefix)
1227
+	 * @param array  $params   an array of parameters to send to the process() method
1228
+	 *
1229
+	 * @return string the process() return value
1230
+	 */
1231
+	public function classCall($plugName, array $params = array())
1232
+	{
1233
+		$class  = self::toCamelCase($plugName);
1234
+		$plugin = $this->getObjectPlugin($class);
1235
+
1236
+		return call_user_func_array(array($plugin, 'process'), $params);
1237
+	}
1238
+
1239
+	/**
1240
+	 * Calls a php function.
1241
+	 *
1242
+	 * @param string $callback the function to call
1243
+	 * @param array  $params   an array of parameters to send to the function
1244
+	 *
1245
+	 * @return mixed the return value of the called function
1246
+	 */
1247
+	public function arrayMap($callback, array $params)
1248
+	{
1249
+		if ($params[0] === $this) {
1250
+			$addThis = true;
1251
+			array_shift($params);
1252
+		}
1253
+		if ((is_array($params[0]) || ($params[0] instanceof Iterator && $params[0] instanceof ArrayAccess))) {
1254
+			if (empty($params[0])) {
1255
+				return $params[0];
1256
+			}
1257
+
1258
+			// array map
1259
+			$out = array();
1260
+			$cnt = count($params);
1261
+
1262
+			if (isset($addThis)) {
1263
+				array_unshift($params, $this);
1264
+				$items = $params[1];
1265
+				$keys  = array_keys($items);
1266
+
1267
+				if (is_string($callback) === false) {
1268
+					while (($i = array_shift($keys)) !== null) {
1269
+						$out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1270
+					}
1271
+				} elseif ($cnt === 1) {
1272
+					while (($i = array_shift($keys)) !== null) {
1273
+						$out[] = $callback($this, $items[$i]);
1274
+					}
1275
+				} elseif ($cnt === 2) {
1276
+					while (($i = array_shift($keys)) !== null) {
1277
+						$out[] = $callback($this, $items[$i], $params[2]);
1278
+					}
1279
+				} elseif ($cnt === 3) {
1280
+					while (($i = array_shift($keys)) !== null) {
1281
+						$out[] = $callback($this, $items[$i], $params[2], $params[3]);
1282
+					}
1283
+				} else {
1284
+					while (($i = array_shift($keys)) !== null) {
1285
+						$out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1286
+					}
1287
+				}
1288
+			} else {
1289
+				$items = $params[0];
1290
+				$keys  = array_keys($items);
1291
+
1292
+				if (is_string($callback) === false) {
1293
+					while (($i = array_shift($keys)) !== null) {
1294
+						$out[] = call_user_func_array($callback, array($items[$i]) + $params);
1295
+					}
1296
+				} elseif ($cnt === 1) {
1297
+					while (($i = array_shift($keys)) !== null) {
1298
+						$out[] = $callback($items[$i]);
1299
+					}
1300
+				} elseif ($cnt === 2) {
1301
+					while (($i = array_shift($keys)) !== null) {
1302
+						$out[] = $callback($items[$i], $params[1]);
1303
+					}
1304
+				} elseif ($cnt === 3) {
1305
+					while (($i = array_shift($keys)) !== null) {
1306
+						$out[] = $callback($items[$i], $params[1], $params[2]);
1307
+					}
1308
+				} elseif ($cnt === 4) {
1309
+					while (($i = array_shift($keys)) !== null) {
1310
+						$out[] = $callback($items[$i], $params[1], $params[2], $params[3]);
1311
+					}
1312
+				} else {
1313
+					while (($i = array_shift($keys)) !== null) {
1314
+						$out[] = call_user_func_array($callback, array($items[$i]) + $params);
1315
+					}
1316
+				}
1317
+			}
1318
+
1319
+			return $out;
1320
+		} else {
1321
+			return $params[0];
1322
+		}
1323
+	}
1324
+
1325
+	/**
1326
+	 * Reads a variable into the given data array.
1327
+	 *
1328
+	 * @param string $varstr   the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1329
+	 * @param mixed  $data     the data array or object to read from
1330
+	 * @param bool   $safeRead if true, the function will check whether the index exists to prevent any notices from
1331
+	 *                         being output
1332
+	 *
1333
+	 * @return mixed
1334
+	 */
1335
+	public function readVarInto($varstr, $data, $safeRead = false)
1336
+	{
1337
+		if ($data === null) {
1338
+			return null;
1339
+		}
1340
+
1341
+		if (is_array($varstr) === false) {
1342
+			preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1343
+		} else {
1344
+			$m = $varstr;
1345
+		}
1346
+		unset($varstr);
1347
+
1348
+		while (list($k, $sep) = each($m[1])) {
1349
+			if ($sep === '.' || $sep === '[' || $sep === '') {
1350
+				// strip enclosing quotes if present
1351
+				$m[2][$k] = preg_replace('#^(["\']?)(.*?)\1$#', '$2', $m[2][$k]);
1352
+
1353
+				if ((is_array($data) || $data instanceof ArrayAccess) && ($safeRead === false || isset($data[$m[2][$k]]))) {
1354
+					$data = $data[$m[2][$k]];
1355
+				} else {
1356
+					return null;
1357
+				}
1358
+			} else {
1359
+				if (is_object($data) && ($safeRead === false || isset($data->$m[2][$k]))) {
1360
+					$data = $data->$m[2][$k];
1361
+				} else {
1362
+					return null;
1363
+				}
1364
+			}
1365
+		}
1366
+
1367
+		return $data;
1368
+	}
1369
+
1370
+	/**
1371
+	 * Reads a variable into the parent scope.
1372
+	 *
1373
+	 * @param int    $parentLevels the amount of parent levels to go from the current scope
1374
+	 * @param string $varstr       the variable string, using dwoo variable syntax (i.e.
1375
+	 *                             "var.subvar[subsubvar]->property")
1376
+	 *
1377
+	 * @return mixed
1378
+	 */
1379
+	public function readParentVar($parentLevels, $varstr = null)
1380
+	{
1381
+		$tree = $this->scopeTree;
1382
+		$cur  = $this->data;
1383
+
1384
+		while ($parentLevels -- !== 0) {
1385
+			array_pop($tree);
1386
+		}
1387
+
1388
+		while (($i = array_shift($tree)) !== null) {
1389
+			if (is_object($cur)) {
1390
+				$cur = $cur->$i;
1391
+			} else {
1392
+				$cur = $cur[$i];
1393
+			}
1394
+		}
1395
+
1396
+		if ($varstr !== null) {
1397
+			return $this->readVarInto($varstr, $cur);
1398
+		} else {
1399
+			return $cur;
1400
+		}
1401
+	}
1402
+
1403
+	/**
1404
+	 * Reads a variable into the current scope.
1405
+	 *
1406
+	 * @param string $varstr the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1407
+	 *
1408
+	 * @return mixed
1409
+	 */
1410
+	public function readVar($varstr)
1411
+	{
1412
+		if (is_array($varstr) === true) {
1413
+			$m = $varstr;
1414
+			unset($varstr);
1415
+		} else {
1416
+			if (strstr($varstr, '.') === false && strstr($varstr, '[') === false && strstr($varstr, '->') === false) {
1417
+				if ($varstr === 'dwoo') {
1418
+					return $this->globals;
1419
+				} elseif ($varstr === '__' || $varstr === '_root') {
1420
+					return $this->data;
1421
+				} elseif ($varstr === '_' || $varstr === '_parent') {
1422
+					$varstr = '.' . $varstr;
1423
+					$tree   = $this->scopeTree;
1424
+					$cur    = $this->data;
1425
+					array_pop($tree);
1426
+
1427
+					while (($i = array_shift($tree)) !== null) {
1428
+						if (is_object($cur)) {
1429
+							$cur = $cur->$i;
1430
+						} else {
1431
+							$cur = $cur[$i];
1432
+						}
1433
+					}
1434
+
1435
+					return $cur;
1436
+				}
1437
+
1438
+				$cur = $this->scope;
1439
+
1440
+				if (isset($cur[$varstr])) {
1441
+					return $cur[$varstr];
1442
+				} else {
1443
+					return null;
1444
+				}
1445
+			}
1446
+
1447
+			if (substr($varstr, 0, 1) === '.') {
1448
+				$varstr = 'dwoo' . $varstr;
1449
+			}
1450
+
1451
+			preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
1452
+		}
1453
+
1454
+		$i = $m[2][0];
1455
+		if ($i === 'dwoo') {
1456
+			$cur = $this->globals;
1457
+			array_shift($m[2]);
1458
+			array_shift($m[1]);
1459
+			switch ($m[2][0]) {
1460
+			case 'get':
1461
+				$cur = $_GET;
1462
+				break;
1463
+			case 'post':
1464
+				$cur = $_POST;
1465
+				break;
1466
+			case 'session':
1467
+				$cur = $_SESSION;
1468
+				break;
1469
+			case 'cookies':
1470
+			case 'cookie':
1471
+				$cur = $_COOKIE;
1472
+				break;
1473
+			case 'server':
1474
+				$cur = $_SERVER;
1475
+				break;
1476
+			case 'env':
1477
+				$cur = $_ENV;
1478
+				break;
1479
+			case 'request':
1480
+				$cur = $_REQUEST;
1481
+				break;
1482
+			case 'const':
1483
+				array_shift($m[2]);
1484
+				if (defined($m[2][0])) {
1485
+					return constant($m[2][0]);
1486
+				} else {
1487
+					return null;
1488
+				}
1489
+			}
1490
+			if ($cur !== $this->globals) {
1491
+				array_shift($m[2]);
1492
+				array_shift($m[1]);
1493
+			}
1494
+		} elseif ($i === '__' || $i === '_root') {
1495
+			$cur = $this->data;
1496
+			array_shift($m[2]);
1497
+			array_shift($m[1]);
1498
+		} elseif ($i === '_' || $i === '_parent') {
1499
+			$tree = $this->scopeTree;
1500
+			$cur  = $this->data;
1501
+
1502
+			while (true) {
1503
+				array_pop($tree);
1504
+				array_shift($m[2]);
1505
+				array_shift($m[1]);
1506
+				if (current($m[2]) === '_' || current($m[2]) === '_parent') {
1507
+					continue;
1508
+				}
1509
+
1510
+				while (($i = array_shift($tree)) !== null) {
1511
+					if (is_object($cur)) {
1512
+						$cur = $cur->$i;
1513
+					} else {
1514
+						$cur = $cur[$i];
1515
+					}
1516
+				}
1517
+				break;
1518
+			}
1519
+		} else {
1520
+			$cur = $this->scope;
1521
+		}
1522
+
1523
+		while (list($k, $sep) = each($m[1])) {
1524
+			if ($sep === '.' || $sep === '[' || $sep === '') {
1525
+				if ((is_array($cur) || $cur instanceof ArrayAccess) && isset($cur[$m[2][$k]])) {
1526
+					$cur = $cur[$m[2][$k]];
1527
+				} else {
1528
+					return null;
1529
+				}
1530
+			} elseif ($sep === '->') {
1531
+				if (is_object($cur)) {
1532
+					$cur = $cur->$m[2][$k];
1533
+				} else {
1534
+					return null;
1535
+				}
1536
+			} else {
1537
+				return null;
1538
+			}
1539
+		}
1540
+
1541
+		return $cur;
1542
+	}
1543
+
1544
+	/**
1545
+	 * Assign the value to the given variable.
1546
+	 *
1547
+	 * @param mixed  $value the value to assign
1548
+	 * @param string $scope the variable string, using dwoo variable syntax (i.e. "var.subvar[subsubvar]->property")
1549
+	 *
1550
+	 * @return bool true if assigned correctly or false if a problem occured while parsing the var string
1551
+	 */
1552
+	public function assignInScope($value, $scope)
1553
+	{
1554
+		if (!is_string($scope)) {
1555
+			$this->triggerError('Assignments must be done into strings, (' . gettype($scope) . ') ' . var_export($scope, true) . ' given', E_USER_ERROR);
1556
+		}
1557
+		if (strstr($scope, '.') === false && strstr($scope, '->') === false) {
1558
+			$this->scope[$scope] = $value;
1559
+		} else {
1560
+			// TODO handle _root/_parent scopes ?
1561
+			preg_match_all('#(\[|->|\.)?([^.[\]-]+)\]?#i', $scope, $m);
1562
+
1563
+			$cur  = &$this->scope;
1564
+			$last = array(
1565
+				array_pop($m[1]),
1566
+				array_pop($m[2])
1567
+			);
1568
+
1569
+			while (list($k, $sep) = each($m[1])) {
1570
+				if ($sep === '.' || $sep === '[' || $sep === '') {
1571
+					if (is_array($cur) === false) {
1572
+						$cur = array();
1573
+					}
1574
+					$cur = &$cur[$m[2][$k]];
1575
+				} elseif ($sep === '->') {
1576
+					if (is_object($cur) === false) {
1577
+						$cur = new stdClass();
1578
+					}
1579
+					$cur = &$cur->$m[2][$k];
1580
+				} else {
1581
+					return false;
1582
+				}
1583
+			}
1584
+
1585
+			if ($last[0] === '.' || $last[0] === '[' || $last[0] === '') {
1586
+				if (is_array($cur) === false) {
1587
+					$cur = array();
1588
+				}
1589
+				$cur[$last[1]] = $value;
1590
+			} elseif ($last[0] === '->') {
1591
+				if (is_object($cur) === false) {
1592
+					$cur = new stdClass();
1593
+				}
1594
+				$cur->$last[1] = $value;
1595
+			} else {
1596
+				return false;
1597
+			}
1598
+		}
1599
+	}
1600
+
1601
+	/**
1602
+	 * Sets the scope to the given scope string or array.
1603
+	 *
1604
+	 * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1605
+	 * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1606
+	 *
1607
+	 * @return array the current scope tree
1608
+	 */
1609
+	public function setScope($scope, $absolute = false)
1610
+	{
1611
+		$old = $this->scopeTree;
1612
+
1613
+		if (is_string($scope) === true) {
1614
+			$scope = explode('.', $scope);
1615
+		}
1616
+
1617
+		if ($absolute === true) {
1618
+			$this->scope     = &$this->data;
1619
+			$this->scopeTree = array();
1620
+		}
1621
+
1622
+		while (($bit = array_shift($scope)) !== null) {
1623
+			if ($bit === '_' || $bit === '_parent') {
1624
+				array_pop($this->scopeTree);
1625
+				$this->scope = &$this->data;
1626
+				$cnt         = count($this->scopeTree);
1627
+				for ($i = 0; $i < $cnt; ++ $i) {
1628
+					$this->scope = &$this->scope[$this->scopeTree[$i]];
1629
+				}
1630
+			} elseif ($bit === '__' || $bit === '_root') {
1631
+				$this->scope     = &$this->data;
1632
+				$this->scopeTree = array();
1633
+			} elseif (isset($this->scope[$bit])) {
1634
+				if ($this->scope instanceof ArrayAccess) {
1635
+					$tmp         = $this->scope[$bit];
1636
+					$this->scope = &$tmp;
1637
+				} else {
1638
+					$this->scope = &$this->scope[$bit];
1639
+				}
1640
+				$this->scopeTree[] = $bit;
1641
+			} else {
1642
+				unset($this->scope);
1643
+				$this->scope = null;
1644
+			}
1645
+		}
1646
+
1647
+		return $old;
1648
+	}
1649
+
1650
+	/**
1651
+	 * Returns the entire data array.
1652
+	 *
1653
+	 * @return array
1654
+	 */
1655
+	public function getData()
1656
+	{
1657
+		return $this->data;
1658
+	}
1659
+
1660
+	/**
1661
+	 * Sets a return value for the currently running template.
1662
+	 *
1663
+	 * @param string $name  var name
1664
+	 * @param mixed  $value var value
1665
+	 *
1666
+	 * @return void
1667
+	 */
1668
+	public function setReturnValue($name, $value)
1669
+	{
1670
+		$this->returnData[$name] = $value;
1671
+	}
1672
+
1673
+	/**
1674
+	 * Retrieves the return values set by the template.
1675
+	 *
1676
+	 * @return array
1677
+	 */
1678
+	public function getReturnValues()
1679
+	{
1680
+		return $this->returnData;
1681
+	}
1682
+
1683
+	/**
1684
+	 * Returns a reference to the current scope.
1685
+	 *
1686
+	 * @return mixed
1687
+	 */
1688
+	public function &getScope()
1689
+	{
1690
+		return $this->scope;
1691
+	}
1692
+
1693
+	/**
1694
+	 * Redirects all calls to unexisting to plugin proxy.
1695
+	 *
1696
+	 * @param string $method the method name
1697
+	 * @param array  $args   array of arguments
1698
+	 *
1699
+	 * @return mixed
1700
+	 * @throws Exception
1701
+	 */
1702
+	public function __call($method, $args)
1703
+	{
1704
+		$proxy = $this->getPluginProxy();
1705
+		if (!$proxy) {
1706
+			throw new Exception('Call to undefined method ' . __CLASS__ . '::' . $method . '()');
1707
+		}
1708
+
1709
+		return call_user_func_array($proxy->getCallback($method), $args);
1710
+	}
1711
+
1712
+	/**
1713
+	 * Convert plugin name from `auto_escape` to `AutoEscape`.
1714
+	 * @param string $input
1715
+	 * @param string $separator
1716
+	 *
1717
+	 * @return mixed
1718
+	 */
1719
+	public static function toCamelCase($input, $separator = '_')
1720
+	{
1721
+		return join(array_map('ucfirst', explode($separator, $input)));
1722
+
1723
+		// TODO >= PHP5.4.32
1724
+		//return str_replace($separator, '', ucwords($input, $separator));
1725
+	}
1726 1726
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -375,8 +375,8 @@  discard block
 block discarded – undo
375 375
             }
376 376
 
377 377
             if ($doCache === true) {
378
-                $out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*' . $dynamicId . '*/ echo \'$1\'; ?>', $out);
379
-                if (!class_exists(self::NAMESPACE_PLUGINS_BLOCKS . 'PluginDynamic')) {
378
+                $out = preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php /*'.$dynamicId.'*/ echo \'$1\'; ?>', $out);
379
+                if (!class_exists(self::NAMESPACE_PLUGINS_BLOCKS.'PluginDynamic')) {
380 380
                     $this->getLoader()->loadPlugin('PluginDynamic');
381 381
                 }
382 382
                 $out = PluginDynamic::unescape($out, $dynamicId, $compiledTemplate);
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
     public function addFilter($callback, $autoload = false)
546 546
     {
547 547
         if ($autoload) {
548
-            $class = self::NAMESPACE_PLUGINS_FILTERS . self::toCamelCase($callback);
548
+            $class = self::NAMESPACE_PLUGINS_FILTERS.self::toCamelCase($callback);
549 549
             if (!class_exists($class) && !function_exists($class)) {
550 550
                 try {
551 551
                     $this->getLoader()->loadPlugin($callback);
@@ -553,12 +553,12 @@  discard block
 block discarded – undo
553 553
                 catch (Exception $e) {
554 554
                     if (strstr($callback, self::NAMESPACE_PLUGINS_FILTERS)) {
555 555
                         throw new Exception(
556
-                            'Wrong filter name : ' . $callback . ', the "Dwoo_Filter_" prefix should 
557
-                        not be used, please only use "' . str_replace('Dwoo_Filter_', '', $callback) . '"'
556
+                            'Wrong filter name : '.$callback.', the "Dwoo_Filter_" prefix should 
557
+                        not be used, please only use "' . str_replace('Dwoo_Filter_', '', $callback).'"'
558 558
                         );
559 559
                     } else {
560 560
                         throw new Exception(
561
-                            'Wrong filter name : ' . $callback . ', when using autoload the filter must
561
+                            'Wrong filter name : '.$callback.', when using autoload the filter must
562 562
                          be in one of your plugin dir as "name.php" containig a class or function named
563 563
                          "Dwoo_Filter_name"'
564 564
                         );
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
                 $callback = $class;
573 573
             } else {
574 574
                 throw new Exception(
575
-                    'Wrong filter name : ' . $callback . ', when using autoload the filter must be in
575
+                    'Wrong filter name : '.$callback.', when using autoload the filter must be in
576 576
                 one of your plugin dir as "name.php" containig a class or function named "Dwoo_Filter_name"'
577 577
                 );
578 578
             }
@@ -592,14 +592,14 @@  discard block
 block discarded – undo
592 592
      */
593 593
     public function removeFilter($callback)
594 594
     {
595
-        if (($index = array_search(self::NAMESPACE_PLUGINS_FILTERS. 'Filter' . self::toCamelCase($callback), $this->filters,
595
+        if (($index = array_search(self::NAMESPACE_PLUGINS_FILTERS.'Filter'.self::toCamelCase($callback), $this->filters,
596 596
                 true)) !==
597 597
             false) {
598 598
             unset($this->filters[$index]);
599 599
         } elseif (($index = array_search($callback, $this->filters, true)) !== false) {
600 600
             unset($this->filters[$index]);
601 601
         } else {
602
-            $class = self::NAMESPACE_PLUGINS_FILTERS . 'Filter' . $callback;
602
+            $class = self::NAMESPACE_PLUGINS_FILTERS.'Filter'.$callback;
603 603
             foreach ($this->filters as $index => $filter) {
604 604
                 if (is_array($filter) && $filter[0] instanceof $class) {
605 605
                     unset($this->filters[$index]);
@@ -722,7 +722,7 @@  discard block
 block discarded – undo
722 722
     public function getCacheDir()
723 723
     {
724 724
         if ($this->cacheDir === null) {
725
-            $this->setCacheDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR);
725
+            $this->setCacheDir(dirname(__DIR__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR);
726 726
         }
727 727
 
728 728
         return $this->cacheDir;
@@ -738,9 +738,9 @@  discard block
 block discarded – undo
738 738
      */
739 739
     public function setCacheDir($dir)
740 740
     {
741
-        $this->cacheDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
741
+        $this->cacheDir = rtrim($dir, '/\\').DIRECTORY_SEPARATOR;
742 742
         if (is_writable($this->cacheDir) === false) {
743
-            throw new Exception('The cache directory must be writable, chmod "' . $this->cacheDir . '" to make it writable');
743
+            throw new Exception('The cache directory must be writable, chmod "'.$this->cacheDir.'" to make it writable');
744 744
         }
745 745
     }
746 746
 
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
     public function getCompileDir()
753 753
     {
754 754
         if ($this->compileDir === null) {
755
-            $this->setCompileDir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR);
755
+            $this->setCompileDir(dirname(__DIR__).DIRECTORY_SEPARATOR.'compiled'.DIRECTORY_SEPARATOR);
756 756
         }
757 757
 
758 758
         return $this->compileDir;
@@ -768,9 +768,9 @@  discard block
 block discarded – undo
768 768
      */
769 769
     public function setCompileDir($dir)
770 770
     {
771
-        $this->compileDir = rtrim($dir, '/\\') . DIRECTORY_SEPARATOR;
771
+        $this->compileDir = rtrim($dir, '/\\').DIRECTORY_SEPARATOR;
772 772
         if (is_writable($this->compileDir) === false) {
773
-            throw new Exception('The compile directory must be writable, chmod "' . $this->compileDir . '" to make it writable');
773
+            throw new Exception('The compile directory must be writable, chmod "'.$this->compileDir.'" to make it writable');
774 774
         }
775 775
     }
776 776
 
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
      */
794 794
     public function setCacheTime($seconds)
795 795
     {
796
-        $this->cacheTime = (int)$seconds;
796
+        $this->cacheTime = (int) $seconds;
797 797
     }
798 798
 
799 799
     /**
@@ -817,7 +817,7 @@  discard block
 block discarded – undo
817 817
      */
818 818
     public function setCharset($charset)
819 819
     {
820
-        $this->charset = strtolower((string)$charset);
820
+        $this->charset = strtolower((string) $charset);
821 821
     }
822 822
 
823 823
     /**
@@ -954,11 +954,11 @@  discard block
 block discarded – undo
954 954
     public function clearCache($olderThan = - 1)
955 955
     {
956 956
         $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getCacheDir()), \RecursiveIteratorIterator::SELF_FIRST);
957
-        $expired  = time() - $olderThan;
957
+        $expired  = time()-$olderThan;
958 958
         $count    = 0;
959 959
         foreach ($iterator as $file) {
960 960
             if ($file->isFile() && $file->getCTime() < $expired) {
961
-                $count += unlink((string)$file) ? 1 : 0;
961
+                $count += unlink((string) $file) ? 1 : 0;
962 962
             }
963 963
         }
964 964
 
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
             return $class::templateFactory($this, $resourceId, $cacheTime, $cacheId, $compileId, $parentTemplate);
992 992
         }
993 993
 
994
-        throw new Exception('Unknown resource type : ' . $resourceName);
994
+        throw new Exception('Unknown resource type : '.$resourceName);
995 995
     }
996 996
 
997 997
     /**
@@ -1091,7 +1091,7 @@  discard block
 block discarded – undo
1091 1091
         if (!($tplIdentifier = $this->template->getResourceIdentifier())) {
1092 1092
             $tplIdentifier = $this->template->getResourceName();
1093 1093
         }
1094
-        trigger_error('Dwoo error (in ' . $tplIdentifier . ') : ' . $message, $level);
1094
+        trigger_error('Dwoo error (in '.$tplIdentifier.') : '.$message, $level);
1095 1095
     }
1096 1096
 
1097 1097
     /**
@@ -1107,7 +1107,7 @@  discard block
 block discarded – undo
1107 1107
         if (isset($this->plugins[$blockName])) {
1108 1108
             $class = $this->plugins[$blockName]['class'];
1109 1109
         } else {
1110
-            $class = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin' . self::toCamelCase($blockName);
1110
+            $class = self::NAMESPACE_PLUGINS_BLOCKS.'Plugin'.self::toCamelCase($blockName);
1111 1111
         }
1112 1112
 
1113 1113
         if ($this->curBlock !== null) {
@@ -1170,7 +1170,7 @@  discard block
 block discarded – undo
1170 1170
     {
1171 1171
         $index = array_search($block, $this->stack, true);
1172 1172
         if ($index !== false && $index > 0) {
1173
-            return $this->stack[$index - 1];
1173
+            return $this->stack[$index-1];
1174 1174
         }
1175 1175
 
1176 1176
         return false;
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
         if (isset($this->plugins[$type])) {
1189 1189
             $type = $this->plugins[$type]['class'];
1190 1190
         } else {
1191
-            $type = self::NAMESPACE_PLUGINS_BLOCKS . 'Plugin_' . str_replace(self::NAMESPACE_PLUGINS_BLOCKS.'Plugin',
1191
+            $type = self::NAMESPACE_PLUGINS_BLOCKS.'Plugin_'.str_replace(self::NAMESPACE_PLUGINS_BLOCKS.'Plugin',
1192 1192
                     '', $type);
1193 1193
         }
1194 1194
 
@@ -1266,7 +1266,7 @@  discard block
 block discarded – undo
1266 1266
 
1267 1267
                 if (is_string($callback) === false) {
1268 1268
                     while (($i = array_shift($keys)) !== null) {
1269
-                        $out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1269
+                        $out[] = call_user_func_array($callback, array(1 => $items[$i])+$params);
1270 1270
                     }
1271 1271
                 } elseif ($cnt === 1) {
1272 1272
                     while (($i = array_shift($keys)) !== null) {
@@ -1282,7 +1282,7 @@  discard block
 block discarded – undo
1282 1282
                     }
1283 1283
                 } else {
1284 1284
                     while (($i = array_shift($keys)) !== null) {
1285
-                        $out[] = call_user_func_array($callback, array(1 => $items[$i]) + $params);
1285
+                        $out[] = call_user_func_array($callback, array(1 => $items[$i])+$params);
1286 1286
                     }
1287 1287
                 }
1288 1288
             } else {
@@ -1291,7 +1291,7 @@  discard block
 block discarded – undo
1291 1291
 
1292 1292
                 if (is_string($callback) === false) {
1293 1293
                     while (($i = array_shift($keys)) !== null) {
1294
-                        $out[] = call_user_func_array($callback, array($items[$i]) + $params);
1294
+                        $out[] = call_user_func_array($callback, array($items[$i])+$params);
1295 1295
                     }
1296 1296
                 } elseif ($cnt === 1) {
1297 1297
                     while (($i = array_shift($keys)) !== null) {
@@ -1311,7 +1311,7 @@  discard block
 block discarded – undo
1311 1311
                     }
1312 1312
                 } else {
1313 1313
                     while (($i = array_shift($keys)) !== null) {
1314
-                        $out[] = call_user_func_array($callback, array($items[$i]) + $params);
1314
+                        $out[] = call_user_func_array($callback, array($items[$i])+$params);
1315 1315
                     }
1316 1316
                 }
1317 1317
             }
@@ -1381,7 +1381,7 @@  discard block
 block discarded – undo
1381 1381
         $tree = $this->scopeTree;
1382 1382
         $cur  = $this->data;
1383 1383
 
1384
-        while ($parentLevels -- !== 0) {
1384
+        while ($parentLevels-- !== 0) {
1385 1385
             array_pop($tree);
1386 1386
         }
1387 1387
 
@@ -1419,7 +1419,7 @@  discard block
 block discarded – undo
1419 1419
                 } elseif ($varstr === '__' || $varstr === '_root') {
1420 1420
                     return $this->data;
1421 1421
                 } elseif ($varstr === '_' || $varstr === '_parent') {
1422
-                    $varstr = '.' . $varstr;
1422
+                    $varstr = '.'.$varstr;
1423 1423
                     $tree   = $this->scopeTree;
1424 1424
                     $cur    = $this->data;
1425 1425
                     array_pop($tree);
@@ -1445,7 +1445,7 @@  discard block
 block discarded – undo
1445 1445
             }
1446 1446
 
1447 1447
             if (substr($varstr, 0, 1) === '.') {
1448
-                $varstr = 'dwoo' . $varstr;
1448
+                $varstr = 'dwoo'.$varstr;
1449 1449
             }
1450 1450
 
1451 1451
             preg_match_all('#(\[|->|\.)?((?:[^.[\]-]|-(?!>))+)\]?#i', $varstr, $m);
@@ -1552,7 +1552,7 @@  discard block
 block discarded – undo
1552 1552
     public function assignInScope($value, $scope)
1553 1553
     {
1554 1554
         if (!is_string($scope)) {
1555
-            $this->triggerError('Assignments must be done into strings, (' . gettype($scope) . ') ' . var_export($scope, true) . ' given', E_USER_ERROR);
1555
+            $this->triggerError('Assignments must be done into strings, ('.gettype($scope).') '.var_export($scope, true).' given', E_USER_ERROR);
1556 1556
         }
1557 1557
         if (strstr($scope, '.') === false && strstr($scope, '->') === false) {
1558 1558
             $this->scope[$scope] = $value;
@@ -1703,7 +1703,7 @@  discard block
 block discarded – undo
1703 1703
     {
1704 1704
         $proxy = $this->getPluginProxy();
1705 1705
         if (!$proxy) {
1706
-            throw new Exception('Call to undefined method ' . __CLASS__ . '::' . $method . '()');
1706
+            throw new Exception('Call to undefined method '.__CLASS__.'::'.$method.'()');
1707 1707
         }
1708 1708
 
1709 1709
         return call_user_func_array($proxy->getCallback($method), $args);
Please login to merge, or discard this patch.
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.
lib/Dwoo/Loader.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@
 block discarded – undo
57 57
     /**
58 58
      * Loader constructor.
59 59
      *
60
-     * @param $cacheDir
60
+     * @param string $cacheDir
61 61
      */
62 62
     public function __construct($cacheDir)
63 63
     {
Please login to merge, or discard this patch.
Indentation   +162 added lines, -162 removed lines patch added patch discarded remove patch
@@ -23,176 +23,176 @@
 block discarded – undo
23 23
  */
24 24
 class Loader implements ILoader
25 25
 {
26
-    /**
27
-     * Stores the plugin directories.
28
-     *
29
-     * @see addDirectory
30
-     * @var array
31
-     */
32
-    protected $paths = array();
26
+	/**
27
+	 * Stores the plugin directories.
28
+	 *
29
+	 * @see addDirectory
30
+	 * @var array
31
+	 */
32
+	protected $paths = array();
33 33
 
34
-    /**
35
-     * Stores the plugins names/paths relationships
36
-     * don't edit this on your own, use addDirectory.
37
-     *
38
-     * @see addDirectory
39
-     * @var array
40
-     */
41
-    protected $classPath = array();
34
+	/**
35
+	 * Stores the plugins names/paths relationships
36
+	 * don't edit this on your own, use addDirectory.
37
+	 *
38
+	 * @see addDirectory
39
+	 * @var array
40
+	 */
41
+	protected $classPath = array();
42 42
 
43
-    /**
44
-     * Path where class paths cache files are written.
45
-     *
46
-     * @var string
47
-     */
48
-    protected $cacheDir;
43
+	/**
44
+	 * Path where class paths cache files are written.
45
+	 *
46
+	 * @var string
47
+	 */
48
+	protected $cacheDir;
49 49
 
50
-    /**
51
-     * Path where builtin plugins are stored.
52
-     *
53
-     * @var string
54
-     */
55
-    protected $corePluginDir;
50
+	/**
51
+	 * Path where builtin plugins are stored.
52
+	 *
53
+	 * @var string
54
+	 */
55
+	protected $corePluginDir;
56 56
 
57
-    /**
58
-     * Loader constructor.
59
-     *
60
-     * @param $cacheDir
61
-     */
62
-    public function __construct($cacheDir)
63
-    {
64
-        $this->corePluginDir = __DIR__ . DIRECTORY_SEPARATOR . 'Plugins';
65
-        $this->cacheDir      = rtrim($cacheDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
57
+	/**
58
+	 * Loader constructor.
59
+	 *
60
+	 * @param $cacheDir
61
+	 */
62
+	public function __construct($cacheDir)
63
+	{
64
+		$this->corePluginDir = __DIR__ . DIRECTORY_SEPARATOR . 'Plugins';
65
+		$this->cacheDir      = rtrim($cacheDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
66 66
 
67
-        // include class paths or rebuild paths if the cache file isn't there
68
-        $cacheFile = $this->cacheDir . 'classpath.cache.d' . Core::RELEASE_TAG . '.php';
69
-        if (file_exists($cacheFile)) {
70
-            $classpath       = file_get_contents($cacheFile);
71
-            $this->classPath = unserialize($classpath) + $this->classPath;
72
-        } else {
73
-            $this->rebuildClassPathCache($this->corePluginDir, $cacheFile);
74
-        }
75
-    }
67
+		// include class paths or rebuild paths if the cache file isn't there
68
+		$cacheFile = $this->cacheDir . 'classpath.cache.d' . Core::RELEASE_TAG . '.php';
69
+		if (file_exists($cacheFile)) {
70
+			$classpath       = file_get_contents($cacheFile);
71
+			$this->classPath = unserialize($classpath) + $this->classPath;
72
+		} else {
73
+			$this->rebuildClassPathCache($this->corePluginDir, $cacheFile);
74
+		}
75
+	}
76 76
 
77
-    /**
78
-     * Rebuilds class paths, scans the given directory recursively and saves all paths in the given file.
79
-     *
80
-     * @param string $path      the plugin path to scan
81
-     * @param string $cacheFile the file where to store the plugin paths cache, it will be overwritten
82
-     *
83
-     * @throws Exception
84
-     */
85
-    protected function rebuildClassPathCache($path, $cacheFile)
86
-    {
87
-        if ($cacheFile !== false) {
88
-            $tmp             = $this->classPath;
89
-            $this->classPath = array();
90
-        }
77
+	/**
78
+	 * Rebuilds class paths, scans the given directory recursively and saves all paths in the given file.
79
+	 *
80
+	 * @param string $path      the plugin path to scan
81
+	 * @param string $cacheFile the file where to store the plugin paths cache, it will be overwritten
82
+	 *
83
+	 * @throws Exception
84
+	 */
85
+	protected function rebuildClassPathCache($path, $cacheFile)
86
+	{
87
+		if ($cacheFile !== false) {
88
+			$tmp             = $this->classPath;
89
+			$this->classPath = array();
90
+		}
91 91
 
92
-        // iterates over all files/folders
93
-        $list = glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*');
94
-        if (is_array($list)) {
95
-            foreach ($list as $f) {
96
-                if (is_dir($f)) {
97
-                    $this->rebuildClassPathCache($f, false);
98
-                } else {
99
-                    // TODO: is it still valid now?
100
-                    $this->classPath[str_replace(array(
101
-                        'function.',
102
-                        'block.',
103
-                        'modifier.',
104
-                        'outputfilter.',
105
-                        'filter.',
106
-                        'prefilter.',
107
-                        'postfilter.',
108
-                        'pre.',
109
-                        'post.',
110
-                        'output.',
111
-                        'shared.',
112
-                        'helper.'
113
-                    ), '', basename($f, '.php'))] = $f;
114
-                }
115
-            }
116
-        }
92
+		// iterates over all files/folders
93
+		$list = glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*');
94
+		if (is_array($list)) {
95
+			foreach ($list as $f) {
96
+				if (is_dir($f)) {
97
+					$this->rebuildClassPathCache($f, false);
98
+				} else {
99
+					// TODO: is it still valid now?
100
+					$this->classPath[str_replace(array(
101
+						'function.',
102
+						'block.',
103
+						'modifier.',
104
+						'outputfilter.',
105
+						'filter.',
106
+						'prefilter.',
107
+						'postfilter.',
108
+						'pre.',
109
+						'post.',
110
+						'output.',
111
+						'shared.',
112
+						'helper.'
113
+					), '', basename($f, '.php'))] = $f;
114
+				}
115
+			}
116
+		}
117 117
 
118
-        // save in file if it's the first call (not recursed)
119
-        if ($cacheFile !== false) {
120
-            if (!file_put_contents($cacheFile, serialize($this->classPath))) {
121
-                throw new Exception('Could not write into ' . $cacheFile .
122
-                    ', either because the folder is not there (create it) or because of the chmod configuration (please ensure this directory is writable by php), alternatively you can change the directory used with $dwoo->setCompileDir() or provide a custom loader object with $dwoo->setLoader()');
123
-            }
124
-            $this->classPath += $tmp;
125
-        }
126
-    }
118
+		// save in file if it's the first call (not recursed)
119
+		if ($cacheFile !== false) {
120
+			if (!file_put_contents($cacheFile, serialize($this->classPath))) {
121
+				throw new Exception('Could not write into ' . $cacheFile .
122
+					', either because the folder is not there (create it) or because of the chmod configuration (please ensure this directory is writable by php), alternatively you can change the directory used with $dwoo->setCompileDir() or provide a custom loader object with $dwoo->setLoader()');
123
+			}
124
+			$this->classPath += $tmp;
125
+		}
126
+	}
127 127
 
128
-    /**
129
-     * Loads a plugin file.
130
-     *
131
-     * @param string $class       the plugin name, without the `Plugin` prefix
132
-     * @param bool   $forceRehash if true, the class path caches will be rebuilt if the plugin is not found, in case it
133
-     *                            has just been added, defaults to true
134
-     *
135
-     * @throws Exception
136
-     */
137
-    public function loadPlugin($class, $forceRehash = true)
138
-    {
139
-        /**
140
-         * An unknown class was requested (maybe newly added) or the
141
-         * include failed so we rebuild the cache. include() will fail
142
-         * with an uncatchable error if the file doesn't exist, which
143
-         * usually means that the cache is stale and must be rebuilt,
144
-         * so we check for that before trying to include() the plugin.
145
-         */
146
-        if ((!isset($this->classPath[$class]) || !is_readable($this->classPath[$class])) || (!isset
147
-                ($this->classPath[$class . 'Compile']) || !is_readable($this->classPath[$class . 'Compile']))) {
148
-            if ($forceRehash) {
149
-                $this->rebuildClassPathCache($this->corePluginDir, $this->cacheDir . 'classpath.cache.d' .
150
-                    Core::RELEASE_TAG . '.php');
151
-                foreach ($this->paths as $path => $file) {
152
-                    $this->rebuildClassPathCache($path, $file);
153
-                }
154
-                if (isset($this->classPath[$class])) {
155
-                    include_once $this->classPath[$class];
156
-                } elseif (isset($this->classPath[$class . 'Compile'])) {
157
-                    include_once $this->classPath[$class . 'Compile'];
158
-                } else {
159
-                    throw new Exception('Plugin "' . $class .
160
-                        '" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
161
-                }
162
-            } else {
163
-                throw new Exception('Plugin "' . $class .
164
-                    '" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
165
-            }
166
-        }
167
-    }
128
+	/**
129
+	 * Loads a plugin file.
130
+	 *
131
+	 * @param string $class       the plugin name, without the `Plugin` prefix
132
+	 * @param bool   $forceRehash if true, the class path caches will be rebuilt if the plugin is not found, in case it
133
+	 *                            has just been added, defaults to true
134
+	 *
135
+	 * @throws Exception
136
+	 */
137
+	public function loadPlugin($class, $forceRehash = true)
138
+	{
139
+		/**
140
+		 * An unknown class was requested (maybe newly added) or the
141
+		 * include failed so we rebuild the cache. include() will fail
142
+		 * with an uncatchable error if the file doesn't exist, which
143
+		 * usually means that the cache is stale and must be rebuilt,
144
+		 * so we check for that before trying to include() the plugin.
145
+		 */
146
+		if ((!isset($this->classPath[$class]) || !is_readable($this->classPath[$class])) || (!isset
147
+				($this->classPath[$class . 'Compile']) || !is_readable($this->classPath[$class . 'Compile']))) {
148
+			if ($forceRehash) {
149
+				$this->rebuildClassPathCache($this->corePluginDir, $this->cacheDir . 'classpath.cache.d' .
150
+					Core::RELEASE_TAG . '.php');
151
+				foreach ($this->paths as $path => $file) {
152
+					$this->rebuildClassPathCache($path, $file);
153
+				}
154
+				if (isset($this->classPath[$class])) {
155
+					include_once $this->classPath[$class];
156
+				} elseif (isset($this->classPath[$class . 'Compile'])) {
157
+					include_once $this->classPath[$class . 'Compile'];
158
+				} else {
159
+					throw new Exception('Plugin "' . $class .
160
+						'" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
161
+				}
162
+			} else {
163
+				throw new Exception('Plugin "' . $class .
164
+					'" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
165
+			}
166
+		}
167
+	}
168 168
 
169
-    /**
170
-     * Adds a plugin directory, the plugins found in the new plugin directory
171
-     * will take precedence over the other directories (including the default
172
-     * dwoo plugin directory), you can use this for example to override plugins
173
-     * in a specific directory for a specific application while keeping all your
174
-     * usual plugins in the same place for all applications.
175
-     * TOCOM don't forget that php functions overrides are not rehashed so you
176
-     * need to clear the classpath caches by hand when adding those.
177
-     *
178
-     * @param string $pluginDirectory the plugin path to scan
179
-     *
180
-     * @throws Exception
181
-     */
182
-    public function addDirectory($pluginDirectory)
183
-    {
184
-        $pluginDir = realpath($pluginDirectory);
185
-        if (!$pluginDir) {
186
-            throw new Exception('Plugin directory does not exist or can not be read : ' . $pluginDirectory);
187
-        }
188
-        $cacheFile = $this->cacheDir . 'classpath-' . substr(strtr($pluginDir, '/\\:' . PATH_SEPARATOR, '----'),
189
-                strlen($pluginDir) > 80 ? - 80 : 0) . '.d' . Core::RELEASE_TAG . '.php';
190
-        $this->paths[$pluginDir] = $cacheFile;
191
-        if (file_exists($cacheFile)) {
192
-            $classpath       = file_get_contents($cacheFile);
193
-            $this->classPath = unserialize($classpath) + $this->classPath;
194
-        } else {
195
-            $this->rebuildClassPathCache($pluginDir, $cacheFile);
196
-        }
197
-    }
169
+	/**
170
+	 * Adds a plugin directory, the plugins found in the new plugin directory
171
+	 * will take precedence over the other directories (including the default
172
+	 * dwoo plugin directory), you can use this for example to override plugins
173
+	 * in a specific directory for a specific application while keeping all your
174
+	 * usual plugins in the same place for all applications.
175
+	 * TOCOM don't forget that php functions overrides are not rehashed so you
176
+	 * need to clear the classpath caches by hand when adding those.
177
+	 *
178
+	 * @param string $pluginDirectory the plugin path to scan
179
+	 *
180
+	 * @throws Exception
181
+	 */
182
+	public function addDirectory($pluginDirectory)
183
+	{
184
+		$pluginDir = realpath($pluginDirectory);
185
+		if (!$pluginDir) {
186
+			throw new Exception('Plugin directory does not exist or can not be read : ' . $pluginDirectory);
187
+		}
188
+		$cacheFile = $this->cacheDir . 'classpath-' . substr(strtr($pluginDir, '/\\:' . PATH_SEPARATOR, '----'),
189
+				strlen($pluginDir) > 80 ? - 80 : 0) . '.d' . Core::RELEASE_TAG . '.php';
190
+		$this->paths[$pluginDir] = $cacheFile;
191
+		if (file_exists($cacheFile)) {
192
+			$classpath       = file_get_contents($cacheFile);
193
+			$this->classPath = unserialize($classpath) + $this->classPath;
194
+		} else {
195
+			$this->rebuildClassPathCache($pluginDir, $cacheFile);
196
+		}
197
+	}
198 198
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -61,14 +61,14 @@  discard block
 block discarded – undo
61 61
      */
62 62
     public function __construct($cacheDir)
63 63
     {
64
-        $this->corePluginDir = __DIR__ . DIRECTORY_SEPARATOR . 'Plugins';
65
-        $this->cacheDir      = rtrim($cacheDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
64
+        $this->corePluginDir = __DIR__.DIRECTORY_SEPARATOR.'Plugins';
65
+        $this->cacheDir      = rtrim($cacheDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
66 66
 
67 67
         // include class paths or rebuild paths if the cache file isn't there
68
-        $cacheFile = $this->cacheDir . 'classpath.cache.d' . Core::RELEASE_TAG . '.php';
68
+        $cacheFile = $this->cacheDir.'classpath.cache.d'.Core::RELEASE_TAG.'.php';
69 69
         if (file_exists($cacheFile)) {
70 70
             $classpath       = file_get_contents($cacheFile);
71
-            $this->classPath = unserialize($classpath) + $this->classPath;
71
+            $this->classPath = unserialize($classpath)+$this->classPath;
72 72
         } else {
73 73
             $this->rebuildClassPathCache($this->corePluginDir, $cacheFile);
74 74
         }
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
         }
91 91
 
92 92
         // iterates over all files/folders
93
-        $list = glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*');
93
+        $list = glob(rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'*');
94 94
         if (is_array($list)) {
95 95
             foreach ($list as $f) {
96 96
                 if (is_dir($f)) {
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
         // save in file if it's the first call (not recursed)
119 119
         if ($cacheFile !== false) {
120 120
             if (!file_put_contents($cacheFile, serialize($this->classPath))) {
121
-                throw new Exception('Could not write into ' . $cacheFile .
121
+                throw new Exception('Could not write into '.$cacheFile.
122 122
                     ', either because the folder is not there (create it) or because of the chmod configuration (please ensure this directory is writable by php), alternatively you can change the directory used with $dwoo->setCompileDir() or provide a custom loader object with $dwoo->setLoader()');
123 123
             }
124 124
             $this->classPath += $tmp;
@@ -144,23 +144,23 @@  discard block
 block discarded – undo
144 144
          * so we check for that before trying to include() the plugin.
145 145
          */
146 146
         if ((!isset($this->classPath[$class]) || !is_readable($this->classPath[$class])) || (!isset
147
-                ($this->classPath[$class . 'Compile']) || !is_readable($this->classPath[$class . 'Compile']))) {
147
+                ($this->classPath[$class.'Compile']) || !is_readable($this->classPath[$class.'Compile']))) {
148 148
             if ($forceRehash) {
149
-                $this->rebuildClassPathCache($this->corePluginDir, $this->cacheDir . 'classpath.cache.d' .
150
-                    Core::RELEASE_TAG . '.php');
149
+                $this->rebuildClassPathCache($this->corePluginDir, $this->cacheDir.'classpath.cache.d'.
150
+                    Core::RELEASE_TAG.'.php');
151 151
                 foreach ($this->paths as $path => $file) {
152 152
                     $this->rebuildClassPathCache($path, $file);
153 153
                 }
154 154
                 if (isset($this->classPath[$class])) {
155 155
                     include_once $this->classPath[$class];
156
-                } elseif (isset($this->classPath[$class . 'Compile'])) {
157
-                    include_once $this->classPath[$class . 'Compile'];
156
+                } elseif (isset($this->classPath[$class.'Compile'])) {
157
+                    include_once $this->classPath[$class.'Compile'];
158 158
                 } else {
159
-                    throw new Exception('Plugin "' . $class .
159
+                    throw new Exception('Plugin "'.$class.
160 160
                         '" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
161 161
                 }
162 162
             } else {
163
-                throw new Exception('Plugin "' . $class .
163
+                throw new Exception('Plugin "'.$class.
164 164
                     '" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
165 165
             }
166 166
         }
@@ -183,14 +183,14 @@  discard block
 block discarded – undo
183 183
     {
184 184
         $pluginDir = realpath($pluginDirectory);
185 185
         if (!$pluginDir) {
186
-            throw new Exception('Plugin directory does not exist or can not be read : ' . $pluginDirectory);
186
+            throw new Exception('Plugin directory does not exist or can not be read : '.$pluginDirectory);
187 187
         }
188
-        $cacheFile = $this->cacheDir . 'classpath-' . substr(strtr($pluginDir, '/\\:' . PATH_SEPARATOR, '----'),
189
-                strlen($pluginDir) > 80 ? - 80 : 0) . '.d' . Core::RELEASE_TAG . '.php';
188
+        $cacheFile = $this->cacheDir.'classpath-'.substr(strtr($pluginDir, '/\\:'.PATH_SEPARATOR, '----'),
189
+                strlen($pluginDir) > 80 ? -80 : 0).'.d'.Core::RELEASE_TAG.'.php';
190 190
         $this->paths[$pluginDir] = $cacheFile;
191 191
         if (file_exists($cacheFile)) {
192 192
             $classpath       = file_get_contents($cacheFile);
193
-            $this->classPath = unserialize($classpath) + $this->classPath;
193
+            $this->classPath = unserialize($classpath)+$this->classPath;
194 194
         } else {
195 195
             $this->rebuildClassPathCache($pluginDir, $cacheFile);
196 196
         }
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Blocks/PluginDynamic.php 4 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -85,8 +85,8 @@
 block discarded – undo
85 85
 
86 86
     /**
87 87
      * @param $output
88
-     * @param $dynamicId
89
-     * @param $compiledFile
88
+     * @param string $dynamicId
89
+     * @param string $compiledFile
90 90
      *
91 91
      * @return mixed|string
92 92
      */
Please login to merge, or discard this patch.
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -28,89 +28,89 @@
 block discarded – undo
28 28
  */
29 29
 class PluginDynamic extends BlockPlugin implements ICompilableBlock
30 30
 {
31
-    /**
32
-     *
33
-     */
34
-    public function init()
35
-    {
36
-    }
31
+	/**
32
+	 *
33
+	 */
34
+	public function init()
35
+	{
36
+	}
37 37
 
38
-    /**
39
-     * @param Compiler $compiler
40
-     * @param array    $params
41
-     * @param string   $prepend
42
-     * @param string   $append
43
-     * @param string   $type
44
-     *
45
-     * @return string
46
-     */
47
-    public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
48
-    {
49
-        return '';
50
-    }
38
+	/**
39
+	 * @param Compiler $compiler
40
+	 * @param array    $params
41
+	 * @param string   $prepend
42
+	 * @param string   $append
43
+	 * @param string   $type
44
+	 *
45
+	 * @return string
46
+	 */
47
+	public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
48
+	{
49
+		return '';
50
+	}
51 51
 
52
-    /**
53
-     * @param Compiler $compiler
54
-     * @param array    $params
55
-     * @param string   $prepend
56
-     * @param string   $append
57
-     * @param string   $content
58
-     *
59
-     * @return string
60
-     */
61
-    public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
62
-    {
63
-        try {
64
-            $compiler->findBlock('dynamic');
52
+	/**
53
+	 * @param Compiler $compiler
54
+	 * @param array    $params
55
+	 * @param string   $prepend
56
+	 * @param string   $append
57
+	 * @param string   $content
58
+	 *
59
+	 * @return string
60
+	 */
61
+	public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
62
+	{
63
+		try {
64
+			$compiler->findBlock('dynamic');
65 65
 
66
-            return $content;
67
-        }
68
-        catch (CompilationException $e) {
69
-        }
70
-        $output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
71
-        if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
72
-            $output .= substr($content, strlen(Compiler::PHP_OPEN));
73
-        } else {
74
-            $output .= Compiler::PHP_CLOSE . $content;
75
-        }
76
-        if (substr($output, - strlen(Compiler::PHP_CLOSE)) == Compiler::PHP_CLOSE) {
77
-            $output = substr($output, 0, - strlen(Compiler::PHP_CLOSE));
78
-        } else {
79
-            $output .= Compiler::PHP_OPEN;
80
-        }
81
-        $output .= "\n}" . Compiler::PHP_CLOSE;
66
+			return $content;
67
+		}
68
+		catch (CompilationException $e) {
69
+		}
70
+		$output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
71
+		if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
72
+			$output .= substr($content, strlen(Compiler::PHP_OPEN));
73
+		} else {
74
+			$output .= Compiler::PHP_CLOSE . $content;
75
+		}
76
+		if (substr($output, - strlen(Compiler::PHP_CLOSE)) == Compiler::PHP_CLOSE) {
77
+			$output = substr($output, 0, - strlen(Compiler::PHP_CLOSE));
78
+		} else {
79
+			$output .= Compiler::PHP_OPEN;
80
+		}
81
+		$output .= "\n}" . Compiler::PHP_CLOSE;
82 82
 
83
-        return $output;
84
-    }
83
+		return $output;
84
+	}
85 85
 
86
-    /**
87
-     * @param $output
88
-     * @param $dynamicId
89
-     * @param $compiledFile
90
-     *
91
-     * @return mixed|string
92
-     */
93
-    public static function unescape($output, $dynamicId, $compiledFile)
94
-    {
95
-        $output = preg_replace_callback('/<dwoo:dynamic_(' . $dynamicId . ')>(.+?)<\/dwoo:dynamic_' . $dynamicId . '>/s', array(
96
-            'self',
97
-            'unescapePhp'
98
-        ), $output, - 1, $count);
99
-        // re-add the includes on top of the file
100
-        if ($count && preg_match('#/\* template head \*/(.+?)/\* end template head \*/#s', file_get_contents($compiledFile), $m)) {
101
-            $output = '<?php ' . $m[1] . ' ?>' . $output;
102
-        }
86
+	/**
87
+	 * @param $output
88
+	 * @param $dynamicId
89
+	 * @param $compiledFile
90
+	 *
91
+	 * @return mixed|string
92
+	 */
93
+	public static function unescape($output, $dynamicId, $compiledFile)
94
+	{
95
+		$output = preg_replace_callback('/<dwoo:dynamic_(' . $dynamicId . ')>(.+?)<\/dwoo:dynamic_' . $dynamicId . '>/s', array(
96
+			'self',
97
+			'unescapePhp'
98
+		), $output, - 1, $count);
99
+		// re-add the includes on top of the file
100
+		if ($count && preg_match('#/\* template head \*/(.+?)/\* end template head \*/#s', file_get_contents($compiledFile), $m)) {
101
+			$output = '<?php ' . $m[1] . ' ?>' . $output;
102
+		}
103 103
 
104
-        return $output;
105
-    }
104
+		return $output;
105
+	}
106 106
 
107
-    /**
108
-     * @param $match
109
-     *
110
-     * @return mixed
111
-     */
112
-    public static function unescapePhp($match)
113
-    {
114
-        return preg_replace('{<\?php /\*' . $match[1] . '\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
115
-    }
107
+	/**
108
+	 * @param $match
109
+	 *
110
+	 * @return mixed
111
+	 */
112
+	public static function unescapePhp($match)
113
+	{
114
+		return preg_replace('{<\?php /\*' . $match[1] . '\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
115
+	}
116 116
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -67,18 +67,18 @@  discard block
 block discarded – undo
67 67
         }
68 68
         catch (CompilationException $e) {
69 69
         }
70
-        $output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
70
+        $output = Compiler::PHP_OPEN.'if($doCache) {'."\n\t".'echo \'<dwoo:dynamic_\'.$dynamicId.\'>'.str_replace('\'', '\\\'', $content).'</dwoo:dynamic_\'.$dynamicId.\'>\';'."\n} else {\n\t";
71 71
         if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
72 72
             $output .= substr($content, strlen(Compiler::PHP_OPEN));
73 73
         } else {
74
-            $output .= Compiler::PHP_CLOSE . $content;
74
+            $output .= Compiler::PHP_CLOSE.$content;
75 75
         }
76 76
         if (substr($output, - strlen(Compiler::PHP_CLOSE)) == Compiler::PHP_CLOSE) {
77 77
             $output = substr($output, 0, - strlen(Compiler::PHP_CLOSE));
78 78
         } else {
79 79
             $output .= Compiler::PHP_OPEN;
80 80
         }
81
-        $output .= "\n}" . Compiler::PHP_CLOSE;
81
+        $output .= "\n}".Compiler::PHP_CLOSE;
82 82
 
83 83
         return $output;
84 84
     }
@@ -92,13 +92,13 @@  discard block
 block discarded – undo
92 92
      */
93 93
     public static function unescape($output, $dynamicId, $compiledFile)
94 94
     {
95
-        $output = preg_replace_callback('/<dwoo:dynamic_(' . $dynamicId . ')>(.+?)<\/dwoo:dynamic_' . $dynamicId . '>/s', array(
95
+        $output = preg_replace_callback('/<dwoo:dynamic_('.$dynamicId.')>(.+?)<\/dwoo:dynamic_'.$dynamicId.'>/s', array(
96 96
             'self',
97 97
             'unescapePhp'
98 98
         ), $output, - 1, $count);
99 99
         // re-add the includes on top of the file
100 100
         if ($count && preg_match('#/\* template head \*/(.+?)/\* end template head \*/#s', file_get_contents($compiledFile), $m)) {
101
-            $output = '<?php ' . $m[1] . ' ?>' . $output;
101
+            $output = '<?php '.$m[1].' ?>'.$output;
102 102
         }
103 103
 
104 104
         return $output;
@@ -111,6 +111,6 @@  discard block
 block discarded – undo
111 111
      */
112 112
     public static function unescapePhp($match)
113 113
     {
114
-        return preg_replace('{<\?php /\*' . $match[1] . '\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
114
+        return preg_replace('{<\?php /\*'.$match[1].'\*/ echo \'(.+?)\'; \?>}s', '$1', $match[2]);
115 115
     }
116 116
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -64,8 +64,7 @@
 block discarded – undo
64 64
             $compiler->findBlock('dynamic');
65 65
 
66 66
             return $content;
67
-        }
68
-        catch (CompilationException $e) {
67
+        } catch (CompilationException $e) {
69 68
         }
70 69
         $output = Compiler::PHP_OPEN . 'if($doCache) {' . "\n\t" . 'echo \'<dwoo:dynamic_\'.$dynamicId.\'>' . str_replace('\'', '\\\'', $content) . '</dwoo:dynamic_\'.$dynamicId.\'>\';' . "\n} else {\n\t";
71 70
         if (substr($content, 0, strlen(Compiler::PHP_OPEN)) == Compiler::PHP_OPEN) {
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Blocks/PluginStrip.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -59,7 +59,7 @@
 block discarded – undo
59 59
      * @param string   $append
60 60
      * @param string   $content
61 61
      *
62
-     * @return mixed|string
62
+     * @return string
63 63
      */
64 64
     public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
65 65
     {
Please login to merge, or discard this patch.
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -31,59 +31,59 @@
 block discarded – undo
31 31
  */
32 32
 class PluginStrip extends BlockPlugin implements ICompilableBlock
33 33
 {
34
-    /**
35
-     * @param string $mode
36
-     */
37
-    public function init($mode = 'default')
38
-    {
39
-    }
34
+	/**
35
+	 * @param string $mode
36
+	 */
37
+	public function init($mode = 'default')
38
+	{
39
+	}
40 40
 
41
-    /**
42
-     * @param Compiler $compiler
43
-     * @param array    $params
44
-     * @param string   $prepend
45
-     * @param string   $append
46
-     * @param string   $type
47
-     *
48
-     * @return string
49
-     */
50
-    public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
51
-    {
52
-        return '';
53
-    }
41
+	/**
42
+	 * @param Compiler $compiler
43
+	 * @param array    $params
44
+	 * @param string   $prepend
45
+	 * @param string   $append
46
+	 * @param string   $type
47
+	 *
48
+	 * @return string
49
+	 */
50
+	public static function preProcessing(Compiler $compiler, array $params, $prepend, $append, $type)
51
+	{
52
+		return '';
53
+	}
54 54
 
55
-    /**
56
-     * @param Compiler $compiler
57
-     * @param array    $params
58
-     * @param string   $prepend
59
-     * @param string   $append
60
-     * @param string   $content
61
-     *
62
-     * @return mixed|string
63
-     */
64
-    public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
65
-    {
66
-        $params = $compiler->getCompiledParams($params);
55
+	/**
56
+	 * @param Compiler $compiler
57
+	 * @param array    $params
58
+	 * @param string   $prepend
59
+	 * @param string   $append
60
+	 * @param string   $content
61
+	 *
62
+	 * @return mixed|string
63
+	 */
64
+	public static function postProcessing(Compiler $compiler, array $params, $prepend, $append, $content)
65
+	{
66
+		$params = $compiler->getCompiledParams($params);
67 67
 
68
-        $mode = trim($params['mode'], '"\'');
69
-        switch ($mode) {
70
-            case 'js':
71
-            case 'javascript':
72
-                $content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
68
+		$mode = trim($params['mode'], '"\'');
69
+		switch ($mode) {
70
+			case 'js':
71
+			case 'javascript':
72
+				$content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
73 73
 
74
-            case 'default':
75
-            default:
76
-        }
77
-        $content = preg_replace(array(
78
-            "/\n/",
79
-            "/\r/",
80
-            '/(<\?(?:php)?|<%)\s*/'
81
-        ), array(
82
-            '',
83
-            '',
84
-            '$1 '
85
-        ), preg_replace('#^\s*(.+?)\s*$#m', '$1', $content));
74
+			case 'default':
75
+			default:
76
+		}
77
+		$content = preg_replace(array(
78
+			"/\n/",
79
+			"/\r/",
80
+			'/(<\?(?:php)?|<%)\s*/'
81
+		), array(
82
+			'',
83
+			'',
84
+			'$1 '
85
+		), preg_replace('#^\s*(.+?)\s*$#m', '$1', $content));
86 86
 
87
-        return $content;
88
-    }
87
+		return $content;
88
+	}
89 89
 }
Please login to merge, or discard this patch.
Switch Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -67,12 +67,12 @@
 block discarded – undo
67 67
 
68 68
         $mode = trim($params['mode'], '"\'');
69 69
         switch ($mode) {
70
-            case 'js':
71
-            case 'javascript':
72
-                $content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
70
+        case 'js':
71
+        case 'javascript':
72
+            $content = preg_replace('#(?<!:)//\s[^\r\n]*|/\*.*?\*/#s', '', $content);
73 73
 
74
-            case 'default':
75
-            default:
74
+        case 'default':
75
+        default:
76 76
         }
77 77
         $content = preg_replace(array(
78 78
             "/\n/",
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Functions/PluginDump.php 3 patches
Doc Comments   +6 added lines patch added patch discarded remove patch
@@ -86,6 +86,9 @@  discard block
 block discarded – undo
86 86
         return $out;
87 87
     }
88 88
 
89
+    /**
90
+     * @param string $i
91
+     */
89 92
     protected function exportVar($i, $v)
90 93
     {
91 94
         if (is_string($v) || is_bool($v) || is_numeric($v)) {
@@ -99,6 +102,9 @@  discard block
 block discarded – undo
99 102
         }
100 103
     }
101 104
 
105
+    /**
106
+     * @param string $i
107
+     */
102 108
     protected function exportObj($i, $obj)
103 109
     {
104 110
         if (array_search($obj, $this->outputObjects, true) !== false) {
Please login to merge, or discard this patch.
Indentation   +145 added lines, -145 removed lines patch added patch discarded remove patch
@@ -29,156 +29,156 @@
 block discarded – undo
29 29
  */
30 30
 class PluginDump extends Plugin
31 31
 {
32
-    protected $outputObjects;
33
-    protected $outputMethods;
34
-
35
-    public function process($var = '$', $show_methods = false)
36
-    {
37
-        $this->outputMethods = $show_methods;
38
-        if ($var === '$') {
39
-            $var = $this->core->getData();
40
-            $out = '<div style="background:#aaa; padding:5px; margin:5px; color:#000;">data';
41
-        } else {
42
-            $out = '<div style="background:#aaa; padding:5px; margin:5px; color:#000;">dump';
43
-        }
44
-
45
-        $this->outputObjects = array();
46
-
47
-        if (!is_array($var)) {
48
-            if (is_object($var)) {
49
-                return $this->exportObj('', $var);
50
-            } else {
51
-                return $this->exportVar('', $var);
52
-            }
53
-        }
54
-
55
-        $scope = $this->core->getScope();
56
-
57
-        if ($var === $scope) {
58
-            $out .= ' (current scope): <div style="background:#ccc;">';
59
-        } else {
60
-            $out .= ':<div style="padding-left:20px;">';
61
-        }
62
-
63
-        $out .= $this->export($var, $scope);
64
-
65
-        return $out . '</div></div>';
66
-    }
67
-
68
-    protected function export($var, $scope)
69
-    {
70
-        $out = '';
71
-        foreach ($var as $i => $v) {
72
-            if (is_array($v) || (is_object($v) && $v instanceof Iterator)) {
73
-                $out .= $i . ' (' . (is_array($v) ? 'array' : 'object: ' . get_class($v)) . ')';
74
-                if ($v === $scope) {
75
-                    $out .= ' (current scope):<div style="background:#ccc;padding-left:20px;">' . $this->export($v, $scope) . '</div>';
76
-                } else {
77
-                    $out .= ':<div style="padding-left:20px;">' . $this->export($v, $scope) . '</div>';
78
-                }
79
-            } elseif (is_object($v)) {
80
-                $out .= $this->exportObj($i . ' (object: ' . get_class($v) . '):', $v);
81
-            } else {
82
-                $out .= $this->exportVar($i . ' = ', $v);
83
-            }
84
-        }
85
-
86
-        return $out;
87
-    }
88
-
89
-    protected function exportVar($i, $v)
90
-    {
91
-        if (is_string($v) || is_bool($v) || is_numeric($v)) {
92
-            return $i . htmlentities(var_export($v, true)) . '<br />';
93
-        } elseif (is_null($v)) {
94
-            return $i . 'null<br />';
95
-        } elseif (is_resource($v)) {
96
-            return $i . 'resource(' . get_resource_type($v) . ')<br />';
97
-        } else {
98
-            return $i . htmlentities(var_export($v, true)) . '<br />';
99
-        }
100
-    }
101
-
102
-    protected function exportObj($i, $obj)
103
-    {
104
-        if (array_search($obj, $this->outputObjects, true) !== false) {
105
-            return $i . ' [recursion, skipped]<br />';
106
-        }
107
-
108
-        $this->outputObjects[] = $obj;
109
-
110
-        $list = (array)$obj;
111
-
112
-        $protectedLength = strlen(get_class($obj)) + 2;
113
-
114
-        $out = array();
115
-
116
-        if ($this->outputMethods) {
117
-            $ref = new ReflectionObject($obj);
118
-
119
-            foreach ($ref->getMethods() as $method) {
120
-                if (!$method->isPublic()) {
121
-                    continue;
122
-                }
123
-
124
-                if (empty($out['method'])) {
125
-                    $out['method'] = '';
126
-                }
127
-
128
-                $params = array();
129
-                foreach ($method->getParameters() as $param) {
130
-                    $params[] = ($param->isPassedByReference() ? '&' : '') . '$' . $param->getName() . ($param->isOptional() ? ' = ' . var_export($param->getDefaultValue(), true) : '');
131
-                }
132
-
133
-                $out['method'] .= '(method) ' . $method->getName() . '(' . implode(', ', $params) . ')<br />';
134
-            }
135
-        }
136
-
137
-        foreach ($list as $attributeName => $attributeValue) {
138
-            if (property_exists($obj, $attributeName)) {
139
-                $key = 'public';
140
-            } elseif (substr($attributeName, 0, 3) === "\0*\0") {
141
-                $key           = 'protected';
142
-                $attributeName = substr($attributeName, 3);
143
-            } else {
144
-                $key           = 'private';
145
-                $attributeName = substr($attributeName, $protectedLength);
146
-            }
147
-
148
-            if (empty($out[$key])) {
149
-                $out[$key] = '';
150
-            }
151
-
152
-            $out[$key] .= '(' . $key . ') ';
153
-
154
-            if (is_array($attributeValue)) {
155
-                $out[$key] .= $attributeName . ' (array):<br />
32
+	protected $outputObjects;
33
+	protected $outputMethods;
34
+
35
+	public function process($var = '$', $show_methods = false)
36
+	{
37
+		$this->outputMethods = $show_methods;
38
+		if ($var === '$') {
39
+			$var = $this->core->getData();
40
+			$out = '<div style="background:#aaa; padding:5px; margin:5px; color:#000;">data';
41
+		} else {
42
+			$out = '<div style="background:#aaa; padding:5px; margin:5px; color:#000;">dump';
43
+		}
44
+
45
+		$this->outputObjects = array();
46
+
47
+		if (!is_array($var)) {
48
+			if (is_object($var)) {
49
+				return $this->exportObj('', $var);
50
+			} else {
51
+				return $this->exportVar('', $var);
52
+			}
53
+		}
54
+
55
+		$scope = $this->core->getScope();
56
+
57
+		if ($var === $scope) {
58
+			$out .= ' (current scope): <div style="background:#ccc;">';
59
+		} else {
60
+			$out .= ':<div style="padding-left:20px;">';
61
+		}
62
+
63
+		$out .= $this->export($var, $scope);
64
+
65
+		return $out . '</div></div>';
66
+	}
67
+
68
+	protected function export($var, $scope)
69
+	{
70
+		$out = '';
71
+		foreach ($var as $i => $v) {
72
+			if (is_array($v) || (is_object($v) && $v instanceof Iterator)) {
73
+				$out .= $i . ' (' . (is_array($v) ? 'array' : 'object: ' . get_class($v)) . ')';
74
+				if ($v === $scope) {
75
+					$out .= ' (current scope):<div style="background:#ccc;padding-left:20px;">' . $this->export($v, $scope) . '</div>';
76
+				} else {
77
+					$out .= ':<div style="padding-left:20px;">' . $this->export($v, $scope) . '</div>';
78
+				}
79
+			} elseif (is_object($v)) {
80
+				$out .= $this->exportObj($i . ' (object: ' . get_class($v) . '):', $v);
81
+			} else {
82
+				$out .= $this->exportVar($i . ' = ', $v);
83
+			}
84
+		}
85
+
86
+		return $out;
87
+	}
88
+
89
+	protected function exportVar($i, $v)
90
+	{
91
+		if (is_string($v) || is_bool($v) || is_numeric($v)) {
92
+			return $i . htmlentities(var_export($v, true)) . '<br />';
93
+		} elseif (is_null($v)) {
94
+			return $i . 'null<br />';
95
+		} elseif (is_resource($v)) {
96
+			return $i . 'resource(' . get_resource_type($v) . ')<br />';
97
+		} else {
98
+			return $i . htmlentities(var_export($v, true)) . '<br />';
99
+		}
100
+	}
101
+
102
+	protected function exportObj($i, $obj)
103
+	{
104
+		if (array_search($obj, $this->outputObjects, true) !== false) {
105
+			return $i . ' [recursion, skipped]<br />';
106
+		}
107
+
108
+		$this->outputObjects[] = $obj;
109
+
110
+		$list = (array)$obj;
111
+
112
+		$protectedLength = strlen(get_class($obj)) + 2;
113
+
114
+		$out = array();
115
+
116
+		if ($this->outputMethods) {
117
+			$ref = new ReflectionObject($obj);
118
+
119
+			foreach ($ref->getMethods() as $method) {
120
+				if (!$method->isPublic()) {
121
+					continue;
122
+				}
123
+
124
+				if (empty($out['method'])) {
125
+					$out['method'] = '';
126
+				}
127
+
128
+				$params = array();
129
+				foreach ($method->getParameters() as $param) {
130
+					$params[] = ($param->isPassedByReference() ? '&' : '') . '$' . $param->getName() . ($param->isOptional() ? ' = ' . var_export($param->getDefaultValue(), true) : '');
131
+				}
132
+
133
+				$out['method'] .= '(method) ' . $method->getName() . '(' . implode(', ', $params) . ')<br />';
134
+			}
135
+		}
136
+
137
+		foreach ($list as $attributeName => $attributeValue) {
138
+			if (property_exists($obj, $attributeName)) {
139
+				$key = 'public';
140
+			} elseif (substr($attributeName, 0, 3) === "\0*\0") {
141
+				$key           = 'protected';
142
+				$attributeName = substr($attributeName, 3);
143
+			} else {
144
+				$key           = 'private';
145
+				$attributeName = substr($attributeName, $protectedLength);
146
+			}
147
+
148
+			if (empty($out[$key])) {
149
+				$out[$key] = '';
150
+			}
151
+
152
+			$out[$key] .= '(' . $key . ') ';
153
+
154
+			if (is_array($attributeValue)) {
155
+				$out[$key] .= $attributeName . ' (array):<br />
156 156
 							<div style="padding-left:20px;">' . $this->export($attributeValue, false) . '</div>';
157
-            } elseif (is_object($attributeValue)) {
158
-                $out[$key] .= $this->exportObj($attributeName . ' (object: ' . get_class($attributeValue) . '):', $attributeValue);
159
-            } else {
160
-                $out[$key] .= $this->exportVar($attributeName . ' = ', $attributeValue);
161
-            }
162
-        }
157
+			} elseif (is_object($attributeValue)) {
158
+				$out[$key] .= $this->exportObj($attributeName . ' (object: ' . get_class($attributeValue) . '):', $attributeValue);
159
+			} else {
160
+				$out[$key] .= $this->exportVar($attributeName . ' = ', $attributeValue);
161
+			}
162
+		}
163 163
 
164
-        $return = $i . '<br /><div style="padding-left:20px;">';
164
+		$return = $i . '<br /><div style="padding-left:20px;">';
165 165
 
166
-        if (!empty($out['method'])) {
167
-            $return .= $out['method'];
168
-        }
166
+		if (!empty($out['method'])) {
167
+			$return .= $out['method'];
168
+		}
169 169
 
170
-        if (!empty($out['public'])) {
171
-            $return .= $out['public'];
172
-        }
170
+		if (!empty($out['public'])) {
171
+			$return .= $out['public'];
172
+		}
173 173
 
174
-        if (!empty($out['protected'])) {
175
-            $return .= $out['protected'];
176
-        }
174
+		if (!empty($out['protected'])) {
175
+			$return .= $out['protected'];
176
+		}
177 177
 
178
-        if (!empty($out['private'])) {
179
-            $return .= $out['private'];
180
-        }
178
+		if (!empty($out['private'])) {
179
+			$return .= $out['private'];
180
+		}
181 181
 
182
-        return $return . '</div>';
183
-    }
182
+		return $return . '</div>';
183
+	}
184 184
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -62,7 +62,7 @@  discard block
 block discarded – undo
62 62
 
63 63
         $out .= $this->export($var, $scope);
64 64
 
65
-        return $out . '</div></div>';
65
+        return $out.'</div></div>';
66 66
     }
67 67
 
68 68
     protected function export($var, $scope)
@@ -70,16 +70,16 @@  discard block
 block discarded – undo
70 70
         $out = '';
71 71
         foreach ($var as $i => $v) {
72 72
             if (is_array($v) || (is_object($v) && $v instanceof Iterator)) {
73
-                $out .= $i . ' (' . (is_array($v) ? 'array' : 'object: ' . get_class($v)) . ')';
73
+                $out .= $i.' ('.(is_array($v) ? 'array' : 'object: '.get_class($v)).')';
74 74
                 if ($v === $scope) {
75
-                    $out .= ' (current scope):<div style="background:#ccc;padding-left:20px;">' . $this->export($v, $scope) . '</div>';
75
+                    $out .= ' (current scope):<div style="background:#ccc;padding-left:20px;">'.$this->export($v, $scope).'</div>';
76 76
                 } else {
77
-                    $out .= ':<div style="padding-left:20px;">' . $this->export($v, $scope) . '</div>';
77
+                    $out .= ':<div style="padding-left:20px;">'.$this->export($v, $scope).'</div>';
78 78
                 }
79 79
             } elseif (is_object($v)) {
80
-                $out .= $this->exportObj($i . ' (object: ' . get_class($v) . '):', $v);
80
+                $out .= $this->exportObj($i.' (object: '.get_class($v).'):', $v);
81 81
             } else {
82
-                $out .= $this->exportVar($i . ' = ', $v);
82
+                $out .= $this->exportVar($i.' = ', $v);
83 83
             }
84 84
         }
85 85
 
@@ -89,27 +89,27 @@  discard block
 block discarded – undo
89 89
     protected function exportVar($i, $v)
90 90
     {
91 91
         if (is_string($v) || is_bool($v) || is_numeric($v)) {
92
-            return $i . htmlentities(var_export($v, true)) . '<br />';
92
+            return $i.htmlentities(var_export($v, true)).'<br />';
93 93
         } elseif (is_null($v)) {
94
-            return $i . 'null<br />';
94
+            return $i.'null<br />';
95 95
         } elseif (is_resource($v)) {
96
-            return $i . 'resource(' . get_resource_type($v) . ')<br />';
96
+            return $i.'resource('.get_resource_type($v).')<br />';
97 97
         } else {
98
-            return $i . htmlentities(var_export($v, true)) . '<br />';
98
+            return $i.htmlentities(var_export($v, true)).'<br />';
99 99
         }
100 100
     }
101 101
 
102 102
     protected function exportObj($i, $obj)
103 103
     {
104 104
         if (array_search($obj, $this->outputObjects, true) !== false) {
105
-            return $i . ' [recursion, skipped]<br />';
105
+            return $i.' [recursion, skipped]<br />';
106 106
         }
107 107
 
108 108
         $this->outputObjects[] = $obj;
109 109
 
110
-        $list = (array)$obj;
110
+        $list = (array) $obj;
111 111
 
112
-        $protectedLength = strlen(get_class($obj)) + 2;
112
+        $protectedLength = strlen(get_class($obj))+2;
113 113
 
114 114
         $out = array();
115 115
 
@@ -127,10 +127,10 @@  discard block
 block discarded – undo
127 127
 
128 128
                 $params = array();
129 129
                 foreach ($method->getParameters() as $param) {
130
-                    $params[] = ($param->isPassedByReference() ? '&' : '') . '$' . $param->getName() . ($param->isOptional() ? ' = ' . var_export($param->getDefaultValue(), true) : '');
130
+                    $params[] = ($param->isPassedByReference() ? '&' : '').'$'.$param->getName().($param->isOptional() ? ' = '.var_export($param->getDefaultValue(), true) : '');
131 131
                 }
132 132
 
133
-                $out['method'] .= '(method) ' . $method->getName() . '(' . implode(', ', $params) . ')<br />';
133
+                $out['method'] .= '(method) '.$method->getName().'('.implode(', ', $params).')<br />';
134 134
             }
135 135
         }
136 136
 
@@ -149,19 +149,19 @@  discard block
 block discarded – undo
149 149
                 $out[$key] = '';
150 150
             }
151 151
 
152
-            $out[$key] .= '(' . $key . ') ';
152
+            $out[$key] .= '('.$key.') ';
153 153
 
154 154
             if (is_array($attributeValue)) {
155
-                $out[$key] .= $attributeName . ' (array):<br />
156
-							<div style="padding-left:20px;">' . $this->export($attributeValue, false) . '</div>';
155
+                $out[$key] .= $attributeName.' (array):<br />
156
+							<div style="padding-left:20px;">' . $this->export($attributeValue, false).'</div>';
157 157
             } elseif (is_object($attributeValue)) {
158
-                $out[$key] .= $this->exportObj($attributeName . ' (object: ' . get_class($attributeValue) . '):', $attributeValue);
158
+                $out[$key] .= $this->exportObj($attributeName.' (object: '.get_class($attributeValue).'):', $attributeValue);
159 159
             } else {
160
-                $out[$key] .= $this->exportVar($attributeName . ' = ', $attributeValue);
160
+                $out[$key] .= $this->exportVar($attributeName.' = ', $attributeValue);
161 161
             }
162 162
         }
163 163
 
164
-        $return = $i . '<br /><div style="padding-left:20px;">';
164
+        $return = $i.'<br /><div style="padding-left:20px;">';
165 165
 
166 166
         if (!empty($out['method'])) {
167 167
             $return .= $out['method'];
@@ -179,6 +179,6 @@  discard block
 block discarded – undo
179 179
             $return .= $out['private'];
180 180
         }
181 181
 
182
-        return $return . '</div>';
182
+        return $return.'</div>';
183 183
     }
184 184
 }
Please login to merge, or discard this patch.
lib/Dwoo/Plugins/Processors/PluginSmartyCompatible.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -29,7 +29,7 @@
 block discarded – undo
29 29
     /**
30 30
      * @param string $input
31 31
      *
32
-     * @return mixed
32
+     * @return string
33 33
      */
34 34
     public function process($input)
35 35
     {
Please login to merge, or discard this patch.
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -26,69 +26,69 @@
 block discarded – undo
26 26
  */
27 27
 class PluginSmartyCompatible extends Processor
28 28
 {
29
-    /**
30
-     * @param string $input
31
-     *
32
-     * @return mixed
33
-     */
34
-    public function process($input)
35
-    {
36
-        list($l, $r) = $this->compiler->getDelimiters();
29
+	/**
30
+	 * @param string $input
31
+	 *
32
+	 * @return mixed
33
+	 */
34
+	public function process($input)
35
+	{
36
+		list($l, $r) = $this->compiler->getDelimiters();
37 37
 
38
-        $rl           = preg_quote($l, '/');
39
-        $rr           = preg_quote($r, '/');
40
-        $sectionParam = '(?:(name|loop|start|step|max|show)\s*=\s*(\S+))?\s*';
41
-        $input        = preg_replace_callback('/' . $rl . '\s*section ' . str_repeat($sectionParam, 6) . '\s*' . $rr . '(.+?)(?:' . $rl . '\s*sectionelse\s*' . $rr . '(.+?))?' . $rl . '\s*\/section\s*' . $rr . '/is', array(
42
-            $this,
43
-            'convertSection'
44
-        ), $input);
45
-        $input        = str_replace('$smarty.section.', '$smarty.for.', $input);
38
+		$rl           = preg_quote($l, '/');
39
+		$rr           = preg_quote($r, '/');
40
+		$sectionParam = '(?:(name|loop|start|step|max|show)\s*=\s*(\S+))?\s*';
41
+		$input        = preg_replace_callback('/' . $rl . '\s*section ' . str_repeat($sectionParam, 6) . '\s*' . $rr . '(.+?)(?:' . $rl . '\s*sectionelse\s*' . $rr . '(.+?))?' . $rl . '\s*\/section\s*' . $rr . '/is', array(
42
+			$this,
43
+			'convertSection'
44
+		), $input);
45
+		$input        = str_replace('$smarty.section.', '$smarty.for.', $input);
46 46
 
47
-        $smarty = array(
48
-            '/' . $rl . '\s*ldelim\s*' . $rr . '/',
49
-            '/' . $rl . '\s*rdelim\s*' . $rr . '/',
50
-            '/' . $rl . '\s*\$smarty\.ldelim\s*' . $rr . '/',
51
-            '/' . $rl . '\s*\$smarty\.rdelim\s*' . $rr . '/',
52
-            '/\$smarty\./',
53
-            '/' . $rl . '\s*php\s*' . $rr . '/',
54
-            '/' . $rl . '\s*\/php\s*' . $rr . '/',
55
-            '/\|(@?)strip(\||' . $rr . ')/',
56
-            '/' . $rl . '\s*sectionelse\s*' . $rr . '/',
57
-        );
47
+		$smarty = array(
48
+			'/' . $rl . '\s*ldelim\s*' . $rr . '/',
49
+			'/' . $rl . '\s*rdelim\s*' . $rr . '/',
50
+			'/' . $rl . '\s*\$smarty\.ldelim\s*' . $rr . '/',
51
+			'/' . $rl . '\s*\$smarty\.rdelim\s*' . $rr . '/',
52
+			'/\$smarty\./',
53
+			'/' . $rl . '\s*php\s*' . $rr . '/',
54
+			'/' . $rl . '\s*\/php\s*' . $rr . '/',
55
+			'/\|(@?)strip(\||' . $rr . ')/',
56
+			'/' . $rl . '\s*sectionelse\s*' . $rr . '/',
57
+		);
58 58
 
59
-        $dwoo = array(
60
-            '\\' . $l,
61
-            $r,
62
-            '\\' . $l,
63
-            $r,
64
-            '$dwoo.',
65
-            '<?php ',
66
-            ' ?>',
67
-            '|$1whitespace$2',
68
-            $l . 'else' . $r,
69
-        );
59
+		$dwoo = array(
60
+			'\\' . $l,
61
+			$r,
62
+			'\\' . $l,
63
+			$r,
64
+			'$dwoo.',
65
+			'<?php ',
66
+			' ?>',
67
+			'|$1whitespace$2',
68
+			$l . 'else' . $r,
69
+		);
70 70
 
71
-        if (preg_match('{\|@([a-z][a-z0-9_]*)}i', $input, $matches)) {
72
-            trigger_error('The Smarty Compatibility Module has detected that you use |@' . $matches[1] . ' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
73
-        }
71
+		if (preg_match('{\|@([a-z][a-z0-9_]*)}i', $input, $matches)) {
72
+			trigger_error('The Smarty Compatibility Module has detected that you use |@' . $matches[1] . ' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
73
+		}
74 74
 
75
-        return preg_replace($smarty, $dwoo, $input);
76
-    }
75
+		return preg_replace($smarty, $dwoo, $input);
76
+	}
77 77
 
78
-    /**
79
-     * @param array $matches
80
-     *
81
-     * @return mixed
82
-     */
83
-    protected function convertSection(array $matches)
84
-    {
85
-        $params = array();
86
-        $index  = 1;
87
-        while (!empty($matches[$index]) && $index < 13) {
88
-            $params[$matches[$index]] = $matches[$index + 1];
89
-            $index += 2;
90
-        }
78
+	/**
79
+	 * @param array $matches
80
+	 *
81
+	 * @return mixed
82
+	 */
83
+	protected function convertSection(array $matches)
84
+	{
85
+		$params = array();
86
+		$index  = 1;
87
+		while (!empty($matches[$index]) && $index < 13) {
88
+			$params[$matches[$index]] = $matches[$index + 1];
89
+			$index += 2;
90
+		}
91 91
 
92
-        return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
93
-    }
92
+		return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
93
+	}
94 94
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -38,38 +38,38 @@  discard block
 block discarded – undo
38 38
         $rl           = preg_quote($l, '/');
39 39
         $rr           = preg_quote($r, '/');
40 40
         $sectionParam = '(?:(name|loop|start|step|max|show)\s*=\s*(\S+))?\s*';
41
-        $input        = preg_replace_callback('/' . $rl . '\s*section ' . str_repeat($sectionParam, 6) . '\s*' . $rr . '(.+?)(?:' . $rl . '\s*sectionelse\s*' . $rr . '(.+?))?' . $rl . '\s*\/section\s*' . $rr . '/is', array(
41
+        $input        = preg_replace_callback('/'.$rl.'\s*section '.str_repeat($sectionParam, 6).'\s*'.$rr.'(.+?)(?:'.$rl.'\s*sectionelse\s*'.$rr.'(.+?))?'.$rl.'\s*\/section\s*'.$rr.'/is', array(
42 42
             $this,
43 43
             'convertSection'
44 44
         ), $input);
45
-        $input        = str_replace('$smarty.section.', '$smarty.for.', $input);
45
+        $input = str_replace('$smarty.section.', '$smarty.for.', $input);
46 46
 
47 47
         $smarty = array(
48
-            '/' . $rl . '\s*ldelim\s*' . $rr . '/',
49
-            '/' . $rl . '\s*rdelim\s*' . $rr . '/',
50
-            '/' . $rl . '\s*\$smarty\.ldelim\s*' . $rr . '/',
51
-            '/' . $rl . '\s*\$smarty\.rdelim\s*' . $rr . '/',
48
+            '/'.$rl.'\s*ldelim\s*'.$rr.'/',
49
+            '/'.$rl.'\s*rdelim\s*'.$rr.'/',
50
+            '/'.$rl.'\s*\$smarty\.ldelim\s*'.$rr.'/',
51
+            '/'.$rl.'\s*\$smarty\.rdelim\s*'.$rr.'/',
52 52
             '/\$smarty\./',
53
-            '/' . $rl . '\s*php\s*' . $rr . '/',
54
-            '/' . $rl . '\s*\/php\s*' . $rr . '/',
55
-            '/\|(@?)strip(\||' . $rr . ')/',
56
-            '/' . $rl . '\s*sectionelse\s*' . $rr . '/',
53
+            '/'.$rl.'\s*php\s*'.$rr.'/',
54
+            '/'.$rl.'\s*\/php\s*'.$rr.'/',
55
+            '/\|(@?)strip(\||'.$rr.')/',
56
+            '/'.$rl.'\s*sectionelse\s*'.$rr.'/',
57 57
         );
58 58
 
59 59
         $dwoo = array(
60
-            '\\' . $l,
60
+            '\\'.$l,
61 61
             $r,
62
-            '\\' . $l,
62
+            '\\'.$l,
63 63
             $r,
64 64
             '$dwoo.',
65 65
             '<?php ',
66 66
             ' ?>',
67 67
             '|$1whitespace$2',
68
-            $l . 'else' . $r,
68
+            $l.'else'.$r,
69 69
         );
70 70
 
71 71
         if (preg_match('{\|@([a-z][a-z0-9_]*)}i', $input, $matches)) {
72
-            trigger_error('The Smarty Compatibility Module has detected that you use |@' . $matches[1] . ' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
72
+            trigger_error('The Smarty Compatibility Module has detected that you use |@'.$matches[1].' in your template, this might lead to problems as Dwoo interprets the @ operator differently than Smarty, see http://wiki.dwoo.org/index.php/Syntax#The_.40_Operator', E_USER_NOTICE);
73 73
         }
74 74
 
75 75
         return preg_replace($smarty, $dwoo, $input);
@@ -85,10 +85,10 @@  discard block
 block discarded – undo
85 85
         $params = array();
86 86
         $index  = 1;
87 87
         while (!empty($matches[$index]) && $index < 13) {
88
-            $params[$matches[$index]] = $matches[$index + 1];
88
+            $params[$matches[$index]] = $matches[$index+1];
89 89
             $index += 2;
90 90
         }
91 91
 
92
-        return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
92
+        return str_replace('['.trim($params['name'], '"\'').']', '[$'.trim($params['name'], '"\'').']', $matches[0]);
93 93
     }
94 94
 }
Please login to merge, or discard this patch.