Test Failed
Pull Request — 1.2 (#90)
by
unknown
05:25
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
@@ -19,88 +19,88 @@
 block discarded – undo
19 19
  */
20 20
 class Dwoo_Adapters_ZendFramework_PluginProxy implements Dwoo_IPluginProxy
21 21
 {
22
-    /**
23
-     * reference to the zend view owning this proxy.
24
-     *
25
-     * @var Zend_View_Interface
26
-     */
27
-    public $view;
22
+	/**
23
+	 * reference to the zend view owning this proxy.
24
+	 *
25
+	 * @var Zend_View_Interface
26
+	 */
27
+	public $view;
28 28
 
29
-    /**
30
-     * Dwoo_Adapters_ZendFramework_PluginProxy's constructor.
31
-     *
32
-     * @param Zend_View_Interface $view
33
-     */
34
-    public function __construct(Zend_View_Interface $view)
35
-    {
36
-        $this->view = $view;
37
-    }
29
+	/**
30
+	 * Dwoo_Adapters_ZendFramework_PluginProxy's constructor.
31
+	 *
32
+	 * @param Zend_View_Interface $view
33
+	 */
34
+	public function __construct(Zend_View_Interface $view)
35
+	{
36
+		$this->view = $view;
37
+	}
38 38
 
39
-    /**
40
-     * Called from Dwoo_Compiler to check if the requested plugin is available.
41
-     *
42
-     * @param string $name
43
-     *
44
-     * @return bool
45
-     */
46
-    public function handles($name)
47
-    {
48
-        try {
49
-            $this->view->getHelper($name);
50
-        } catch (Zend_Loader_PluginLoader_Exception $e) {
51
-            return false;
52
-        }
39
+	/**
40
+	 * Called from Dwoo_Compiler to check if the requested plugin is available.
41
+	 *
42
+	 * @param string $name
43
+	 *
44
+	 * @return bool
45
+	 */
46
+	public function handles($name)
47
+	{
48
+		try {
49
+			$this->view->getHelper($name);
50
+		} catch (Zend_Loader_PluginLoader_Exception $e) {
51
+			return false;
52
+		}
53 53
 
54
-        return true;
55
-    }
54
+		return true;
55
+	}
56 56
 
57
-    /**
58
-     * returns the code (as a string) to call the plugin
59
-     * (this will be executed at runtime inside the Dwoo class).
60
-     *
61
-     * @param string $name   the plugin name
62
-     * @param array  $params a parameter array, array key "*" is the rest array
63
-     *
64
-     * @return string
65
-     */
66
-    public function getCode($name, $params)
67
-    {
68
-        return '$this->getPluginProxy()->view->'.$name.'('.Dwoo_Compiler::implode_r($params).')';
69
-    }
57
+	/**
58
+	 * returns the code (as a string) to call the plugin
59
+	 * (this will be executed at runtime inside the Dwoo class).
60
+	 *
61
+	 * @param string $name   the plugin name
62
+	 * @param array  $params a parameter array, array key "*" is the rest array
63
+	 *
64
+	 * @return string
65
+	 */
66
+	public function getCode($name, $params)
67
+	{
68
+		return '$this->getPluginProxy()->view->'.$name.'('.Dwoo_Compiler::implode_r($params).')';
69
+	}
70 70
 
71
-    /**
72
-     * returns a callback to the plugin, this is used with the reflection API to
73
-     * find out about the plugin's parameter names etc.
74
-     *
75
-     * should you need a rest array (i.e. for ZendFramework helpers) without the
76
-     * possibility to edit the plugin's code, you can provide a callback to some
77
-     * other function with the correct parameter signature, i.e. :
78
-     * <code>
79
-     * return array($this, "callbackHelper");
80
-     * // and callbackHelper would be as such:
81
-     * public function callbackHelper(array $rest=array()){}
82
-     * </code>
83
-     *
84
-     * @param string $name the plugin name
85
-     *
86
-     * @return callback
87
-     */
88
-    public function getCallback($name)
89
-    {
90
-        return array($this->view->getHelper($name), $name);
91
-    }
71
+	/**
72
+	 * returns a callback to the plugin, this is used with the reflection API to
73
+	 * find out about the plugin's parameter names etc.
74
+	 *
75
+	 * should you need a rest array (i.e. for ZendFramework helpers) without the
76
+	 * possibility to edit the plugin's code, you can provide a callback to some
77
+	 * other function with the correct parameter signature, i.e. :
78
+	 * <code>
79
+	 * return array($this, "callbackHelper");
80
+	 * // and callbackHelper would be as such:
81
+	 * public function callbackHelper(array $rest=array()){}
82
+	 * </code>
83
+	 *
84
+	 * @param string $name the plugin name
85
+	 *
86
+	 * @return callback
87
+	 */
88
+	public function getCallback($name)
89
+	{
90
+		return array($this->view->getHelper($name), $name);
91
+	}
92 92
 
93
-    /**
94
-     * returns some code that will check if the plugin is loaded and if not load it
95
-     * this is optional, if your plugins are autoloaded or whatever, just return an
96
-     * empty string.
97
-     *
98
-     * @param string $name the plugin name
99
-     *
100
-     * @return string
101
-     */
102
-    public function getLoader($name)
103
-    {
104
-        return '';
105
-    }
93
+	/**
94
+	 * returns some code that will check if the plugin is loaded and if not load it
95
+	 * this is optional, if your plugins are autoloaded or whatever, just return an
96
+	 * empty string.
97
+	 *
98
+	 * @param string $name the plugin name
99
+	 *
100
+	 * @return string
101
+	 */
102
+	public function getLoader($name)
103
+	{
104
+		return '';
105
+	}
106 106
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/CakePHP/dwoo.php 1 patch
Indentation   +113 added lines, -113 removed lines patch added patch discarded remove patch
@@ -42,118 +42,118 @@
 block discarded – undo
42 42
  */
43 43
 class DwooView extends View
44 44
 {
45
-    protected $_sv_template_dir;
46
-    protected $_sv_layout_dir;
47
-    protected $_sv_compile_dir;
48
-    protected $_sv_cache_dir;
49
-    protected $_sv_compile_id;
50
-
51
-    protected $_dwoo;
52
-
53
-    public $sv_processedTpl;
45
+	protected $_sv_template_dir;
46
+	protected $_sv_layout_dir;
47
+	protected $_sv_compile_dir;
48
+	protected $_sv_cache_dir;
49
+	protected $_sv_compile_id;
50
+
51
+	protected $_dwoo;
52
+
53
+	public $sv_processedTpl;
54 54
 
55
-    public function __construct(&$controller)
56
-    {
57
-        parent::__construct($controller);
58
-
59
-        $this->ext = '.tpl';
60
-
61
-        $this->_sv_template_dir = array(
62
-            VIEWS.$this->viewPath.DS.$this->subDir,
63
-            VIEWS.$this->viewPath,
64
-            VIEWS,
65
-        );
66
-
67
-        $this->_sv_layout_dir = array(
68
-            LAYOUTS.$this->subDir,
69
-            VIEWS,
70
-        );
71
-
72
-        $this->_sv_compile_dir = TMP.'dwoo'.DS.'compile';
73
-        $this->_sv_cache_dir = TMP.'dwoo'.DS.'cache';
74
-
75
-        $this->_dwoo = new Dwoo_Core($this->_sv_compile_dir, $this->_sv_cache_dir);
76
-
77
-        $this->_sv_compile_id = $controller->name;
78
-
79
-        $this->_dwoo->sv_this = $this;
80
-        $this->_dwoo->setSecurityPolicy();
81
-
82
-        return;
83
-    }
84
-
85
-    /**
86
-     * changes the template directory.
87
-     */
88
-    public function setTemplateDir($path = VIEW)
89
-    {
90
-        $old = $this->_sv_template_dir;
91
-        $this->_sv_template_dir = $path;
92
-
93
-        return $old;
94
-    }
95
-
96
-    public function getTemplateDir()
97
-    {
98
-        return $this->_sv_template_dir;
99
-    }
100
-
101
-    public function _render($___viewFn, $___data_for_view, $___play_safe = true, $loadHelpers = true)
102
-    {
103
-        // let's determine if this is a layout call or a template call
104
-        // and change the template dir accordingly
105
-        $layout = false;
106
-        if (isset($___data_for_view['content_for_layout'])) {
107
-            $this->_sv_template_dir = $this->_sv_layout_dir;
108
-            $layout = true;
109
-        }
110
-
111
-        $tpl = new Dwoo_Template_File($___viewFn);
112
-        $data = $___data_for_view;
113
-
114
-        $data['view'] = $this;
115
-
116
-        if ($this->helpers != false && $loadHelpers === true) {
117
-            $loadedHelpers = array();
118
-            $loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers);
119
-
120
-            foreach (array_keys($loadedHelpers) as $helper) {
121
-                $camelBackedHelper = strtolower(substr($helper, 0, 1)).substr($helper, 1);
122
-
123
-                ${$camelBackedHelper} = $loadedHelpers[$helper];
124
-
125
-                if (is_array(${$camelBackedHelper}->helpers) && !empty(${$camelBackedHelper}->helpers)) {
126
-                    $subHelpers = ${$camelBackedHelper}->helpers;
127
-                    foreach ($subHelpers as $subHelper) {
128
-                        ${$camelBackedHelper}->{$subHelper} = $loadedHelpers[$subHelper];
129
-                    }
130
-                }
131
-
132
-                if (isset($this->passedArgs)) {
133
-                    ${$camelBackedHelper}->passedArgs = $this->passedArgs;
134
-                }
135
-
136
-                $this->loaded[$camelBackedHelper] = ${$camelBackedHelper};
137
-
138
-                $data[$camelBackedHelper] = ${$camelBackedHelper};
139
-            }
140
-        }
141
-
142
-        if ($this->helpers != false && $loadHelpers === true) {
143
-            foreach ($loadedHelpers as $helper) {
144
-                if (is_object($helper)) {
145
-                    if (is_subclass_of($helper, 'Helper') || is_subclass_of($helper, 'helper')) {
146
-                        $helper->beforeRender();
147
-                    }
148
-                }
149
-            }
150
-        }
151
-
152
-        return $this->_dwoo->get($tpl, $data);
153
-    }
154
-
155
-    public function get()
156
-    {
157
-        return $this->_dwoo;
158
-    }
55
+	public function __construct(&$controller)
56
+	{
57
+		parent::__construct($controller);
58
+
59
+		$this->ext = '.tpl';
60
+
61
+		$this->_sv_template_dir = array(
62
+			VIEWS.$this->viewPath.DS.$this->subDir,
63
+			VIEWS.$this->viewPath,
64
+			VIEWS,
65
+		);
66
+
67
+		$this->_sv_layout_dir = array(
68
+			LAYOUTS.$this->subDir,
69
+			VIEWS,
70
+		);
71
+
72
+		$this->_sv_compile_dir = TMP.'dwoo'.DS.'compile';
73
+		$this->_sv_cache_dir = TMP.'dwoo'.DS.'cache';
74
+
75
+		$this->_dwoo = new Dwoo_Core($this->_sv_compile_dir, $this->_sv_cache_dir);
76
+
77
+		$this->_sv_compile_id = $controller->name;
78
+
79
+		$this->_dwoo->sv_this = $this;
80
+		$this->_dwoo->setSecurityPolicy();
81
+
82
+		return;
83
+	}
84
+
85
+	/**
86
+	 * changes the template directory.
87
+	 */
88
+	public function setTemplateDir($path = VIEW)
89
+	{
90
+		$old = $this->_sv_template_dir;
91
+		$this->_sv_template_dir = $path;
92
+
93
+		return $old;
94
+	}
95
+
96
+	public function getTemplateDir()
97
+	{
98
+		return $this->_sv_template_dir;
99
+	}
100
+
101
+	public function _render($___viewFn, $___data_for_view, $___play_safe = true, $loadHelpers = true)
102
+	{
103
+		// let's determine if this is a layout call or a template call
104
+		// and change the template dir accordingly
105
+		$layout = false;
106
+		if (isset($___data_for_view['content_for_layout'])) {
107
+			$this->_sv_template_dir = $this->_sv_layout_dir;
108
+			$layout = true;
109
+		}
110
+
111
+		$tpl = new Dwoo_Template_File($___viewFn);
112
+		$data = $___data_for_view;
113
+
114
+		$data['view'] = $this;
115
+
116
+		if ($this->helpers != false && $loadHelpers === true) {
117
+			$loadedHelpers = array();
118
+			$loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers);
119
+
120
+			foreach (array_keys($loadedHelpers) as $helper) {
121
+				$camelBackedHelper = strtolower(substr($helper, 0, 1)).substr($helper, 1);
122
+
123
+				${$camelBackedHelper} = $loadedHelpers[$helper];
124
+
125
+				if (is_array(${$camelBackedHelper}->helpers) && !empty(${$camelBackedHelper}->helpers)) {
126
+					$subHelpers = ${$camelBackedHelper}->helpers;
127
+					foreach ($subHelpers as $subHelper) {
128
+						${$camelBackedHelper}->{$subHelper} = $loadedHelpers[$subHelper];
129
+					}
130
+				}
131
+
132
+				if (isset($this->passedArgs)) {
133
+					${$camelBackedHelper}->passedArgs = $this->passedArgs;
134
+				}
135
+
136
+				$this->loaded[$camelBackedHelper] = ${$camelBackedHelper};
137
+
138
+				$data[$camelBackedHelper] = ${$camelBackedHelper};
139
+			}
140
+		}
141
+
142
+		if ($this->helpers != false && $loadHelpers === true) {
143
+			foreach ($loadedHelpers as $helper) {
144
+				if (is_object($helper)) {
145
+					if (is_subclass_of($helper, 'Helper') || is_subclass_of($helper, 'helper')) {
146
+						$helper->beforeRender();
147
+					}
148
+				}
149
+			}
150
+		}
151
+
152
+		return $this->_dwoo->get($tpl, $data);
153
+	}
154
+
155
+	public function get()
156
+	{
157
+		return $this->_dwoo;
158
+	}
159 159
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/Agavi/dwoo_plugins/t.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -16,5 +16,5 @@
 block discarded – undo
16 16
  */
17 17
 function Dwoo_Plugin_t_compile(Dwoo_Compiler $compiler, $string)
18 18
 {
19
-    return '$this->data[\'tm\']->_('.$string.')';
19
+	return '$this->data[\'tm\']->_('.$string.')';
20 20
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/Agavi/dwoo_plugins/url.php 1 patch
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -16,24 +16,24 @@
 block discarded – undo
16 16
  */
17 17
 function Dwoo_Plugin_url_compile(Dwoo_Compiler $compiler, $route = null, $params = null, $options = null, array $rest = array())
18 18
 {
19
-    if ($params == 'null') {
20
-        if (count($rest)) {
21
-            $params = array();
22
-            foreach ($rest as $k => $v) {
23
-                if (is_numeric($k)) {
24
-                    $params[] = $k.'=>'.$v;
25
-                } else {
26
-                    $params[] = '"'.$k.'"=>'.$v;
27
-                }
28
-            }
29
-            $params = 'array('.implode(', ', $params).')';
30
-        } else {
31
-            $params = 'array()';
32
-        }
33
-    }
34
-    if ($options == 'null') {
35
-        $options = 'array()';
36
-    }
19
+	if ($params == 'null') {
20
+		if (count($rest)) {
21
+			$params = array();
22
+			foreach ($rest as $k => $v) {
23
+				if (is_numeric($k)) {
24
+					$params[] = $k.'=>'.$v;
25
+				} else {
26
+					$params[] = '"'.$k.'"=>'.$v;
27
+				}
28
+			}
29
+			$params = 'array('.implode(', ', $params).')';
30
+		} else {
31
+			$params = 'array()';
32
+		}
33
+	}
34
+	if ($options == 'null') {
35
+		$options = 'array()';
36
+	}
37 37
 
38
-    return '$this->data[\'ro\']->gen('.$route.', '.$params.', '.$options.')';
38
+	return '$this->data[\'ro\']->gen('.$route.', '.$params.', '.$options.')';
39 39
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/CodeIgniter/controllers/dwoowelcome.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -16,15 +16,15 @@
 block discarded – undo
16 16
 
17 17
 class dwoowelcome extends Controller
18 18
 {
19
-    public function __construct()
20
-    {
21
-        parent::Controller();
22
-    }
19
+	public function __construct()
20
+	{
21
+		parent::Controller();
22
+	}
23 23
 
24
-    public function index()
25
-    {
26
-        $this->load->library('Dwootemplate');
27
-        $this->dwootemplate->assign('itshowlate', date('H:i:s'));
28
-        $this->dwootemplate->display('dwoowelcome.tpl');
29
-    }
24
+	public function index()
25
+	{
26
+		$this->load->library('Dwootemplate');
27
+		$this->dwootemplate->assign('itshowlate', date('H:i:s'));
28
+		$this->dwootemplate->display('dwoowelcome.tpl');
29
+	}
30 30
 }
Please login to merge, or discard this patch.
lib/Dwoo/Plugin.php 2 patches
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -79,24 +79,24 @@
 block discarded – undo
79 79
 
80 80
         $out = '';
81 81
         foreach ($params as $attr => $val) {
82
-            $out .= ' ' . $attr . '=';
82
+            $out .= ' '.$attr.'=';
83 83
             if (trim($val, '"\'') == '' || $val == 'null') {
84
-                $out .= str_replace($delim, '\\' . $delim, '""');
84
+                $out .= str_replace($delim, '\\'.$delim, '""');
85 85
             } elseif (substr($val, 0, 1) === $delim && substr($val, - 1) === $delim) {
86
-                $out .= str_replace($delim, '\\' . $delim, '"' . substr($val, 1, - 1) . '"');
86
+                $out .= str_replace($delim, '\\'.$delim, '"'.substr($val, 1, - 1).'"');
87 87
             } else {
88 88
                 if (!$compiler) {
89 89
                     // disable double encoding since it can not be determined if it was encoded
90
-                    $escapedVal = '.(is_string($tmp2=' . $val . ') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset, false) : $tmp2).';
90
+                    $escapedVal = '.(is_string($tmp2='.$val.') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset, false) : $tmp2).';
91 91
                 } elseif (!$compiler->getAutoEscape() || false === strpos($val, 'isset($this->scope')) {
92 92
                     // escape if auto escaping is disabled, or there was no variable in the string
93
-                    $escapedVal = '.(is_string($tmp2=' . $val . ') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset) : $tmp2).';
93
+                    $escapedVal = '.(is_string($tmp2='.$val.') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset) : $tmp2).';
94 94
                 } else {
95 95
                     // print as is
96
-                    $escapedVal = '.' . $val . '.';
96
+                    $escapedVal = '.'.$val.'.';
97 97
                 }
98 98
 
99
-                $out .= str_replace($delim, '\\' . $delim, '"') . $delim . $escapedVal . $delim . str_replace($delim, '\\' . $delim, '"');
99
+                $out .= str_replace($delim, '\\'.$delim, '"').$delim.$escapedVal.$delim.str_replace($delim, '\\'.$delim, '"');
100 100
             }
101 101
         }
102 102
 
Please login to merge, or discard this patch.
Indentation   +70 added lines, -70 removed lines patch added patch discarded remove patch
@@ -20,81 +20,81 @@
 block discarded – undo
20 20
  */
21 21
 abstract class Dwoo_Plugin
22 22
 {
23
-    /**
24
-     * The dwoo instance that runs this plugin.
25
-     *
26
-     * @var Dwoo
27
-     */
28
-    protected $dwoo;
23
+	/**
24
+	 * The dwoo instance that runs this plugin.
25
+	 *
26
+	 * @var Dwoo
27
+	 */
28
+	protected $dwoo;
29 29
 
30
-    /**
31
-     * Constructor, if you override it, call parent::__construct($dwoo); or assign
32
-     * the dwoo instance yourself if you need it.
33
-     *
34
-     * @param Dwoo_Core $dwoo the dwoo instance that runs this plugin
35
-     */
36
-    public function __construct(Dwoo_Core $dwoo)
37
-    {
38
-        $this->dwoo = $dwoo;
39
-    }
30
+	/**
31
+	 * Constructor, if you override it, call parent::__construct($dwoo); or assign
32
+	 * the dwoo instance yourself if you need it.
33
+	 *
34
+	 * @param Dwoo_Core $dwoo the dwoo instance that runs this plugin
35
+	 */
36
+	public function __construct(Dwoo_Core $dwoo)
37
+	{
38
+		$this->dwoo = $dwoo;
39
+	}
40 40
 
41
-    // plugins should always implement :
42
-    // public function process($arg, $arg, ...)
43
-    // or for block plugins :
44
-    // public function init($arg, $arg, ...)
41
+	// plugins should always implement :
42
+	// public function process($arg, $arg, ...)
43
+	// or for block plugins :
44
+	// public function init($arg, $arg, ...)
45 45
 
46
-    // this could be enforced with :
47
-    // abstract public function process(...);
48
-    // if my feature request gets enough interest one day
49
-    // see => http://bugs.php.net/bug.php?id=44043
46
+	// this could be enforced with :
47
+	// abstract public function process(...);
48
+	// if my feature request gets enough interest one day
49
+	// see => http://bugs.php.net/bug.php?id=44043
50 50
 
51
-    /**
52
-     * Utility function that converts an array of compiled parameters (or rest array) to a string of xml/html tag
53
-     * attributes. this is to be used in preProcessing or postProcessing functions, example :
54
-     *  $p = $compiler->getCompiledParams($params);
55
-     *  // get only the rest array as attributes
56
-     *  $attributes = Dwoo_Plugin::paramsToAttributes($p['*']);
57
-     *  // get all the parameters as attributes (if there is a rest array, it will be included)
58
-     *  $attributes = Dwoo_Plugin::paramsToAttributes($p);
59
-     *
60
-     * @param array         $params   an array of attributeName=>value items that will be compiled to be ready for
61
-     *                                inclusion in a php string
62
-     * @param string        $delim    the string delimiter you want to use (defaults to ')
63
-     * @param Dwoo_Compiler $compiler the compiler instance (optional for BC, but recommended to pass it for proper
64
-     *                                escaping behavior)
65
-     *
66
-     * @return string
67
-     */
68
-    public static function paramsToAttributes(array $params, $delim = '\'', Dwoo_Compiler $compiler = null)
69
-    {
70
-        if (isset($params['*'])) {
71
-            $params = array_merge($params, $params['*']);
72
-            unset($params['*']);
73
-        }
51
+	/**
52
+	 * Utility function that converts an array of compiled parameters (or rest array) to a string of xml/html tag
53
+	 * attributes. this is to be used in preProcessing or postProcessing functions, example :
54
+	 *  $p = $compiler->getCompiledParams($params);
55
+	 *  // get only the rest array as attributes
56
+	 *  $attributes = Dwoo_Plugin::paramsToAttributes($p['*']);
57
+	 *  // get all the parameters as attributes (if there is a rest array, it will be included)
58
+	 *  $attributes = Dwoo_Plugin::paramsToAttributes($p);
59
+	 *
60
+	 * @param array         $params   an array of attributeName=>value items that will be compiled to be ready for
61
+	 *                                inclusion in a php string
62
+	 * @param string        $delim    the string delimiter you want to use (defaults to ')
63
+	 * @param Dwoo_Compiler $compiler the compiler instance (optional for BC, but recommended to pass it for proper
64
+	 *                                escaping behavior)
65
+	 *
66
+	 * @return string
67
+	 */
68
+	public static function paramsToAttributes(array $params, $delim = '\'', Dwoo_Compiler $compiler = null)
69
+	{
70
+		if (isset($params['*'])) {
71
+			$params = array_merge($params, $params['*']);
72
+			unset($params['*']);
73
+		}
74 74
 
75
-        $out = '';
76
-        foreach ($params as $attr => $val) {
77
-            $out .= ' ' . $attr . '=';
78
-            if (trim($val, '"\'') == '' || $val == 'null') {
79
-                $out .= str_replace($delim, '\\' . $delim, '""');
80
-            } elseif (substr($val, 0, 1) === $delim && substr($val, - 1) === $delim) {
81
-                $out .= str_replace($delim, '\\' . $delim, '"' . substr($val, 1, - 1) . '"');
82
-            } else {
83
-                if (!$compiler) {
84
-                    // disable double encoding since it can not be determined if it was encoded
85
-                    $escapedVal = '.(is_string($tmp2=' . $val . ') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset, false) : $tmp2).';
86
-                } elseif (!$compiler->getAutoEscape() || false === strpos($val, 'isset($this->scope')) {
87
-                    // escape if auto escaping is disabled, or there was no variable in the string
88
-                    $escapedVal = '.(is_string($tmp2=' . $val . ') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset) : $tmp2).';
89
-                } else {
90
-                    // print as is
91
-                    $escapedVal = '.' . $val . '.';
92
-                }
75
+		$out = '';
76
+		foreach ($params as $attr => $val) {
77
+			$out .= ' ' . $attr . '=';
78
+			if (trim($val, '"\'') == '' || $val == 'null') {
79
+				$out .= str_replace($delim, '\\' . $delim, '""');
80
+			} elseif (substr($val, 0, 1) === $delim && substr($val, - 1) === $delim) {
81
+				$out .= str_replace($delim, '\\' . $delim, '"' . substr($val, 1, - 1) . '"');
82
+			} else {
83
+				if (!$compiler) {
84
+					// disable double encoding since it can not be determined if it was encoded
85
+					$escapedVal = '.(is_string($tmp2=' . $val . ') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset, false) : $tmp2).';
86
+				} elseif (!$compiler->getAutoEscape() || false === strpos($val, 'isset($this->scope')) {
87
+					// escape if auto escaping is disabled, or there was no variable in the string
88
+					$escapedVal = '.(is_string($tmp2=' . $val . ') ? htmlspecialchars($tmp2, ENT_QUOTES, $this->charset) : $tmp2).';
89
+				} else {
90
+					// print as is
91
+					$escapedVal = '.' . $val . '.';
92
+				}
93 93
 
94
-                $out .= str_replace($delim, '\\' . $delim, '"') . $delim . $escapedVal . $delim . str_replace($delim, '\\' . $delim, '"');
95
-            }
96
-        }
94
+				$out .= str_replace($delim, '\\' . $delim, '"') . $delim . $escapedVal . $delim . str_replace($delim, '\\' . $delim, '"');
95
+			}
96
+		}
97 97
 
98
-        return ltrim($out);
99
-    }
98
+		return ltrim($out);
99
+	}
100 100
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/CodeIgniter/libraries/Dwootemplate.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -95,7 +95,7 @@
 block discarded – undo
95 95
      * @param string $sTemplate
96 96
      * @param bool   $return
97 97
      *
98
-     * @return mixed
98
+     * @return null|string
99 99
      */
100 100
     public function display($sTemplate, $return = false)
101 101
     {
Please login to merge, or discard this patch.
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (!defined('BASEPATH')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 
7 7
 require 'dwoo/dwooAutoload.php';
@@ -26,154 +26,154 @@  discard block
 block discarded – undo
26 26
  */
27 27
 class Dwootemplate extends Dwoo_Core
28 28
 {
29
-    protected $dwoo_data = array();
30
-
31
-    /**
32
-     * Constructor for the DwooTemplate engine.
33
-     */
34
-    public function __construct()
35
-    {
36
-        // Call parents constructor
37
-        parent::__construct();
38
-
39
-        // Set the config settings
40
-        $this->initialize();
41
-
42
-        // Assign some defaults to dwoo
43
-        $CI = get_instance();
44
-        $this->dwoo_data = new Dwoo_Data();
45
-        $this->dwoo_data->js_files = array();
46
-        $this->dwoo_data->css_files = array();
47
-        $this->dwoo_data->CI = $CI;
48
-        $this->dwoo_data->site_url = $CI->config->site_url(); // so we can get the full path to CI easily
49
-        $this->dwoo_data->uniqid = uniqid();
50
-        $this->dwoo_data->timestamp = mktime();
51
-
52
-        log_message('debug', 'Dwoo Template Class Initialized');
53
-    }
54
-
55
-    /**
56
-     * Assign data to dwoo data object.
57
-     *
58
-     * @param string $key
59
-     * @param mixed  $value
60
-     */
61
-    public function assign($key, $value)
62
-    {
63
-        $this->dwoo_data->$key = $value;
64
-    }
65
-
66
-    /**
67
-     * Add Javascript files to template.
68
-     *
69
-     * @param string $js
70
-     */
71
-    public function add_js($js)
72
-    {
73
-        $current = $this->dwoo_data->js_files;
74
-        $current[] = $js;
75
-        $this->dwoo_data->js_files = $current;
76
-    }
77
-
78
-    /**
79
-     * Add Css stylesheets to template.
80
-     *
81
-     * @param string $css
82
-     */
83
-    public function add_css($css)
84
-    {
85
-        $current = $this->dwoo_data->css_files;
86
-        $current[] = $css;
87
-        $this->dwoo_data->css_files = $current;
88
-    }
89
-
90
-    /**
91
-     * Display or return the compiled template
92
-     * Since we assign the results to the standard CI output module
93
-     * you can also use the helper from CI in your templates!!
94
-     *
95
-     * @param string $sTemplate
96
-     * @param bool   $return
97
-     *
98
-     * @return mixed
99
-     */
100
-    public function display($sTemplate, $return = false)
101
-    {
102
-        // Start benchmark
103
-        $CI = get_instance();
104
-        $CI->benchmark->mark('dwoo_parse_start');
105
-
106
-        // Check if file exists
107
-        if (!file_exists($this->template_dir.$sTemplate)) {
108
-            $message = sprintf('Template file \'%s\' not found.', $sTemplate);
109
-            show_error($message);
110
-            log_message('error', $message);
111
-        }
112
-
113
-        // Create new template
114
-        $tpl = new Dwoo_Template_File($this->template_dir.$sTemplate);
115
-
116
-        // render the template
117
-        $template = $this->get($tpl, $this->dwoo_data);
118
-
119
-        // Finish benchmark
120
-        $CI->benchmark->mark('dwoo_parse_end');
121
-
122
-        // Return results or not ?
123
-        if ($return == false) {
124
-            $CI->output->final_output = $template;
125
-        } else {
126
-            return $template;
127
-        }
128
-    }
129
-
130
-    /**
131
-     * Toggle Codeigniter profiler on/off.
132
-     */
133
-    public function enable_profiler($toggle = true)
134
-    {
135
-        $CI = get_instance();
136
-        $CI->output->enable_profiler($toggle);
137
-    }
138
-
139
-    /**
140
-     * Set http header.
141
-     *
142
-     * @example $this->output->set_header("HTTP/1.1 200 OK");
143
-     * @example $this->output->set_header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_update).' GMT');
144
-     *
145
-     * @param string $header
146
-     */
147
-    public function set_header($header)
148
-    {
149
-        $CI = get_instance();
150
-        $CI->output->set_header($header);
151
-    }
152
-
153
-    /**
154
-     * Set status header.
155
-     *
156
-     * @example $this->output->set_status_header('401');
157
-     * @example // Sets the header as: Unauthorized
158
-     *
159
-     * @param string $header
160
-     */
161
-    public function set_status_header($header)
162
-    {
163
-        $CI = get_instance();
164
-        $CI->output->set_status_header($header);
165
-    }
166
-
167
-    /**
168
-     * Assign the dwootemplate config items to the instance.
169
-     */
170
-    private function initialize()
171
-    {
172
-        $CI = get_instance();
173
-        $CI->config->load('dwootemplate', true);
174
-        $config = $CI->config->item('dwootemplate');
175
-        foreach ($config as $key => $val) {
176
-            $this->$key = $val;
177
-        }
178
-    }
29
+	protected $dwoo_data = array();
30
+
31
+	/**
32
+	 * Constructor for the DwooTemplate engine.
33
+	 */
34
+	public function __construct()
35
+	{
36
+		// Call parents constructor
37
+		parent::__construct();
38
+
39
+		// Set the config settings
40
+		$this->initialize();
41
+
42
+		// Assign some defaults to dwoo
43
+		$CI = get_instance();
44
+		$this->dwoo_data = new Dwoo_Data();
45
+		$this->dwoo_data->js_files = array();
46
+		$this->dwoo_data->css_files = array();
47
+		$this->dwoo_data->CI = $CI;
48
+		$this->dwoo_data->site_url = $CI->config->site_url(); // so we can get the full path to CI easily
49
+		$this->dwoo_data->uniqid = uniqid();
50
+		$this->dwoo_data->timestamp = mktime();
51
+
52
+		log_message('debug', 'Dwoo Template Class Initialized');
53
+	}
54
+
55
+	/**
56
+	 * Assign data to dwoo data object.
57
+	 *
58
+	 * @param string $key
59
+	 * @param mixed  $value
60
+	 */
61
+	public function assign($key, $value)
62
+	{
63
+		$this->dwoo_data->$key = $value;
64
+	}
65
+
66
+	/**
67
+	 * Add Javascript files to template.
68
+	 *
69
+	 * @param string $js
70
+	 */
71
+	public function add_js($js)
72
+	{
73
+		$current = $this->dwoo_data->js_files;
74
+		$current[] = $js;
75
+		$this->dwoo_data->js_files = $current;
76
+	}
77
+
78
+	/**
79
+	 * Add Css stylesheets to template.
80
+	 *
81
+	 * @param string $css
82
+	 */
83
+	public function add_css($css)
84
+	{
85
+		$current = $this->dwoo_data->css_files;
86
+		$current[] = $css;
87
+		$this->dwoo_data->css_files = $current;
88
+	}
89
+
90
+	/**
91
+	 * Display or return the compiled template
92
+	 * Since we assign the results to the standard CI output module
93
+	 * you can also use the helper from CI in your templates!!
94
+	 *
95
+	 * @param string $sTemplate
96
+	 * @param bool   $return
97
+	 *
98
+	 * @return mixed
99
+	 */
100
+	public function display($sTemplate, $return = false)
101
+	{
102
+		// Start benchmark
103
+		$CI = get_instance();
104
+		$CI->benchmark->mark('dwoo_parse_start');
105
+
106
+		// Check if file exists
107
+		if (!file_exists($this->template_dir.$sTemplate)) {
108
+			$message = sprintf('Template file \'%s\' not found.', $sTemplate);
109
+			show_error($message);
110
+			log_message('error', $message);
111
+		}
112
+
113
+		// Create new template
114
+		$tpl = new Dwoo_Template_File($this->template_dir.$sTemplate);
115
+
116
+		// render the template
117
+		$template = $this->get($tpl, $this->dwoo_data);
118
+
119
+		// Finish benchmark
120
+		$CI->benchmark->mark('dwoo_parse_end');
121
+
122
+		// Return results or not ?
123
+		if ($return == false) {
124
+			$CI->output->final_output = $template;
125
+		} else {
126
+			return $template;
127
+		}
128
+	}
129
+
130
+	/**
131
+	 * Toggle Codeigniter profiler on/off.
132
+	 */
133
+	public function enable_profiler($toggle = true)
134
+	{
135
+		$CI = get_instance();
136
+		$CI->output->enable_profiler($toggle);
137
+	}
138
+
139
+	/**
140
+	 * Set http header.
141
+	 *
142
+	 * @example $this->output->set_header("HTTP/1.1 200 OK");
143
+	 * @example $this->output->set_header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_update).' GMT');
144
+	 *
145
+	 * @param string $header
146
+	 */
147
+	public function set_header($header)
148
+	{
149
+		$CI = get_instance();
150
+		$CI->output->set_header($header);
151
+	}
152
+
153
+	/**
154
+	 * Set status header.
155
+	 *
156
+	 * @example $this->output->set_status_header('401');
157
+	 * @example // Sets the header as: Unauthorized
158
+	 *
159
+	 * @param string $header
160
+	 */
161
+	public function set_status_header($header)
162
+	{
163
+		$CI = get_instance();
164
+		$CI->output->set_status_header($header);
165
+	}
166
+
167
+	/**
168
+	 * Assign the dwootemplate config items to the instance.
169
+	 */
170
+	private function initialize()
171
+	{
172
+		$CI = get_instance();
173
+		$CI->config->load('dwootemplate', true);
174
+		$config = $CI->config->item('dwootemplate');
175
+		foreach ($config as $key => $val) {
176
+			$this->$key = $val;
177
+		}
178
+	}
179 179
 }
Please login to merge, or discard this patch.
lib/Dwoo/Adapters/ZendFramework/View.php 2 patches
Doc Comments   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -87,7 +87,6 @@  discard block
 block discarded – undo
87 87
      *  - type class name or object for engine, dataProvider or compiler
88 88
      *  - any set* method (compileDir for setCompileDir ...)
89 89
      *
90
-     * @param array $options
91 90
      *
92 91
      * @return Dwoo_Adapters_ZendFramework_View
93 92
      */
@@ -279,6 +278,7 @@  discard block
 block discarded – undo
279 278
      * Sets Dwoo data object.
280 279
      *
281 280
      * @param string|Dwoo_Data Object or name of the class
281
+     * @param Dwoo_Data $data
282 282
      */
283 283
     public function setDataProvider($data)
284 284
     {
@@ -441,7 +441,6 @@  discard block
 block discarded – undo
441 441
      * Processes a view script and outputs it. Output is then
442 442
      * passed through filters.
443 443
      *
444
-     * @param string $name The script script name to process
445 444
      *
446 445
      * @return string The script output
447 446
      */
Please login to merge, or discard this patch.
Indentation   +503 added lines, -503 removed lines patch added patch discarded remove patch
@@ -20,507 +20,507 @@
 block discarded – undo
20 20
  */
21 21
 class Dwoo_Adapters_ZendFramework_View extends Zend_View_Abstract
22 22
 {
23
-    /**
24
-     * @var Dwoo
25
-     */
26
-    protected $_engine = null;
27
-
28
-    /**
29
-     * @var Dwoo_Data
30
-     */
31
-    protected $_dataProvider = null;
32
-
33
-    /**
34
-     * @var Dwoo_Compiler
35
-     */
36
-    protected $_compiler = null;
37
-
38
-    /**
39
-     * Changing Filter's scope to play nicely.
40
-     *
41
-     * @var array
42
-     */
43
-    protected $_filter = array();
44
-
45
-    /**
46
-     * @var string
47
-     */
48
-    protected $_templateFileClass = 'Dwoo_Template_File';
49
-
50
-    /**
51
-     * @var array
52
-     */
53
-    protected $_templateFileSettings = array();
54
-
55
-    /**
56
-     * @var Dwoo_IPluginProxy
57
-     */
58
-    protected $_pluginProxy = null;
59
-
60
-    /**
61
-     * Constructor method.
62
-     * See setOptions for $opt details.
63
-     *
64
-     * @see setOptions
65
-     *
66
-     * @param array|Zend_Config List of options or Zend_Config instance
67
-     */
68
-    public function __construct($opt = array())
69
-    {
70
-        if (is_array($opt)) {
71
-            $this->setOptions($opt);
72
-        } elseif ($opt instanceof Zend_Config) {
73
-            $this->setConfig($opt);
74
-        }
75
-
76
-        $this->init();
77
-    }
78
-
79
-    /**
80
-     * Set object state from options array
81
-     *  - engine        = engine class name|engine object|array of options for engine
82
-     *  - dataProvider  = data provider class name|data provider object|array of options for data provider
83
-     *  - compiler      = compiler class name|compiler object|array of options for compiler
84
-     *  - templateFile  =.
85
-     *
86
-     *  Array of options:
87
-     *  - type class name or object for engine, dataProvider or compiler
88
-     *  - any set* method (compileDir for setCompileDir ...)
89
-     *
90
-     * @param array $options
91
-     *
92
-     * @return Dwoo_Adapters_ZendFramework_View
93
-     */
94
-    public function setOptions(array $opt = array())
95
-    {
96
-        // Making sure that everything is loaded.
97
-        $classes = array('engine', 'dataProvider', 'compiler');
98
-
99
-        // Setting options to Dwoo objects...
100
-        foreach ($opt as $type => $settings) {
101
-            if (!method_exists($this, 'set'.$type)) {
102
-                throw new Dwoo_Exception("Unknown type $type");
103
-            }
104
-
105
-            if (is_string($settings) || is_object($settings)) {
106
-                call_user_func(array($this, 'set'.$type), $settings);
107
-            } elseif (is_array($settings)) {
108
-                // Set requested class
109
-                if (array_key_exists('type', $settings)) {
110
-                    call_user_func(array($this, 'set'.$type), $settings['type']);
111
-                }
112
-
113
-                if (in_array($type, $classes)) {
114
-                    // Call get so that the class is initialized
115
-                    $rel = call_user_func(array($this, 'get'.$type));
116
-
117
-                    // Call set*() methods so that all the settings are set.
118
-                    foreach ($settings as $method => $value) {
119
-                        if (method_exists($rel, 'set'.$method)) {
120
-                            call_user_func(array($rel, 'set'.$method), $value);
121
-                        }
122
-                    }
123
-                } elseif ('templateFile' == $type) {
124
-                    // Remember the settings for the templateFile
125
-                    $this->_templateFileSettings = $settings;
126
-                }
127
-            }
128
-        }
129
-    }
130
-
131
-    /**
132
-     * Set object state from Zend_Config object.
133
-     *
134
-     * @param Zend_Config $config
135
-     *
136
-     * @return Dwoo_Adapters_ZendFramework_View
137
-     */
138
-    public function setConfig(Zend_Config $config)
139
-    {
140
-        return $this->setOptions($config->toArray());
141
-    }
142
-
143
-    /**
144
-     * Called before template rendering.
145
-     *
146
-     * Binds plugin proxy to the Dwoo.
147
-     *
148
-     * @see Dwoo_Adapters_ZendFramework_View::getPluginProxy();
149
-     * @see Dwoo_Core::setPluginProxy();
150
-     */
151
-    protected function preRender()
152
-    {
153
-        $this->getEngine()->setPluginProxy($this->getPluginProxy());
154
-    }
155
-
156
-    /**
157
-     * Wraper for Dwoo_Data::__set()
158
-     * allows to assign variables using the object syntax.
159
-     *
160
-     * @see Dwoo_Data::__set()
161
-     *
162
-     * @param string $name  the variable name
163
-     * @param string $value the value to assign to it
164
-     */
165
-    public function __set($name, $value)
166
-    {
167
-        $this->getDataProvider()->__set($name, $value);
168
-    }
169
-
170
-    /**
171
-     * Sraper for Dwoo_Data::__get() allows to read variables using the object
172
-     * syntax.
173
-     *
174
-     * @see Dwoo_Data::__get()
175
-     *
176
-     * @param string $name the variable name
177
-     *
178
-     * @return mixed
179
-     */
180
-    public function __get($name)
181
-    {
182
-        return $this->getDataProvider()->__get($name);
183
-    }
184
-
185
-    /**
186
-     * Wraper for Dwoo_Data::__isset()
187
-     * supports calls to isset($dwooData->var).
188
-     *
189
-     * @see Dwoo_Data::__isset()
190
-     *
191
-     * @param string $name the variable name
192
-     */
193
-    public function __isset($name)
194
-    {
195
-        return $this->getDataProvider()->__isset($name);
196
-    }
197
-
198
-    /**
199
-     * Wraper for Dwoo_Data::_unset()
200
-     * supports unsetting variables using the object syntax.
201
-     *
202
-     * @see Dwoo_Data::__unset()
203
-     *
204
-     * @param string $name the variable name
205
-     */
206
-    public function __unset($name)
207
-    {
208
-        $this->getDataProvider()->__unset($name);
209
-    }
210
-
211
-    /**
212
-     * Catches clone request and clones data provider.
213
-     */
214
-    public function __clone()
215
-    {
216
-        $this->setDataProvider(clone $this->getDataProvider());
217
-    }
218
-
219
-    /**
220
-     * Returns plugin proxy interface.
221
-     *
222
-     * @return Dwoo_IPluginProxy
223
-     */
224
-    public function getPluginProxy()
225
-    {
226
-        if (!$this->_pluginProxy) {
227
-            $this->_pluginProxy = new Dwoo_Adapters_ZendFramework_PluginProxy($this);
228
-        }
229
-
230
-        return $this->_pluginProxy;
231
-    }
232
-
233
-    /**
234
-     * Sets plugin proxy.
235
-     *
236
-     * @param Dwoo_IPluginProxy
237
-     *
238
-     * @return Dwoo_Adapters_ZendFramework_View
239
-     */
240
-    public function setPluginProxy(Dwoo_IPluginProxy $pluginProxy)
241
-    {
242
-        $this->_pluginProxy = $pluginProxy;
243
-
244
-        return $this;
245
-    }
246
-
247
-    /**
248
-     * Sets template engine.
249
-     *
250
-     * @param string|Dwoo Object or name of the class
251
-     */
252
-    public function setEngine($engine)
253
-    {
254
-        // if param given as an object
255
-        if ($engine instanceof Dwoo_Core) {
256
-            $this->_engine = $engine;
257
-        } elseif (is_subclass_of($engine, 'Dwoo') || 'Dwoo' === $engine) {
258
-            $this->_engine = new $engine();
259
-        } else {
260
-            throw new Dwoo_Exception('Custom engine must be a subclass of Dwoo');
261
-        }
262
-    }
263
-
264
-    /**
265
-     * Return the Dwoo template engine object.
266
-     *
267
-     * @return Dwoo
268
-     */
269
-    public function getEngine()
270
-    {
271
-        if (null === $this->_engine) {
272
-            $this->_engine = new Dwoo_Adapters_ZendFramework_Dwoo();
273
-        }
274
-
275
-        return $this->_engine;
276
-    }
277
-
278
-    /**
279
-     * Sets Dwoo data object.
280
-     *
281
-     * @param string|Dwoo_Data Object or name of the class
282
-     */
283
-    public function setDataProvider($data)
284
-    {
285
-        if ($data instanceof Dwoo_IDataProvider) {
286
-            $this->_dataProvider = $data;
287
-        } elseif (is_subclass_of($data, 'Dwoo_Data') || 'Dwoo_Data' == $data) {
288
-            $this->_dataProvider = new $data();
289
-        } else {
290
-            throw new Dwoo_Exception('Custom data provider must be a subclass of Dwoo_Data or instance of Dwoo_IDataProvider');
291
-        }
292
-    }
293
-
294
-    /**
295
-     * Return the Dwoo data object.
296
-     *
297
-     * @return Dwoo_Data
298
-     */
299
-    public function getDataProvider()
300
-    {
301
-        if (null === $this->_dataProvider) {
302
-            $this->_dataProvider = new Dwoo_Data();
303
-
304
-            // Satisfy Zend_View_Abstract wishes to access this unexisting property
305
-            // by setting it to empty array (see Zend_View_Abstract::_filter)
306
-            $this->_dataProvider->_filter = array();
307
-        }
308
-
309
-        return $this->_dataProvider;
310
-    }
311
-
312
-    /**
313
-     * Sets Dwoo compiler.
314
-     *
315
-     * @param string|Dwoo_Compiler Object or name of the class
316
-     */
317
-    public function setCompiler($compiler)
318
-    {
319
-
320
-        // if param given as an object
321
-        if ($compiler instanceof Dwoo_ICompiler) {
322
-            $this->_compiler = $compiler;
323
-        }
324
-        // if param given as a string
325
-        elseif (is_subclass_of($compiler, 'Dwoo_Compiler') || 'Dwoo_Compiler' == $compiler) {
326
-            $this->_compiler = new $compiler();
327
-        } else {
328
-            throw new Dwoo_Exception('Custom compiler must be a subclass of Dwoo_Compiler or instance of Dwoo_ICompiler');
329
-        }
330
-    }
331
-
332
-    /**
333
-     * Return the Dwoo compiler object.
334
-     *
335
-     * @return Dwoo_Compiler
336
-     */
337
-    public function getCompiler()
338
-    {
339
-        if (null === $this->_compiler) {
340
-            $this->_compiler = Dwoo_Compiler::compilerFactory();
341
-        }
342
-
343
-        return $this->_compiler;
344
-    }
345
-
346
-    /**
347
-     * Initializes Dwoo_ITemplate type of class and sets properties from _templateFileSettings.
348
-     *
349
-     * @param string Dwoo_ITemplate $template
350
-     *
351
-     * @return Dwoo_ITemplate
352
-     */
353
-    public function getTemplateFile($template)
354
-    {
355
-        $templateFileClass = $this->_templateFileClass;
356
-
357
-        $dwooTemplateFile = new $templateFileClass($template);
358
-
359
-        if (!($dwooTemplateFile instanceof Dwoo_ITemplate)) {
360
-            throw new Dwoo_Exception('Custom templateFile class must be a subclass of Dwoo_ITemplate');
361
-        }
362
-
363
-        foreach ($this->_templateFileSettings as $method => $value) {
364
-            if (method_exists($dwooTemplateFile, 'set'.$method)) {
365
-                call_user_func(array($dwooTemplateFile, 'set'.$method), $value);
366
-            }
367
-        }
368
-
369
-        return $dwooTemplateFile;
370
-    }
371
-
372
-    /**
373
-     * Dwoo_ITemplate type of class.
374
-     *
375
-     * @param string Name of the class
376
-     */
377
-    public function setTemplateFile($tempateFileClass)
378
-    {
379
-        $this->_templateFileClass = $tempateFileClass;
380
-    }
381
-
382
-    /**
383
-     * Passes data to Dwoo_Data object.
384
-     *
385
-     * @see Dwoo_Data::assign()
386
-     *
387
-     * @param array|string $name
388
-     * @param mixed        $val
389
-     *
390
-     * @return Dwoo_Adapters_ZendFramework_View
391
-     */
392
-    public function assign($name, $val = null)
393
-    {
394
-        $this->getDataProvider()->assign($name, $val);
395
-
396
-        return $this;
397
-    }
398
-
399
-    /**
400
-     * Return list of all assigned variables.
401
-     *
402
-     * @return array
403
-     */
404
-    public function getVars()
405
-    {
406
-        return $this->getDataProvider()->getData();
407
-    }
408
-
409
-    /**
410
-     * Clear all assigned variables.
411
-     *
412
-     * Clears all variables assigned to Zend_View either via {@link assign()} or
413
-     * property overloading ({@link __get()}/{@link __set()}).
414
-     *
415
-     * @return Dwoo_Adapters_ZendFramework_View
416
-     */
417
-    public function clearVars()
418
-    {
419
-        $this->getDataProvider()->clear();
420
-
421
-        return $this;
422
-    }
423
-
424
-    /**
425
-     * Wraper for parent's render method so preRender method
426
-     * can be called (that will bind the plugin proxy to the
427
-     * engine.
428
-     *
429
-     * @see Zend_View_Abstract::render
430
-     *
431
-     * @return string The script output
432
-     */
433
-    public function render($name)
434
-    {
435
-        $this->preRender();
436
-
437
-        return parent::render($name);
438
-    }
439
-
440
-    /**
441
-     * Processes a view script and outputs it. Output is then
442
-     * passed through filters.
443
-     *
444
-     * @param string $name The script script name to process
445
-     *
446
-     * @return string The script output
447
-     */
448
-    public function _run()
449
-    {
450
-        echo $this->_engine->get(
451
-            $this->getTemplateFile(func_get_arg(0)),
452
-            $this->getDataProvider(),
453
-            $this->getCompiler()
454
-        );
455
-    }
456
-
457
-    /**
458
-     * Add plugin path.
459
-     *
460
-     * @param string $dir Directory
461
-     *
462
-     * @return Dwoo_Adapters_ZendFramework_View
463
-     */
464
-    public function addPluginDir($dir)
465
-    {
466
-        $this->getEngine()->getLoader()->addDirectory($dir);
467
-
468
-        return $this;
469
-    }
470
-
471
-    /**
472
-     * Set compile path.
473
-     *
474
-     * @param string $dir Directory
475
-     *
476
-     * @return Dwoo_Adapters_ZendFramework_View
477
-     */
478
-    public function setCompileDir($dir)
479
-    {
480
-        $this->getEngine()->setCompileDir($dir);
481
-
482
-        return $this;
483
-    }
484
-
485
-    /**
486
-     * Set cache path.
487
-     *
488
-     * @param string $dir Directory
489
-     *
490
-     * @return Dwoo_Adapters_ZendFramework_View
491
-     */
492
-    public function setCacheDir($dir)
493
-    {
494
-        $this->getEngine()->setCacheDir($dir);
495
-
496
-        return $this;
497
-    }
498
-
499
-    /**
500
-     * Set cache lifetime.
501
-     *
502
-     * @param string $seconds Lifetime in seconds
503
-     *
504
-     * @return Dwoo_Adapters_ZendFramework_View
505
-     */
506
-    public function setCacheLifetime($seconds)
507
-    {
508
-        $this->getEngine()->setCacheTime($seconds);
509
-
510
-        return $this;
511
-    }
512
-
513
-    /**
514
-     * Set charset.
515
-     *
516
-     * @param string $charset
517
-     *
518
-     * @return Dwoo_Adapters_ZendFramework_View
519
-     */
520
-    public function setCharset($charset)
521
-    {
522
-        $this->_engine->setCharset($charset);
523
-
524
-        return $this;
525
-    }
23
+	/**
24
+	 * @var Dwoo
25
+	 */
26
+	protected $_engine = null;
27
+
28
+	/**
29
+	 * @var Dwoo_Data
30
+	 */
31
+	protected $_dataProvider = null;
32
+
33
+	/**
34
+	 * @var Dwoo_Compiler
35
+	 */
36
+	protected $_compiler = null;
37
+
38
+	/**
39
+	 * Changing Filter's scope to play nicely.
40
+	 *
41
+	 * @var array
42
+	 */
43
+	protected $_filter = array();
44
+
45
+	/**
46
+	 * @var string
47
+	 */
48
+	protected $_templateFileClass = 'Dwoo_Template_File';
49
+
50
+	/**
51
+	 * @var array
52
+	 */
53
+	protected $_templateFileSettings = array();
54
+
55
+	/**
56
+	 * @var Dwoo_IPluginProxy
57
+	 */
58
+	protected $_pluginProxy = null;
59
+
60
+	/**
61
+	 * Constructor method.
62
+	 * See setOptions for $opt details.
63
+	 *
64
+	 * @see setOptions
65
+	 *
66
+	 * @param array|Zend_Config List of options or Zend_Config instance
67
+	 */
68
+	public function __construct($opt = array())
69
+	{
70
+		if (is_array($opt)) {
71
+			$this->setOptions($opt);
72
+		} elseif ($opt instanceof Zend_Config) {
73
+			$this->setConfig($opt);
74
+		}
75
+
76
+		$this->init();
77
+	}
78
+
79
+	/**
80
+	 * Set object state from options array
81
+	 *  - engine        = engine class name|engine object|array of options for engine
82
+	 *  - dataProvider  = data provider class name|data provider object|array of options for data provider
83
+	 *  - compiler      = compiler class name|compiler object|array of options for compiler
84
+	 *  - templateFile  =.
85
+	 *
86
+	 *  Array of options:
87
+	 *  - type class name or object for engine, dataProvider or compiler
88
+	 *  - any set* method (compileDir for setCompileDir ...)
89
+	 *
90
+	 * @param array $options
91
+	 *
92
+	 * @return Dwoo_Adapters_ZendFramework_View
93
+	 */
94
+	public function setOptions(array $opt = array())
95
+	{
96
+		// Making sure that everything is loaded.
97
+		$classes = array('engine', 'dataProvider', 'compiler');
98
+
99
+		// Setting options to Dwoo objects...
100
+		foreach ($opt as $type => $settings) {
101
+			if (!method_exists($this, 'set'.$type)) {
102
+				throw new Dwoo_Exception("Unknown type $type");
103
+			}
104
+
105
+			if (is_string($settings) || is_object($settings)) {
106
+				call_user_func(array($this, 'set'.$type), $settings);
107
+			} elseif (is_array($settings)) {
108
+				// Set requested class
109
+				if (array_key_exists('type', $settings)) {
110
+					call_user_func(array($this, 'set'.$type), $settings['type']);
111
+				}
112
+
113
+				if (in_array($type, $classes)) {
114
+					// Call get so that the class is initialized
115
+					$rel = call_user_func(array($this, 'get'.$type));
116
+
117
+					// Call set*() methods so that all the settings are set.
118
+					foreach ($settings as $method => $value) {
119
+						if (method_exists($rel, 'set'.$method)) {
120
+							call_user_func(array($rel, 'set'.$method), $value);
121
+						}
122
+					}
123
+				} elseif ('templateFile' == $type) {
124
+					// Remember the settings for the templateFile
125
+					$this->_templateFileSettings = $settings;
126
+				}
127
+			}
128
+		}
129
+	}
130
+
131
+	/**
132
+	 * Set object state from Zend_Config object.
133
+	 *
134
+	 * @param Zend_Config $config
135
+	 *
136
+	 * @return Dwoo_Adapters_ZendFramework_View
137
+	 */
138
+	public function setConfig(Zend_Config $config)
139
+	{
140
+		return $this->setOptions($config->toArray());
141
+	}
142
+
143
+	/**
144
+	 * Called before template rendering.
145
+	 *
146
+	 * Binds plugin proxy to the Dwoo.
147
+	 *
148
+	 * @see Dwoo_Adapters_ZendFramework_View::getPluginProxy();
149
+	 * @see Dwoo_Core::setPluginProxy();
150
+	 */
151
+	protected function preRender()
152
+	{
153
+		$this->getEngine()->setPluginProxy($this->getPluginProxy());
154
+	}
155
+
156
+	/**
157
+	 * Wraper for Dwoo_Data::__set()
158
+	 * allows to assign variables using the object syntax.
159
+	 *
160
+	 * @see Dwoo_Data::__set()
161
+	 *
162
+	 * @param string $name  the variable name
163
+	 * @param string $value the value to assign to it
164
+	 */
165
+	public function __set($name, $value)
166
+	{
167
+		$this->getDataProvider()->__set($name, $value);
168
+	}
169
+
170
+	/**
171
+	 * Sraper for Dwoo_Data::__get() allows to read variables using the object
172
+	 * syntax.
173
+	 *
174
+	 * @see Dwoo_Data::__get()
175
+	 *
176
+	 * @param string $name the variable name
177
+	 *
178
+	 * @return mixed
179
+	 */
180
+	public function __get($name)
181
+	{
182
+		return $this->getDataProvider()->__get($name);
183
+	}
184
+
185
+	/**
186
+	 * Wraper for Dwoo_Data::__isset()
187
+	 * supports calls to isset($dwooData->var).
188
+	 *
189
+	 * @see Dwoo_Data::__isset()
190
+	 *
191
+	 * @param string $name the variable name
192
+	 */
193
+	public function __isset($name)
194
+	{
195
+		return $this->getDataProvider()->__isset($name);
196
+	}
197
+
198
+	/**
199
+	 * Wraper for Dwoo_Data::_unset()
200
+	 * supports unsetting variables using the object syntax.
201
+	 *
202
+	 * @see Dwoo_Data::__unset()
203
+	 *
204
+	 * @param string $name the variable name
205
+	 */
206
+	public function __unset($name)
207
+	{
208
+		$this->getDataProvider()->__unset($name);
209
+	}
210
+
211
+	/**
212
+	 * Catches clone request and clones data provider.
213
+	 */
214
+	public function __clone()
215
+	{
216
+		$this->setDataProvider(clone $this->getDataProvider());
217
+	}
218
+
219
+	/**
220
+	 * Returns plugin proxy interface.
221
+	 *
222
+	 * @return Dwoo_IPluginProxy
223
+	 */
224
+	public function getPluginProxy()
225
+	{
226
+		if (!$this->_pluginProxy) {
227
+			$this->_pluginProxy = new Dwoo_Adapters_ZendFramework_PluginProxy($this);
228
+		}
229
+
230
+		return $this->_pluginProxy;
231
+	}
232
+
233
+	/**
234
+	 * Sets plugin proxy.
235
+	 *
236
+	 * @param Dwoo_IPluginProxy
237
+	 *
238
+	 * @return Dwoo_Adapters_ZendFramework_View
239
+	 */
240
+	public function setPluginProxy(Dwoo_IPluginProxy $pluginProxy)
241
+	{
242
+		$this->_pluginProxy = $pluginProxy;
243
+
244
+		return $this;
245
+	}
246
+
247
+	/**
248
+	 * Sets template engine.
249
+	 *
250
+	 * @param string|Dwoo Object or name of the class
251
+	 */
252
+	public function setEngine($engine)
253
+	{
254
+		// if param given as an object
255
+		if ($engine instanceof Dwoo_Core) {
256
+			$this->_engine = $engine;
257
+		} elseif (is_subclass_of($engine, 'Dwoo') || 'Dwoo' === $engine) {
258
+			$this->_engine = new $engine();
259
+		} else {
260
+			throw new Dwoo_Exception('Custom engine must be a subclass of Dwoo');
261
+		}
262
+	}
263
+
264
+	/**
265
+	 * Return the Dwoo template engine object.
266
+	 *
267
+	 * @return Dwoo
268
+	 */
269
+	public function getEngine()
270
+	{
271
+		if (null === $this->_engine) {
272
+			$this->_engine = new Dwoo_Adapters_ZendFramework_Dwoo();
273
+		}
274
+
275
+		return $this->_engine;
276
+	}
277
+
278
+	/**
279
+	 * Sets Dwoo data object.
280
+	 *
281
+	 * @param string|Dwoo_Data Object or name of the class
282
+	 */
283
+	public function setDataProvider($data)
284
+	{
285
+		if ($data instanceof Dwoo_IDataProvider) {
286
+			$this->_dataProvider = $data;
287
+		} elseif (is_subclass_of($data, 'Dwoo_Data') || 'Dwoo_Data' == $data) {
288
+			$this->_dataProvider = new $data();
289
+		} else {
290
+			throw new Dwoo_Exception('Custom data provider must be a subclass of Dwoo_Data or instance of Dwoo_IDataProvider');
291
+		}
292
+	}
293
+
294
+	/**
295
+	 * Return the Dwoo data object.
296
+	 *
297
+	 * @return Dwoo_Data
298
+	 */
299
+	public function getDataProvider()
300
+	{
301
+		if (null === $this->_dataProvider) {
302
+			$this->_dataProvider = new Dwoo_Data();
303
+
304
+			// Satisfy Zend_View_Abstract wishes to access this unexisting property
305
+			// by setting it to empty array (see Zend_View_Abstract::_filter)
306
+			$this->_dataProvider->_filter = array();
307
+		}
308
+
309
+		return $this->_dataProvider;
310
+	}
311
+
312
+	/**
313
+	 * Sets Dwoo compiler.
314
+	 *
315
+	 * @param string|Dwoo_Compiler Object or name of the class
316
+	 */
317
+	public function setCompiler($compiler)
318
+	{
319
+
320
+		// if param given as an object
321
+		if ($compiler instanceof Dwoo_ICompiler) {
322
+			$this->_compiler = $compiler;
323
+		}
324
+		// if param given as a string
325
+		elseif (is_subclass_of($compiler, 'Dwoo_Compiler') || 'Dwoo_Compiler' == $compiler) {
326
+			$this->_compiler = new $compiler();
327
+		} else {
328
+			throw new Dwoo_Exception('Custom compiler must be a subclass of Dwoo_Compiler or instance of Dwoo_ICompiler');
329
+		}
330
+	}
331
+
332
+	/**
333
+	 * Return the Dwoo compiler object.
334
+	 *
335
+	 * @return Dwoo_Compiler
336
+	 */
337
+	public function getCompiler()
338
+	{
339
+		if (null === $this->_compiler) {
340
+			$this->_compiler = Dwoo_Compiler::compilerFactory();
341
+		}
342
+
343
+		return $this->_compiler;
344
+	}
345
+
346
+	/**
347
+	 * Initializes Dwoo_ITemplate type of class and sets properties from _templateFileSettings.
348
+	 *
349
+	 * @param string Dwoo_ITemplate $template
350
+	 *
351
+	 * @return Dwoo_ITemplate
352
+	 */
353
+	public function getTemplateFile($template)
354
+	{
355
+		$templateFileClass = $this->_templateFileClass;
356
+
357
+		$dwooTemplateFile = new $templateFileClass($template);
358
+
359
+		if (!($dwooTemplateFile instanceof Dwoo_ITemplate)) {
360
+			throw new Dwoo_Exception('Custom templateFile class must be a subclass of Dwoo_ITemplate');
361
+		}
362
+
363
+		foreach ($this->_templateFileSettings as $method => $value) {
364
+			if (method_exists($dwooTemplateFile, 'set'.$method)) {
365
+				call_user_func(array($dwooTemplateFile, 'set'.$method), $value);
366
+			}
367
+		}
368
+
369
+		return $dwooTemplateFile;
370
+	}
371
+
372
+	/**
373
+	 * Dwoo_ITemplate type of class.
374
+	 *
375
+	 * @param string Name of the class
376
+	 */
377
+	public function setTemplateFile($tempateFileClass)
378
+	{
379
+		$this->_templateFileClass = $tempateFileClass;
380
+	}
381
+
382
+	/**
383
+	 * Passes data to Dwoo_Data object.
384
+	 *
385
+	 * @see Dwoo_Data::assign()
386
+	 *
387
+	 * @param array|string $name
388
+	 * @param mixed        $val
389
+	 *
390
+	 * @return Dwoo_Adapters_ZendFramework_View
391
+	 */
392
+	public function assign($name, $val = null)
393
+	{
394
+		$this->getDataProvider()->assign($name, $val);
395
+
396
+		return $this;
397
+	}
398
+
399
+	/**
400
+	 * Return list of all assigned variables.
401
+	 *
402
+	 * @return array
403
+	 */
404
+	public function getVars()
405
+	{
406
+		return $this->getDataProvider()->getData();
407
+	}
408
+
409
+	/**
410
+	 * Clear all assigned variables.
411
+	 *
412
+	 * Clears all variables assigned to Zend_View either via {@link assign()} or
413
+	 * property overloading ({@link __get()}/{@link __set()}).
414
+	 *
415
+	 * @return Dwoo_Adapters_ZendFramework_View
416
+	 */
417
+	public function clearVars()
418
+	{
419
+		$this->getDataProvider()->clear();
420
+
421
+		return $this;
422
+	}
423
+
424
+	/**
425
+	 * Wraper for parent's render method so preRender method
426
+	 * can be called (that will bind the plugin proxy to the
427
+	 * engine.
428
+	 *
429
+	 * @see Zend_View_Abstract::render
430
+	 *
431
+	 * @return string The script output
432
+	 */
433
+	public function render($name)
434
+	{
435
+		$this->preRender();
436
+
437
+		return parent::render($name);
438
+	}
439
+
440
+	/**
441
+	 * Processes a view script and outputs it. Output is then
442
+	 * passed through filters.
443
+	 *
444
+	 * @param string $name The script script name to process
445
+	 *
446
+	 * @return string The script output
447
+	 */
448
+	public function _run()
449
+	{
450
+		echo $this->_engine->get(
451
+			$this->getTemplateFile(func_get_arg(0)),
452
+			$this->getDataProvider(),
453
+			$this->getCompiler()
454
+		);
455
+	}
456
+
457
+	/**
458
+	 * Add plugin path.
459
+	 *
460
+	 * @param string $dir Directory
461
+	 *
462
+	 * @return Dwoo_Adapters_ZendFramework_View
463
+	 */
464
+	public function addPluginDir($dir)
465
+	{
466
+		$this->getEngine()->getLoader()->addDirectory($dir);
467
+
468
+		return $this;
469
+	}
470
+
471
+	/**
472
+	 * Set compile path.
473
+	 *
474
+	 * @param string $dir Directory
475
+	 *
476
+	 * @return Dwoo_Adapters_ZendFramework_View
477
+	 */
478
+	public function setCompileDir($dir)
479
+	{
480
+		$this->getEngine()->setCompileDir($dir);
481
+
482
+		return $this;
483
+	}
484
+
485
+	/**
486
+	 * Set cache path.
487
+	 *
488
+	 * @param string $dir Directory
489
+	 *
490
+	 * @return Dwoo_Adapters_ZendFramework_View
491
+	 */
492
+	public function setCacheDir($dir)
493
+	{
494
+		$this->getEngine()->setCacheDir($dir);
495
+
496
+		return $this;
497
+	}
498
+
499
+	/**
500
+	 * Set cache lifetime.
501
+	 *
502
+	 * @param string $seconds Lifetime in seconds
503
+	 *
504
+	 * @return Dwoo_Adapters_ZendFramework_View
505
+	 */
506
+	public function setCacheLifetime($seconds)
507
+	{
508
+		$this->getEngine()->setCacheTime($seconds);
509
+
510
+		return $this;
511
+	}
512
+
513
+	/**
514
+	 * Set charset.
515
+	 *
516
+	 * @param string $charset
517
+	 *
518
+	 * @return Dwoo_Adapters_ZendFramework_View
519
+	 */
520
+	public function setCharset($charset)
521
+	{
522
+		$this->_engine->setCharset($charset);
523
+
524
+		return $this;
525
+	}
526 526
 }
Please login to merge, or discard this patch.
lib/Dwoo/Compiler.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
     /**
275 275
      * returns the left and right template delimiters.
276 276
      *
277
-     * @return array containing the left and the right delimiters
277
+     * @return string[] containing the left and the right delimiters
278 278
      */
279 279
     public function getDelimiters()
280 280
     {
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
      * adds a preprocessor to the compiler, it will be called
367 367
      * before the template is compiled.
368 368
      *
369
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to true
369
+     * @param string $callback either a valid callback to the preprocessor or a simple name if the autoload is set to true
370 370
      * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else you must provide a valid callback
371 371
      */
372 372
     public function addPreProcessor($callback, $autoload = false)
@@ -1287,7 +1287,7 @@  discard block
 block discarded – undo
1287 1287
      *
1288 1288
      * @param array $params parameter array
1289 1289
      *
1290
-     * @return array tokens
1290
+     * @return Dwoo_Compiler tokens
1291 1291
      */
1292 1292
     public function getParamTokens(array $params)
1293 1293
     {
Please login to merge, or discard this patch.
Spacing   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -788,23 +788,23 @@  discard block
 block discarded – undo
788 788
             if ($pos === false) {
789 789
                 $this->push(substr($tpl, $ptr), 0);
790 790
                 break;
791
-            } elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
792
-                $this->push(substr($tpl, $ptr, $pos - $ptr - 1).$this->ld);
793
-                $ptr = $pos + strlen($this->ld);
791
+            } elseif (substr($tpl, $pos-1, 1) === '\\' && substr($tpl, $pos-2, 1) !== '\\') {
792
+                $this->push(substr($tpl, $ptr, $pos-$ptr-1).$this->ld);
793
+                $ptr = $pos+strlen($this->ld);
794 794
             } elseif (preg_match('/^'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', substr($tpl, $pos), $litOpen)) {
795 795
                 if (!preg_match('/'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'\/literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
796 796
                     throw new Dwoo_Compilation_Exception($this, 'The {literal} blocks must be closed explicitly with {/literal}');
797 797
                 }
798 798
                 $endpos = $litClose[0][1];
799
-                $this->push(substr($tpl, $ptr, $pos - $ptr).substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
800
-                $ptr = $endpos + strlen($litClose[0][0]);
799
+                $this->push(substr($tpl, $ptr, $pos-$ptr).substr($tpl, $pos+strlen($litOpen[0]), $endpos-$pos-strlen($litOpen[0])));
800
+                $ptr = $endpos+strlen($litClose[0][0]);
801 801
             } else {
802
-                if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
803
-                    $this->push(substr($tpl, $ptr, $pos - $ptr - 1));
802
+                if (substr($tpl, $pos-2, 1) === '\\' && substr($tpl, $pos-1, 1) === '\\') {
803
+                    $this->push(substr($tpl, $ptr, $pos-$ptr-1));
804 804
                     $ptr = $pos;
805 805
                 }
806 806
 
807
-                $this->push(substr($tpl, $ptr, $pos - $ptr));
807
+                $this->push(substr($tpl, $ptr, $pos-$ptr));
808 808
                 $ptr = $pos;
809 809
 
810 810
                 $pos += strlen($this->ld);
@@ -836,7 +836,7 @@  discard block
 block discarded – undo
836 836
                         continue 2;
837 837
                     }
838 838
 
839
-                    $len = $subptr - $ptr;
839
+                    $len = $subptr-$ptr;
840 840
                     $this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
841 841
                     $ptr += $len;
842 842
 
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
             $lines = preg_split('{\r\n|\n|<br />}', $output);
933 933
             array_shift($lines);
934 934
             foreach ($lines as $i => $line) {
935
-                echo($i + 1).'. '.$line."\r\n";
935
+                echo($i+1).'. '.$line."\r\n";
936 936
             }
937 937
             echo '============================================================================================='."\n";
938 938
         }
@@ -980,7 +980,7 @@  discard block
 block discarded – undo
980 980
 
981 981
         if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
982 982
             // buffer is not initialized yet (the block has just been created)
983
-            $this->stack[count($this->stack) - 2]['buffer'] .= (string) $content;
983
+            $this->stack[count($this->stack)-2]['buffer'] .= (string) $content;
984 984
             $this->curBlock['buffer'] = '';
985 985
         } else {
986 986
             if (!isset($this->curBlock['buffer'])) {
@@ -1068,7 +1068,7 @@  discard block
 block discarded – undo
1068 1068
         $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1069 1069
 
1070 1070
         $this->stack[] = array('type' => $type, 'params' => $params, 'custom' => false, 'class' => $class, 'buffer' => null);
1071
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1071
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1072 1072
 
1073 1073
         return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1074 1074
     }
@@ -1094,7 +1094,7 @@  discard block
 block discarded – undo
1094 1094
         $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1095 1095
 
1096 1096
         $this->stack[] = array('type' => $type, 'params' => $params, 'custom' => true, 'class' => $class, 'buffer' => null);
1097
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1097
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1098 1098
 
1099 1099
         return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1100 1100
     }
@@ -1118,7 +1118,7 @@  discard block
 block discarded – undo
1118 1118
             $this->dwoo->getLoader()->loadPlugin($type);
1119 1119
         }
1120 1120
         $this->stack[] = array('type' => $type, 'params' => $params, 'custom' => false, 'class' => $class, 'buffer' => null);
1121
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1121
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1122 1122
     }
1123 1123
 
1124 1124
     /**
@@ -1151,7 +1151,7 @@  discard block
 block discarded – undo
1151 1151
                     $class = 'Dwoo_Plugin_'.$top['type'];
1152 1152
                 }
1153 1153
                 if (count($this->stack)) {
1154
-                    $this->curBlock = &$this->stack[count($this->stack) - 1];
1154
+                    $this->curBlock = &$this->stack[count($this->stack)-1];
1155 1155
                     $this->push(call_user_func(array($class, 'postProcessing'), $this, $top['params'], '', '', $top['buffer']), 0);
1156 1156
                 } else {
1157 1157
                     $null = null;
@@ -1241,7 +1241,7 @@  discard block
 block discarded – undo
1241 1241
             $class = 'Dwoo_Plugin_'.$o['type'];
1242 1242
         }
1243 1243
 
1244
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1244
+        $this->curBlock = &$this->stack[count($this->stack)-1];
1245 1245
 
1246 1246
         return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1247 1247
     }
@@ -1353,16 +1353,16 @@  discard block
 block discarded – undo
1353 1353
             $first = $in[$from];
1354 1354
         }
1355 1355
 
1356
-        $substr = substr($in, $from, $to - $from);
1356
+        $substr = substr($in, $from, $to-$from);
1357 1357
 
1358 1358
         if ($this->debug) {
1359
-            echo 'PARSE CALL : PARSING "<b>'.htmlentities(substr($in, $from, min($to - $from, 50))).(($to - $from) > 50 ? '...' : '').'</b>" @ '.$from.':'.$to.' in '.$curBlock.' : pointer='.$pointer."\n";
1359
+            echo 'PARSE CALL : PARSING "<b>'.htmlentities(substr($in, $from, min($to-$from, 50))).(($to-$from) > 50 ? '...' : '').'</b>" @ '.$from.':'.$to.' in '.$curBlock.' : pointer='.$pointer."\n";
1360 1360
         }
1361 1361
         $parsed = '';
1362 1362
 
1363 1363
         if ($curBlock === 'root' && $first === '*') {
1364 1364
             $src = $this->getTemplateSource();
1365
-            $startpos = $this->getPointer() - strlen($this->ld);
1365
+            $startpos = $this->getPointer()-strlen($this->ld);
1366 1366
             if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1367 1367
                 if ($startpos > 0) {
1368 1368
                     do {
@@ -1378,7 +1378,7 @@  discard block
 block discarded – undo
1378 1378
                 if (!isset($whitespaceStart)) {
1379 1379
                     $startpos = $this->getPointer();
1380 1380
                 } else {
1381
-                    $pointer -= $this->getPointer() - $startpos;
1381
+                    $pointer -= $this->getPointer()-$startpos;
1382 1382
                 }
1383 1383
 
1384 1384
                 if ($this->allowNestedComments && strpos($src, $this->ld.'*', $this->getPointer()) !== false) {
@@ -1393,33 +1393,33 @@  discard block
 block discarded – undo
1393 1393
 
1394 1394
                         if ($open !== false && $close !== false) {
1395 1395
                             if ($open < $close) {
1396
-                                $ptr = $open + strlen($comOpen);
1396
+                                $ptr = $open+strlen($comOpen);
1397 1397
                                 ++$level;
1398 1398
                             } else {
1399
-                                $ptr = $close + strlen($comClose);
1399
+                                $ptr = $close+strlen($comClose);
1400 1400
                                 --$level;
1401 1401
                             }
1402 1402
                         } elseif ($open !== false) {
1403
-                            $ptr = $open + strlen($comOpen);
1403
+                            $ptr = $open+strlen($comOpen);
1404 1404
                             ++$level;
1405 1405
                         } elseif ($close !== false) {
1406
-                            $ptr = $close + strlen($comClose);
1406
+                            $ptr = $close+strlen($comClose);
1407 1407
                             --$level;
1408 1408
                         } else {
1409 1409
                             $ptr = strlen($src);
1410 1410
                         }
1411 1411
                     }
1412
-                    $endpos = $ptr - strlen('*'.$this->rd);
1412
+                    $endpos = $ptr-strlen('*'.$this->rd);
1413 1413
                 } else {
1414 1414
                     $endpos = strpos($src, '*'.$this->rd, $startpos);
1415 1415
                     if ($endpos == false) {
1416 1416
                         throw new Dwoo_Compilation_Exception($this, 'Un-ended comment');
1417 1417
                     }
1418 1418
                 }
1419
-                $pointer += $endpos - $startpos + strlen('*'.$this->rd);
1420
-                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*'.$this->rd)), $m)) {
1419
+                $pointer += $endpos-$startpos+strlen('*'.$this->rd);
1420
+                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos+strlen('*'.$this->rd)), $m)) {
1421 1421
                     $pointer += strlen($m[0]);
1422
-                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1422
+                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer'])-($this->getPointer()-$startpos-strlen($this->ld)));
1423 1423
                 }
1424 1424
 
1425 1425
                 return false;
@@ -1449,7 +1449,7 @@  discard block
 block discarded – undo
1449 1449
                 ++$pointer;
1450 1450
             }
1451 1451
 
1452
-            return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1452
+            return $this->parse($in, $from+1, $to, false, 'root', $pointer);
1453 1453
         } elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1454 1454
             // close block
1455 1455
             if (!empty($match[1]) && $match[1] == 'else') {
@@ -1491,14 +1491,14 @@  discard block
 block discarded – undo
1491 1491
                 echo 'NAMED PARAM FOUND'."\n";
1492 1492
             }
1493 1493
             $len = strlen($match[1]);
1494
-            while (substr($in, $from + $len, 1) === ' ') {
1494
+            while (substr($in, $from+$len, 1) === ' ') {
1495 1495
                 ++$len;
1496 1496
             }
1497 1497
             if ($pointer !== null) {
1498 1498
                 $pointer += $len;
1499 1499
             }
1500 1500
 
1501
-            $output = array(trim($match[1], " \t\r\n=>'\""), $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer));
1501
+            $output = array(trim($match[1], " \t\r\n=>'\""), $this->parse($in, $from+$len, $to, false, 'namedparam', $pointer));
1502 1502
 
1503 1503
             $parsingParams[] = $output;
1504 1504
 
@@ -1518,14 +1518,14 @@  discard block
 block discarded – undo
1518 1518
             $out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1519 1519
         } else {
1520 1520
             // parse error
1521
-            throw new Dwoo_Compilation_Exception($this, 'Parse error in "'.substr($in, $from, $to - $from).'"');
1521
+            throw new Dwoo_Compilation_Exception($this, 'Parse error in "'.substr($in, $from, $to-$from).'"');
1522 1522
         }
1523 1523
 
1524 1524
         if (empty($out)) {
1525 1525
             return '';
1526 1526
         }
1527 1527
 
1528
-        $substr = substr($in, $pointer, $to - $pointer);
1528
+        $substr = substr($in, $pointer, $to-$pointer);
1529 1529
 
1530 1530
         // var parsed, check if any var-extension applies
1531 1531
         if ($parsed === 'var') {
@@ -1534,15 +1534,15 @@  discard block
 block discarded – undo
1534 1534
                     echo 'PARSING POST-VAR EXPRESSION '.$substr."\n";
1535 1535
                 }
1536 1536
                 // parse expressions
1537
-                $pointer += strlen($match[0]) - 1;
1537
+                $pointer += strlen($match[0])-1;
1538 1538
                 if (is_array($parsingParams)) {
1539 1539
                     if ($match[2] == '$') {
1540 1540
                         $expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1541 1541
                     } else {
1542 1542
                         $expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1543 1543
                     }
1544
-                    $out[count($out) - 1][0] .= $match[1].$expr[0][0];
1545
-                    $out[count($out) - 1][1] .= $match[1].$expr[0][1];
1544
+                    $out[count($out)-1][0] .= $match[1].$expr[0][0];
1545
+                    $out[count($out)-1][1] .= $match[1].$expr[0][1];
1546 1546
                 } else {
1547 1547
                     if ($match[2] == '$') {
1548 1548
                         $expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
@@ -1610,7 +1610,7 @@  discard block
 block discarded – undo
1610 1610
                     echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND'."\n";
1611 1611
                 }
1612 1612
                 $len = strlen($match[1]);
1613
-                $var = $out[count($out) - 1];
1613
+                $var = $out[count($out)-1];
1614 1614
                 $pointer += $len;
1615 1615
 
1616 1616
                 $output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
@@ -1625,9 +1625,9 @@  discard block
 block discarded – undo
1625 1625
             // parse modifier on funcs or vars
1626 1626
             $srcPointer = $pointer;
1627 1627
             if (is_array($parsingParams)) {
1628
-                $tmp = $this->replaceModifiers(array(null, null, $out[count($out) - 1][0], $match[0]), $curBlock, $pointer);
1629
-                $out[count($out) - 1][0] = $tmp;
1630
-                $out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1628
+                $tmp = $this->replaceModifiers(array(null, null, $out[count($out)-1][0], $match[0]), $curBlock, $pointer);
1629
+                $out[count($out)-1][0] = $tmp;
1630
+                $out[count($out)-1][1] .= substr($substr, $srcPointer, $srcPointer-$pointer);
1631 1631
             } else {
1632 1632
                 $out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1633 1633
             }
@@ -1639,10 +1639,10 @@  discard block
 block discarded – undo
1639 1639
             $ptr = 0;
1640 1640
 
1641 1641
             if (is_array($parsingParams)) {
1642
-                $output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1642
+                $output = $this->parseMethodCall($out[count($out)-1][1], $match[0], $curBlock, $ptr);
1643 1643
 
1644
-                $out[count($out) - 1][0] = $output;
1645
-                $out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1644
+                $out[count($out)-1][0] = $output;
1645
+                $out[count($out)-1][1] .= substr($match[0], 0, $ptr);
1646 1646
             } else {
1647 1647
                 $out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1648 1648
             }
@@ -1675,7 +1675,7 @@  discard block
 block discarded – undo
1675 1675
      */
1676 1676
     protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1677 1677
     {
1678
-        $cmdstr = substr($in, $from, $to - $from);
1678
+        $cmdstr = substr($in, $from, $to-$from);
1679 1679
         preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*'.$this->rdr.'|\s*;)?/i', $cmdstr, $match);
1680 1680
 
1681 1681
         if (empty($match[1])) {
@@ -1701,7 +1701,7 @@  discard block
 block discarded – undo
1701 1701
             $paramspos = $match[1][0][1];
1702 1702
             $paramsep = substr($match[1][0][0], -1) === '(' ? ')' : '';
1703 1703
             if ($paramsep === ')') {
1704
-                $paramspos += strlen($match[1][0][0]) - 1;
1704
+                $paramspos += strlen($match[1][0][0])-1;
1705 1705
                 if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1706 1706
                     $paramsep = '';
1707 1707
                     if (strlen($match[1][0][0]) > 1) {
@@ -1730,8 +1730,8 @@  discard block
 block discarded – undo
1730 1730
                     return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1731 1731
                 }
1732 1732
             }
1733
-            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1734
-            $paramstr = substr($cmdstr, $paramspos + 1);
1733
+            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos-strlen($func)));
1734
+            $paramstr = substr($cmdstr, $paramspos+1);
1735 1735
             if (substr($paramstr, -1, 1) === $paramsep) {
1736 1736
                 $paramstr = substr($paramstr, 0, -1);
1737 1737
             }
@@ -1794,7 +1794,7 @@  discard block
 block discarded – undo
1794 1794
                         }
1795 1795
 
1796 1796
                         if ($this->debug) {
1797
-                            echo 'PARAM PARSED, POINTER AT '.$ptr.' ('.substr($paramstr, $ptr - 1, 3).')'."\n";
1797
+                            echo 'PARAM PARSED, POINTER AT '.$ptr.' ('.substr($paramstr, $ptr-1, 3).')'."\n";
1798 1798
                         }
1799 1799
                     }
1800 1800
                 }
@@ -1818,9 +1818,9 @@  discard block
 block discarded – undo
1818 1818
         }
1819 1819
 
1820 1820
         if ($pointer !== null) {
1821
-            $pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1821
+            $pointer += (isset($paramstr) ? strlen($paramstr) : 0)+(')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1))+strlen($func)+(isset($whitespace) ? $whitespace : 0);
1822 1822
             if ($this->debug) {
1823
-                echo 'FUNC ADDS '.((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)).' TO POINTER'."\n";
1823
+                echo 'FUNC ADDS '.((isset($paramstr) ? strlen($paramstr) : 0)+(')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1))+strlen($func)).' TO POINTER'."\n";
1824 1824
             }
1825 1825
         }
1826 1826
 
@@ -2062,29 +2062,29 @@  discard block
 block discarded – undo
2062 2062
      */
2063 2063
     protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2064 2064
     {
2065
-        $substr = substr($in, $from, $to - $from);
2065
+        $substr = substr($in, $from, $to-$from);
2066 2066
         $first = $substr[0];
2067 2067
 
2068 2068
         if ($this->debug) {
2069
-            echo 'STRING FOUND (in '.htmlentities(substr($in, $from, min($to - $from, 50))).(($to - $from) > 50 ? '...' : '').')'."\n";
2069
+            echo 'STRING FOUND (in '.htmlentities(substr($in, $from, min($to-$from, 50))).(($to-$from) > 50 ? '...' : '').')'."\n";
2070 2070
         }
2071 2071
         $strend = false;
2072
-        $o = $from + 1;
2072
+        $o = $from+1;
2073 2073
         while ($strend === false) {
2074 2074
             $strend = strpos($in, $first, $o);
2075 2075
             if ($strend === false) {
2076
-                throw new Dwoo_Compilation_Exception($this, 'Unfinished string, started with '.substr($in, $from, $to - $from));
2076
+                throw new Dwoo_Compilation_Exception($this, 'Unfinished string, started with '.substr($in, $from, $to-$from));
2077 2077
             }
2078
-            if (substr($in, $strend - 1, 1) === '\\') {
2079
-                $o = $strend + 1;
2078
+            if (substr($in, $strend-1, 1) === '\\') {
2079
+                $o = $strend+1;
2080 2080
                 $strend = false;
2081 2081
             }
2082 2082
         }
2083 2083
         if ($this->debug) {
2084
-            echo 'STRING DELIMITED: '.substr($in, $from, $strend + 1 - $from)."\n";
2084
+            echo 'STRING DELIMITED: '.substr($in, $from, $strend+1-$from)."\n";
2085 2085
         }
2086 2086
 
2087
-        $srcOutput = substr($in, $from, $strend + 1 - $from);
2087
+        $srcOutput = substr($in, $from, $strend+1-$from);
2088 2088
 
2089 2089
         if ($pointer !== null) {
2090 2090
             $pointer += strlen($srcOutput);
@@ -2093,7 +2093,7 @@  discard block
 block discarded – undo
2093 2093
         $output = $this->replaceStringVars($srcOutput, $first);
2094 2094
 
2095 2095
         // handle modifiers
2096
-        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2096
+        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend+1-$from), $match)) {
2097 2097
             $modstr = $match[1];
2098 2098
 
2099 2099
             if ($curBlock === 'root' && substr($modstr, -1) === '}') {
@@ -2107,7 +2107,7 @@  discard block
 block discarded – undo
2107 2107
             if ($pointer !== null) {
2108 2108
                 $pointer += $ptr;
2109 2109
             }
2110
-            $srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2110
+            $srcOutput .= substr($substr, $strend+1-$from, $ptr);
2111 2111
         }
2112 2112
 
2113 2113
         if (is_array($parsingParams)) {
@@ -2137,7 +2137,7 @@  discard block
 block discarded – undo
2137 2137
      */
2138 2138
     protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2139 2139
     {
2140
-        $substr = substr($in, $from, $to - $from);
2140
+        $substr = substr($in, $from, $to-$from);
2141 2141
 
2142 2142
         if ($this->debug) {
2143 2143
             echo 'CONST FOUND : '.$substr."\n";
@@ -2203,12 +2203,12 @@  discard block
 block discarded – undo
2203 2203
      */
2204 2204
     protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2205 2205
     {
2206
-        $substr = substr($in, $from, $to - $from);
2206
+        $substr = substr($in, $from, $to-$from);
2207 2207
 
2208
-        if (preg_match('#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)'. // var key
2209
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()'). // method call
2210
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()'). // simple math expressions
2211
-            ($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())'). // modifiers
2208
+        if (preg_match('#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)'.// var key
2209
+            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()').// method call
2210
+            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()').// simple math expressions
2211
+            ($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())').// modifiers
2212 2212
             '#i', $substr, $match)) {
2213 2213
             $key = substr($match[1], 1);
2214 2214
 
@@ -2223,8 +2223,8 @@  discard block
 block discarded – undo
2223 2223
             }
2224 2224
 
2225 2225
             if ($hasMethodCall) {
2226
-                $matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2227
-                $key = substr($match[1], 1, strrpos($match[1], '->') - 1);
2226
+                $matchedLength -= strlen($match[3])+strlen(substr($match[1], strrpos($match[1], '->')));
2227
+                $key = substr($match[1], 1, strrpos($match[1], '->')-1);
2228 2228
                 $methodCall = substr($match[1], strrpos($match[1], '->')).$match[3];
2229 2229
             }
2230 2230
 
@@ -2266,7 +2266,7 @@  discard block
 block discarded – undo
2266 2266
                             ++$bracketCount;
2267 2267
                         } else {
2268 2268
                             $tree[] = &$current;
2269
-                            $current[$uid] = array($uid + 1 => '');
2269
+                            $current[$uid] = array($uid+1 => '');
2270 2270
                             $current = &$current[$uid++];
2271 2271
                             $curTxt = &$current[$uid++];
2272 2272
                             continue;
@@ -2275,7 +2275,7 @@  discard block
 block discarded – undo
2275 2275
                         if ($bracketCount > 0) {
2276 2276
                             --$bracketCount;
2277 2277
                         } else {
2278
-                            $current = &$tree[count($tree) - 1];
2278
+                            $current = &$tree[count($tree)-1];
2279 2279
                             array_pop($tree);
2280 2280
                             if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2281 2281
                                 $current[$uid] = '';
@@ -2439,7 +2439,7 @@  discard block
 block discarded – undo
2439 2439
                 // method
2440 2440
                 if (substr($methMatch[2], 0, 2) === '()') {
2441 2441
                     $parsedCall = $methMatch[1].'()';
2442
-                    $ptr += strlen($methMatch[1]) + 2;
2442
+                    $ptr += strlen($methMatch[1])+2;
2443 2443
                 } else {
2444 2444
                     $parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2445 2445
                 }
@@ -2608,7 +2608,7 @@  discard block
 block discarded – undo
2608 2608
                     if ($cnt > 0) {
2609 2609
                         while (--$cnt >= 0) {
2610 2610
                             if (isset($last)) {
2611
-                                $last = strrpos($key, '$', -(strlen($key) - $last + 1));
2611
+                                $last = strrpos($key, '$', -(strlen($key)-$last+1));
2612 2612
                             } else {
2613 2613
                                 $last = strrpos($key, '$');
2614 2614
                             }
@@ -2673,7 +2673,7 @@  discard block
 block discarded – undo
2673 2673
     protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2674 2674
     {
2675 2675
         $first = $in[$from];
2676
-        $substr = substr($in, $from, $to - $from);
2676
+        $substr = substr($in, $from, $to-$from);
2677 2677
 
2678 2678
         $end = strlen($substr);
2679 2679
 
@@ -2790,7 +2790,7 @@  discard block
 block discarded – undo
2790 2790
         }
2791 2791
         // replace vars
2792 2792
         while (($pos = strpos($string, '$', $pos)) !== false) {
2793
-            $prev = substr($string, $pos - 1, 1);
2793
+            $prev = substr($string, $pos-1, 1);
2794 2794
             if ($prev === '\\') {
2795 2795
                 ++$pos;
2796 2796
                 continue;
@@ -2800,12 +2800,12 @@  discard block
 block discarded – undo
2800 2800
             $len = $var[0];
2801 2801
             $var = $this->parse(str_replace('\\'.$first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2802 2802
 
2803
-            if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
2804
-                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos - 1, $len + 2);
2803
+            if ($prev === '`' && substr($string, $pos+$len, 1) === '`') {
2804
+                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos-1, $len+2);
2805 2805
             } else {
2806 2806
                 $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos, $len);
2807 2807
             }
2808
-            $pos += strlen($var[1]) + 2;
2808
+            $pos += strlen($var[1])+2;
2809 2809
             if ($this->debug) {
2810 2810
                 echo 'STRING VAR REPLACEMENT DONE : '.$string."\n";
2811 2811
             }
@@ -2886,7 +2886,7 @@  discard block
 block discarded – undo
2886 2886
                     echo 'MODIFIER ('.$func.') CALLED WITH NO PARAMS'."\n";
2887 2887
                 }
2888 2888
             } else {
2889
-                $paramstr = substr($cmdstr, $paramspos + 1);
2889
+                $paramstr = substr($cmdstr, $paramspos+1);
2890 2890
                 if (substr($paramstr, -1, 1) === $paramsep) {
2891 2891
                     $paramstr = substr($paramstr, 0, -1);
2892 2892
                 }
@@ -2919,7 +2919,7 @@  discard block
 block discarded – undo
2919 2919
                         if ($paramstr[$ptr] !== '|') {
2920 2920
                             $continue = false;
2921 2921
                             if ($pointer !== null) {
2922
-                                $pointer -= strlen($paramstr) - $ptr;
2922
+                                $pointer -= strlen($paramstr)-$ptr;
2923 2923
                             }
2924 2924
                         }
2925 2925
                         ++$ptr;
@@ -2929,7 +2929,7 @@  discard block
 block discarded – undo
2929 2929
                         ++$ptr;
2930 2930
                     }
2931 2931
                 }
2932
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
2932
+                $cmdstrsrc = substr($cmdstrsrc, strlen($func)+1+$ptr);
2933 2933
                 $paramstr = substr($paramstr, 0, $ptr);
2934 2934
                 foreach ($params as $k => $p) {
2935 2935
                     if (is_array($p) && is_array($p[1])) {
Please login to merge, or discard this patch.
Indentation   +3358 added lines, -3358 removed lines patch added patch discarded remove patch
@@ -19,3362 +19,3362 @@
 block discarded – undo
19 19
  */
20 20
 class Dwoo_Compiler implements Dwoo_ICompiler
21 21
 {
22
-    /**
23
-     * constant that represents a php opening tag.
24
-     *
25
-     * use it in case it needs to be adjusted
26
-     *
27
-     * @var string
28
-     */
29
-    const PHP_OPEN = '<?php ';
30
-
31
-    /**
32
-     * constant that represents a php closing tag.
33
-     *
34
-     * use it in case it needs to be adjusted
35
-     *
36
-     * @var string
37
-     */
38
-    const PHP_CLOSE = '?>';
39
-
40
-    /**
41
-     * boolean flag to enable or disable debugging output.
42
-     *
43
-     * @var bool
44
-     */
45
-    public $debug = false;
46
-
47
-    /**
48
-     * left script delimiter.
49
-     *
50
-     * @var string
51
-     */
52
-    protected $ld = '{';
53
-
54
-    /**
55
-     * left script delimiter with escaped regex meta characters.
56
-     *
57
-     * @var string
58
-     */
59
-    protected $ldr = '\\{';
60
-
61
-    /**
62
-     * right script delimiter.
63
-     *
64
-     * @var string
65
-     */
66
-    protected $rd = '}';
67
-
68
-    /**
69
-     * right script delimiter with escaped regex meta characters.
70
-     *
71
-     * @var string
72
-     */
73
-    protected $rdr = '\\}';
74
-
75
-    /**
76
-     * defines whether the nested comments should be parsed as nested or not.
77
-     *
78
-     * defaults to false (classic block comment parsing as in all languages)
79
-     *
80
-     * @var bool
81
-     */
82
-    protected $allowNestedComments = false;
83
-
84
-    /**
85
-     * defines whether opening and closing tags can contain spaces before valid data or not.
86
-     *
87
-     * turn to true if you want to be sloppy with the syntax, but when set to false it allows
88
-     * to skip javascript and css tags as long as they are in the form "{ something", which is
89
-     * nice. default is false.
90
-     *
91
-     * @var bool
92
-     */
93
-    protected $allowLooseOpenings = false;
94
-
95
-    /**
96
-     * defines whether the compiler will automatically html-escape variables or not.
97
-     *
98
-     * default is false
99
-     *
100
-     * @var bool
101
-     */
102
-    protected $autoEscape = false;
103
-
104
-    /**
105
-     * security policy object.
106
-     *
107
-     * @var Dwoo_Security_Policy
108
-     */
109
-    protected $securityPolicy;
110
-
111
-    /**
112
-     * stores the custom plugins registered with this compiler.
113
-     *
114
-     * @var array
115
-     */
116
-    protected $customPlugins = array();
117
-
118
-    /**
119
-     * stores the template plugins registered with this compiler.
120
-     *
121
-     * @var array
122
-     */
123
-    protected $templatePlugins = array();
124
-
125
-    /**
126
-     * stores the pre- and post-processors callbacks.
127
-     *
128
-     * @var array
129
-     */
130
-    protected $processors = array('pre' => array(), 'post' => array());
131
-
132
-    /**
133
-     * stores a list of plugins that are used in the currently compiled
134
-     * template, and that are not compilable. these plugins will be loaded
135
-     * during the template's runtime if required.
136
-     *
137
-     * it is a 1D array formatted as key:pluginName value:pluginType
138
-     *
139
-     * @var array
140
-     */
141
-    protected $usedPlugins;
142
-
143
-    /**
144
-     * stores the template undergoing compilation.
145
-     *
146
-     * @var string
147
-     */
148
-    protected $template;
149
-
150
-    /**
151
-     * stores the current pointer position inside the template.
152
-     *
153
-     * @var int
154
-     */
155
-    protected $pointer;
156
-
157
-    /**
158
-     * stores the current line count inside the template for debugging purposes.
159
-     *
160
-     * @var int
161
-     */
162
-    protected $line;
163
-
164
-    /**
165
-     * stores the current template source while compiling it.
166
-     *
167
-     * @var string
168
-     */
169
-    protected $templateSource;
170
-
171
-    /**
172
-     * stores the data within which the scope moves.
173
-     *
174
-     * @var array
175
-     */
176
-    protected $data;
177
-
178
-    /**
179
-     * variable scope of the compiler, set to null if
180
-     * it can not be resolved to a static string (i.e. if some
181
-     * plugin defines a new scope based on a variable array key).
182
-     *
183
-     * @var mixed
184
-     */
185
-    protected $scope;
186
-
187
-    /**
188
-     * variable scope tree, that allows to rebuild the current
189
-     * scope if required, i.e. when going to a parent level.
190
-     *
191
-     * @var array
192
-     */
193
-    protected $scopeTree;
194
-
195
-    /**
196
-     * block plugins stack, accessible through some methods.
197
-     *
198
-     * @see findBlock
199
-     * @see getCurrentBlock
200
-     * @see addBlock
201
-     * @see addCustomBlock
202
-     * @see injectBlock
203
-     * @see removeBlock
204
-     * @see removeTopBlock
205
-     *
206
-     * @var array
207
-     */
208
-    protected $stack = array();
209
-
210
-    /**
211
-     * current block at the top of the block plugins stack,
212
-     * accessible through getCurrentBlock.
213
-     *
214
-     * @see getCurrentBlock
215
-     *
216
-     * @var Dwoo_Block_Plugin
217
-     */
218
-    protected $curBlock;
219
-
220
-    /**
221
-     * current dwoo object that uses this compiler, or null.
222
-     *
223
-     * @var Dwoo
224
-     */
225
-    protected $dwoo;
226
-
227
-    /**
228
-     * holds an instance of this class, used by getInstance when you don't
229
-     * provide a custom compiler in order to save resources.
230
-     *
231
-     * @var Dwoo_Compiler
232
-     */
233
-    protected static $instance;
234
-
235
-    /**
236
-     * token types.
237
-     *
238
-     * @var int
239
-     */
240
-    const T_UNQUOTED_STRING = 1;
241
-    const T_NUMERIC = 2;
242
-    const T_NULL = 4;
243
-    const T_BOOL = 8;
244
-    const T_MATH = 16;
245
-    const T_BREAKCHAR = 32;
246
-
247
-    /**
248
-     * constructor.
249
-     *
250
-     * saves the created instance so that child templates get the same one
251
-     */
252
-    public function __construct()
253
-    {
254
-        self::$instance = $this;
255
-    }
256
-
257
-    /**
258
-     * sets the delimiters to use in the templates.
259
-     *
260
-     * delimiters can be multi-character strings but should not be one of those as they will
261
-     * make it very hard to work with templates or might even break the compiler entirely : "\", "$", "|", ":" and finally "#" only if you intend to use config-vars with the #var# syntax.
262
-     *
263
-     * @param string $left  left delimiter
264
-     * @param string $right right delimiter
265
-     */
266
-    public function setDelimiters($left, $right)
267
-    {
268
-        $this->ld = $left;
269
-        $this->rd = $right;
270
-        $this->ldr = preg_quote($left, '/');
271
-        $this->rdr = preg_quote($right, '/');
272
-    }
273
-
274
-    /**
275
-     * returns the left and right template delimiters.
276
-     *
277
-     * @return array containing the left and the right delimiters
278
-     */
279
-    public function getDelimiters()
280
-    {
281
-        return array($this->ld, $this->rd);
282
-    }
283
-
284
-    /**
285
-     * sets the way to handle nested comments, if set to true
286
-     * {* foo {* some other *} comment *} will be stripped correctly.
287
-     *
288
-     * if false it will remove {* foo {* some other *} and leave "comment *}" alone,
289
-     * this is the default behavior
290
-     *
291
-     * @param bool $allow allow nested comments or not, defaults to true (but the default internal value is false)
292
-     */
293
-    public function setNestedCommentsHandling($allow = true)
294
-    {
295
-        $this->allowNestedComments = (bool) $allow;
296
-    }
297
-
298
-    /**
299
-     * returns the nested comments handling setting.
300
-     *
301
-     * @see setNestedCommentsHandling
302
-     *
303
-     * @return bool true if nested comments are allowed
304
-     */
305
-    public function getNestedCommentsHandling()
306
-    {
307
-        return $this->allowNestedComments;
308
-    }
309
-
310
-    /**
311
-     * sets the tag openings handling strictness, if set to true, template tags can
312
-     * contain spaces before the first function/string/variable such as { $foo} is valid.
313
-     *
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
-     *
330
-     * @return bool true if loose tags are allowed
331
-     */
332
-    public function getLooseOpeningHandling()
333
-    {
334
-        return $this->allowLooseOpenings;
335
-    }
336
-
337
-    /**
338
-     * changes the auto escape setting.
339
-     *
340
-     * if enabled, the compiler will automatically html-escape variables,
341
-     * unless they are passed through the safe function such as {$var|safe}
342
-     * or {safe $var}
343
-     *
344
-     * default setting is disabled/false
345
-     *
346
-     * @param bool $enabled set to true to enable, false to disable
347
-     */
348
-    public function setAutoEscape($enabled)
349
-    {
350
-        $this->autoEscape = (bool) $enabled;
351
-    }
352
-
353
-    /**
354
-     * returns the auto escape setting.
355
-     *
356
-     * default setting is disabled/false
357
-     *
358
-     * @return bool
359
-     */
360
-    public function getAutoEscape()
361
-    {
362
-        return $this->autoEscape;
363
-    }
364
-
365
-    /**
366
-     * adds a preprocessor to the compiler, it will be called
367
-     * before the template is compiled.
368
-     *
369
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to true
370
-     * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else you must provide a valid callback
371
-     */
372
-    public function addPreProcessor($callback, $autoload = false)
373
-    {
374
-        if ($autoload) {
375
-            $name = str_replace('Dwoo_Processor_', '', $callback);
376
-            $class = 'Dwoo_Processor_'.$name;
377
-
378
-            if (class_exists($class)) {
379
-                $callback = array(new $class($this), 'process');
380
-            } elseif (function_exists($class)) {
381
-                $callback = $class;
382
-            } else {
383
-                $callback = array('autoload' => true, 'class' => $class, 'name' => $name);
384
-            }
385
-
386
-            $this->processors['pre'][] = $callback;
387
-        } else {
388
-            $this->processors['pre'][] = $callback;
389
-        }
390
-    }
391
-
392
-    /**
393
-     * removes a preprocessor from the compiler.
394
-     *
395
-     * @param mixed $callback either a valid callback to the preprocessor or a simple name if it was autoloaded
396
-     */
397
-    public function removePreProcessor($callback)
398
-    {
399
-        if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
400
-            unset($this->processors['pre'][$index]);
401
-        } elseif (($index = array_search('Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $callback), $this->processors['pre'], true)) !== false) {
402
-            unset($this->processors['pre'][$index]);
403
-        } else {
404
-            $class = 'Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $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 true
419
-     * @param bool  $autoload if set to true, the postprocessor is auto-loaded from one of the plugin directories, else you must provide a valid callback
420
-     */
421
-    public function addPostProcessor($callback, $autoload = false)
422
-    {
423
-        if ($autoload) {
424
-            $name = str_replace('Dwoo_Processor_', '', $callback);
425
-            $class = 'Dwoo_Processor_'.$name;
426
-
427
-            if (class_exists($class)) {
428
-                $callback = array(new $class($this), 'process');
429
-            } elseif (function_exists($class)) {
430
-                $callback = $class;
431
-            } else {
432
-                $callback = array('autoload' => true, 'class' => $class, 'name' => $name);
433
-            }
434
-
435
-            $this->processors['post'][] = $callback;
436
-        } else {
437
-            $this->processors['post'][] = $callback;
438
-        }
439
-    }
440
-
441
-    /**
442
-     * removes a postprocessor from the compiler.
443
-     *
444
-     * @param mixed $callback either a valid callback to the postprocessor or a simple name if it was autoloaded
445
-     */
446
-    public function removePostProcessor($callback)
447
-    {
448
-        if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
449
-            unset($this->processors['post'][$index]);
450
-        } elseif (($index = array_search('Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $callback), $this->processors['post'], true)) !== false) {
451
-            unset($this->processors['post'][$index]);
452
-        } else {
453
-            $class = 'Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $callback);
454
-            foreach ($this->processors['post'] as $index => $proc) {
455
-                if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
456
-                    unset($this->processors['post'][$index]);
457
-                    break;
458
-                }
459
-            }
460
-        }
461
-    }
462
-
463
-    /**
464
-     * internal function to autoload processors at runtime if required.
465
-     *
466
-     * @param string $class the class/function name
467
-     * @param string $name  the plugin name (without Dwoo_Plugin_ prefix)
468
-     *
469
-     * @return array|string
470
-     *
471
-     * @throws Dwoo_Exception
472
-     */
473
-    protected function loadProcessor($class, $name)
474
-    {
475
-        if (!class_exists($class) && !function_exists($class)) {
476
-            try {
477
-                $this->dwoo->getLoader()->loadPlugin($name);
478
-            } catch (Dwoo_Exception $e) {
479
-                throw new Dwoo_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');
480
-            }
481
-        }
482
-
483
-        if (class_exists($class)) {
484
-            return array(new $class($this), 'process');
485
-        }
486
-
487
-        if (function_exists($class)) {
488
-            return $class;
489
-        }
490
-
491
-        throw new Dwoo_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"');
492
-    }
493
-
494
-    /**
495
-     * adds an used plugin, this is reserved for use by the {template} plugin.
496
-     *
497
-     * this is required so that plugin loading bubbles up from loaded
498
-     * template files to the current one
499
-     *
500
-     * @private
501
-     *
502
-     * @param string $name function name
503
-     * @param int    $type plugin type (Dwoo_Core::*_PLUGIN)
504
-     */
505
-    public function addUsedPlugin($name, $type)
506
-    {
507
-        $this->usedPlugins[$name] = $type;
508
-    }
509
-
510
-    /**
511
-     * returns all the plugins this template uses.
512
-     *
513
-     * @private
514
-     *
515
-     * @return array the list of used plugins in the parsed template
516
-     */
517
-    public function getUsedPlugins()
518
-    {
519
-        return $this->usedPlugins;
520
-    }
521
-
522
-    /**
523
-     * adds a template plugin, this is reserved for use by the {template} plugin.
524
-     *
525
-     * this is required because the template functions are not declared yet
526
-     * during compilation, so we must have a way of validating their argument
527
-     * signature without using the reflection api
528
-     *
529
-     * @private
530
-     *
531
-     * @param string $name   function name
532
-     * @param array  $params parameter array to help validate the function call
533
-     * @param string $uuid   unique id of the function
534
-     * @param string $body   function php code
535
-     */
536
-    public function addTemplatePlugin($name, array $params, $uuid, $body = null, Dwoo_ITemplate $sourceTpl = null)
537
-    {
538
-        if (!array_key_exists($name, $this->templatePlugins) || $this->templatePlugins[$name]['uuid'] == $uuid) {
539
-            $this->templatePlugins[$name] = array('params'=> $params, 'body' => $body, 'uuid' => $uuid, 'sourceTpl' => $sourceTpl);
540
-        }
541
-    }
542
-
543
-    /**
544
-     * returns all the parsed sub-templates.
545
-     *
546
-     * @private
547
-     *
548
-     * @return array the parsed sub-templates
549
-     */
550
-    public function getTemplatePlugins()
551
-    {
552
-        return $this->templatePlugins;
553
-    }
554
-
555
-    /**
556
-     * marks a template plugin as being called, which means its source must be included in the compiled template.
557
-     *
558
-     * @param string $name function name
559
-     */
560
-    public function useTemplatePlugin($name)
561
-    {
562
-        $this->templatePlugins[$name]['called'] = true;
563
-    }
564
-
565
-    /**
566
-     * adds the custom plugins loaded into Dwoo to the compiler so it can load them.
567
-     *
568
-     * @see Dwoo_Core::addPlugin
569
-     *
570
-     * @param array $customPlugins an array of custom plugins
571
-     */
572
-    public function setCustomPlugins(array $customPlugins)
573
-    {
574
-        $this->customPlugins = $customPlugins;
575
-    }
576
-
577
-    /**
578
-     * sets the security policy object to enforce some php security settings.
579
-     *
580
-     * use this if untrusted persons can modify templates,
581
-     * set it on the Dwoo object as it will be passed onto the compiler automatically
582
-     *
583
-     * @param Dwoo_Security_Policy $policy the security policy object
584
-     */
585
-    public function setSecurityPolicy(Dwoo_Security_Policy $policy = null)
586
-    {
587
-        $this->securityPolicy = $policy;
588
-    }
589
-
590
-    /**
591
-     * returns the current security policy object or null by default.
592
-     *
593
-     * @return Dwoo_Security_Policy|null the security policy object if any
594
-     */
595
-    public function getSecurityPolicy()
596
-    {
597
-        return $this->securityPolicy;
598
-    }
599
-
600
-    /**
601
-     * sets the pointer position.
602
-     *
603
-     * @param int  $position the new pointer position
604
-     * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
605
-     */
606
-    public function setPointer($position, $isOffset = false)
607
-    {
608
-        if ($isOffset) {
609
-            $this->pointer += $position;
610
-        } else {
611
-            $this->pointer = $position;
612
-        }
613
-    }
614
-
615
-    /**
616
-     * returns the current pointer position, only available during compilation of a template.
617
-     *
618
-     * @return int
619
-     */
620
-    public function getPointer()
621
-    {
622
-        return $this->pointer;
623
-    }
624
-
625
-    /**
626
-     * sets the line number.
627
-     *
628
-     * @param int  $number   the new line number
629
-     * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
630
-     */
631
-    public function setLine($number, $isOffset = false)
632
-    {
633
-        if ($isOffset) {
634
-            $this->line += $number;
635
-        } else {
636
-            $this->line = $number;
637
-        }
638
-    }
639
-
640
-    /**
641
-     * returns the current line number, only available during compilation of a template.
642
-     *
643
-     * @return int
644
-     */
645
-    public function getLine()
646
-    {
647
-        return $this->line;
648
-    }
649
-
650
-    /**
651
-     * returns the dwoo object that initiated this template compilation, only available during compilation of a template.
652
-     *
653
-     * @return Dwoo
654
-     */
655
-    public function getDwoo()
656
-    {
657
-        return $this->dwoo;
658
-    }
659
-
660
-    /**
661
-     * overwrites the template that is being compiled.
662
-     *
663
-     * @param string $newSource   the template source that must replace the current one
664
-     * @param bool   $fromPointer if set to true, only the source from the current pointer position is replaced
665
-     *
666
-     * @return string the template or partial template
667
-     */
668
-    public function setTemplateSource($newSource, $fromPointer = false)
669
-    {
670
-        if ($fromPointer === true) {
671
-            $this->templateSource = substr($this->templateSource, 0, $this->pointer).$newSource;
672
-        } else {
673
-            $this->templateSource = $newSource;
674
-        }
675
-    }
676
-
677
-    /**
678
-     * returns the template that is being compiled.
679
-     *
680
-     * @param mixed $fromPointer if set to true, only the source from the current pointer
681
-     *                           position is returned, if a number is given it overrides the current pointer
682
-     *
683
-     * @return string the template or partial template
684
-     */
685
-    public function getTemplateSource($fromPointer = false)
686
-    {
687
-        if ($fromPointer === true) {
688
-            return substr($this->templateSource, $this->pointer);
689
-        } elseif (is_numeric($fromPointer)) {
690
-            return substr($this->templateSource, $fromPointer);
691
-        } else {
692
-            return $this->templateSource;
693
-        }
694
-    }
695
-
696
-    /**
697
-     * resets the compilation pointer, effectively restarting the compilation process.
698
-     *
699
-     * this is useful if a plugin modifies the template source since it might need to be recompiled
700
-     */
701
-    public function recompile()
702
-    {
703
-        $this->setPointer(0);
704
-    }
705
-
706
-    /**
707
-     * compiles the provided string down to php code.
708
-     *
709
-     * @param Dwoo_Core      $dwoo
710
-     * @param Dwoo_ITemplate $template the template to compile
711
-     *
712
-     * @return string a compiled php string
713
-     *
714
-     * @throws Dwoo_Compilation_Exception
715
-     */
716
-    public function compile(Dwoo_Core $dwoo, Dwoo_ITemplate $template)
717
-    {
718
-        // init vars
719
-        $tpl = $template->getSource();
720
-        $ptr = 0;
721
-        $this->dwoo = $dwoo;
722
-        $this->template = $template;
723
-        $this->templateSource = &$tpl;
724
-        $this->pointer = &$ptr;
725
-
726
-        while (true) {
727
-            // if pointer is at the beginning, reset everything, that allows a plugin to externally reset the compiler if everything must be reparsed
728
-            if ($ptr === 0) {
729
-                // resets variables
730
-                $this->usedPlugins = array();
731
-                $this->data = array();
732
-                $this->scope = &$this->data;
733
-                $this->scopeTree = array();
734
-                $this->stack = array();
735
-                $this->line = 1;
736
-                $this->templatePlugins = array();
737
-                // add top level block
738
-                $compiled = $this->addBlock('topLevelBlock', array(), 0);
739
-                $this->stack[0]['buffer'] = '';
740
-
741
-                if ($this->debug) {
742
-                    echo "\n";
743
-                    echo 'COMPILER INIT'."\n";
744
-                }
745
-
746
-                if ($this->debug) {
747
-                    echo 'PROCESSING PREPROCESSORS ('.count($this->processors['pre']).')'."\n";
748
-                }
749
-
750
-                // runs preprocessors
751
-                foreach ($this->processors['pre'] as $preProc) {
752
-                    if (is_array($preProc) && isset($preProc['autoload'])) {
753
-                        $preProc = $this->loadProcessor($preProc['class'], $preProc['name']);
754
-                    }
755
-                    if (is_array($preProc) && $preProc[0] instanceof Dwoo_Processor) {
756
-                        $tpl = call_user_func($preProc, $tpl);
757
-                    } else {
758
-                        $tpl = call_user_func($preProc, $this, $tpl);
759
-                    }
760
-                }
761
-                unset($preProc);
762
-
763
-                // show template source if debug
764
-                if ($this->debug) {
765
-                    echo '<pre>'.print_r(htmlentities($tpl), true).'</pre>'."\n";
766
-                }
767
-
768
-                // strips php tags if required by the security policy
769
-                if ($this->securityPolicy !== null) {
770
-                    $search = array('{<\?php.*?\?>}');
771
-                    if (ini_get('short_open_tags')) {
772
-                        $search = array('{<\?.*?\?>}', '{<%.*?%>}');
773
-                    }
774
-                    switch ($this->securityPolicy->getPhpHandling()) {
775
-
776
-                    case Dwoo_Security_Policy::PHP_ALLOW:
777
-                        break;
778
-                    case Dwoo_Security_Policy::PHP_ENCODE:
779
-                        $tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
780
-                        break;
781
-                    case Dwoo_Security_Policy::PHP_REMOVE:
782
-                        $tpl = preg_replace($search, '', $tpl);
783
-
784
-                    }
785
-                }
786
-            }
787
-
788
-            $pos = strpos($tpl, $this->ld, $ptr);
789
-
790
-            if ($pos === false) {
791
-                $this->push(substr($tpl, $ptr), 0);
792
-                break;
793
-            } elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
794
-                $this->push(substr($tpl, $ptr, $pos - $ptr - 1).$this->ld);
795
-                $ptr = $pos + strlen($this->ld);
796
-            } elseif (preg_match('/^'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', substr($tpl, $pos), $litOpen)) {
797
-                if (!preg_match('/'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'\/literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
798
-                    throw new Dwoo_Compilation_Exception($this, 'The {literal} blocks must be closed explicitly with {/literal}');
799
-                }
800
-                $endpos = $litClose[0][1];
801
-                $this->push(substr($tpl, $ptr, $pos - $ptr).substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
802
-                $ptr = $endpos + strlen($litClose[0][0]);
803
-            } else {
804
-                if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
805
-                    $this->push(substr($tpl, $ptr, $pos - $ptr - 1));
806
-                    $ptr = $pos;
807
-                }
808
-
809
-                $this->push(substr($tpl, $ptr, $pos - $ptr));
810
-                $ptr = $pos;
811
-
812
-                $pos += strlen($this->ld);
813
-                if ($this->allowLooseOpenings) {
814
-                    while (substr($tpl, $pos, 1) === ' ') {
815
-                        $pos += 1;
816
-                    }
817
-                } else {
818
-                    if (substr($tpl, $pos, 1) === ' ' || substr($tpl, $pos, 1) === "\r" || substr($tpl, $pos, 1) === "\n" || substr($tpl, $pos, 1) === "\t") {
819
-                        $ptr = $pos;
820
-                        $this->push($this->ld);
821
-                        continue;
822
-                    }
823
-                }
824
-
825
-                // check that there is an end tag present
826
-                if (strpos($tpl, $this->rd, $pos) === false) {
827
-                    throw new Dwoo_Compilation_Exception($this, 'A template tag was not closed, started with "'.substr($tpl, $ptr, 30).'"');
828
-                }
829
-
830
-                $ptr += strlen($this->ld);
831
-                $subptr = $ptr;
832
-
833
-                while (true) {
834
-                    $parsed = $this->parse($tpl, $subptr, null, false, 'root', $subptr);
835
-
836
-                    // reload loop if the compiler was reset
837
-                    if ($ptr === 0) {
838
-                        continue 2;
839
-                    }
840
-
841
-                    $len = $subptr - $ptr;
842
-                    $this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
843
-                    $ptr += $len;
844
-
845
-                    if ($parsed === false) {
846
-                        break;
847
-                    }
848
-                }
849
-            }
850
-        }
851
-
852
-        $compiled .= $this->removeBlock('topLevelBlock');
853
-
854
-        if ($this->debug) {
855
-            echo 'PROCESSING POSTPROCESSORS'."\n";
856
-        }
857
-
858
-        foreach ($this->processors['post'] as $postProc) {
859
-            if (is_array($postProc) && isset($postProc['autoload'])) {
860
-                $postProc = $this->loadProcessor($postProc['class'], $postProc['name']);
861
-            }
862
-            if (is_array($postProc) && $postProc[0] instanceof Dwoo_Processor) {
863
-                $compiled = call_user_func($postProc, $compiled);
864
-            } else {
865
-                $compiled = call_user_func($postProc, $this, $compiled);
866
-            }
867
-        }
868
-        unset($postProc);
869
-
870
-        if ($this->debug) {
871
-            echo 'COMPILATION COMPLETE : MEM USAGE : '.memory_get_usage()."\n";
872
-        }
873
-
874
-        $output = "<?php\n/* template head */\n";
875
-
876
-        // build plugin preloader
877
-        foreach ($this->usedPlugins as $plugin => $type) {
878
-            if ($type & Dwoo_Core::CUSTOM_PLUGIN) {
879
-                continue;
880
-            }
881
-
882
-            switch ($type) {
883
-
884
-            case Dwoo_Core::BLOCK_PLUGIN:
885
-            case Dwoo_Core::CLASS_PLUGIN:
886
-                $output .= "if (class_exists('Dwoo_Plugin_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
887
-                break;
888
-            case Dwoo_Core::FUNC_PLUGIN:
889
-                $output .= "if (function_exists('Dwoo_Plugin_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
890
-                break;
891
-            case Dwoo_Core::SMARTY_MODIFIER:
892
-                $output .= "if (function_exists('smarty_modifier_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
893
-                break;
894
-            case Dwoo_Core::SMARTY_FUNCTION:
895
-                $output .= "if (function_exists('smarty_function_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
896
-                break;
897
-            case Dwoo_Core::SMARTY_BLOCK:
898
-                $output .= "if (function_exists('smarty_block_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
899
-                break;
900
-            case Dwoo_Core::PROXY_PLUGIN:
901
-                $output .= $this->getDwoo()->getPluginProxy()->getPreloader($plugin);
902
-                break;
903
-            default:
904
-                throw new Dwoo_Compilation_Exception($this, 'Type error for '.$plugin.' with type'.$type);
905
-
906
-            }
907
-        }
908
-
909
-        foreach ($this->templatePlugins as $function => $attr) {
910
-            if (isset($attr['called']) && $attr['called'] === true && !isset($attr['checked'])) {
911
-                $this->resolveSubTemplateDependencies($function);
912
-            }
913
-        }
914
-        foreach ($this->templatePlugins as $function) {
915
-            if (isset($function['called']) && $function['called'] === true) {
916
-                $output .= $function['body'].PHP_EOL;
917
-            }
918
-        }
919
-
920
-        $output .= $compiled."\n?>";
921
-
922
-        $output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*'.preg_quote(self::PHP_CLOSE, '/').preg_quote(self::PHP_OPEN, '/').')/', ";\n", $output);
923
-        $output = str_replace(self::PHP_CLOSE.self::PHP_OPEN, "\n", $output);
924
-
925
-        // handle <?xml tag at the beginning
926
-        $output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
927
-
928
-        // add another line break after PHP closing tags that have a line break following,
929
-        // as we do not know whether it's intended, and PHP will strip it otherwise
930
-        $output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0'."\n", $output);
931
-
932
-        if ($this->debug) {
933
-            echo '============================================================================================='."\n";
934
-            $lines = preg_split('{\r\n|\n|<br />}', $output);
935
-            array_shift($lines);
936
-            foreach ($lines as $i => $line) {
937
-                echo($i + 1).'. '.$line."\r\n";
938
-            }
939
-            echo '============================================================================================='."\n";
940
-        }
941
-
942
-        $this->template = $this->dwoo = null;
943
-        $tpl = null;
944
-
945
-        return $output;
946
-    }
947
-
948
-    /**
949
-     * checks what sub-templates are used in every sub-template so that we're sure they are all compiled.
950
-     *
951
-     * @param string $function the sub-template name
952
-     */
953
-    protected function resolveSubTemplateDependencies($function)
954
-    {
955
-        if ($this->debug) {
956
-            echo 'Compiler::'.__FUNCTION__."\n";
957
-        }
958
-
959
-        $body = $this->templatePlugins[$function]['body'];
960
-        foreach ($this->templatePlugins as $func => $attr) {
961
-            if ($func !== $function && !isset($attr['called']) && strpos($body, 'Dwoo_Plugin_'.$func) !== false) {
962
-                $this->templatePlugins[$func]['called'] = true;
963
-                $this->resolveSubTemplateDependencies($func);
964
-            }
965
-        }
966
-        $this->templatePlugins[$function]['checked'] = true;
967
-    }
968
-
969
-    /**
970
-     * adds compiled content to the current block.
971
-     *
972
-     * @param string $content   the content to push
973
-     * @param int    $lineCount newlines count in content, optional
974
-     *
975
-     * @throws Dwoo_Compilation_Exception
976
-     */
977
-    public function push($content, $lineCount = null)
978
-    {
979
-        if ($lineCount === null) {
980
-            $lineCount = substr_count($content, "\n");
981
-        }
982
-
983
-        if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
984
-            // buffer is not initialized yet (the block has just been created)
985
-            $this->stack[count($this->stack) - 2]['buffer'] .= (string) $content;
986
-            $this->curBlock['buffer'] = '';
987
-        } else {
988
-            if (!isset($this->curBlock['buffer'])) {
989
-                throw new Dwoo_Compilation_Exception($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
990
-            }
991
-            // append current content to current block's buffer
992
-            $this->curBlock['buffer'] .= (string) $content;
993
-        }
994
-        $this->line += $lineCount;
995
-    }
996
-
997
-    /**
998
-     * sets the scope.
999
-     *
1000
-     * set to null if the scope becomes "unstable" (i.e. too variable or unknown) so that
1001
-     * variables are compiled in a more evaluative way than just $this->scope['key']
1002
-     *
1003
-     * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1004
-     * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1005
-     *
1006
-     * @return array the current scope tree
1007
-     */
1008
-    public function setScope($scope, $absolute = false)
1009
-    {
1010
-        $old = $this->scopeTree;
1011
-
1012
-        if ($scope === null) {
1013
-            unset($this->scope);
1014
-            $this->scope = null;
1015
-        }
1016
-
1017
-        if (is_array($scope) === false) {
1018
-            $scope = explode('.', $scope);
1019
-        }
1020
-
1021
-        if ($absolute === true) {
1022
-            $this->scope = &$this->data;
1023
-            $this->scopeTree = array();
1024
-        }
1025
-
1026
-        while (($bit = array_shift($scope)) !== null) {
1027
-            if ($bit === '_parent' || $bit === '_') {
1028
-                array_pop($this->scopeTree);
1029
-                reset($this->scopeTree);
1030
-                $this->scope = &$this->data;
1031
-                $cnt = count($this->scopeTree);
1032
-                for ($i = 0; $i < $cnt; ++$i) {
1033
-                    $this->scope = &$this->scope[$this->scopeTree[$i]];
1034
-                }
1035
-            } elseif ($bit === '_root' || $bit === '__') {
1036
-                $this->scope = &$this->data;
1037
-                $this->scopeTree = array();
1038
-            } elseif (isset($this->scope[$bit])) {
1039
-                $this->scope = &$this->scope[$bit];
1040
-                $this->scopeTree[] = $bit;
1041
-            } else {
1042
-                $this->scope[$bit] = array();
1043
-                $this->scope = &$this->scope[$bit];
1044
-                $this->scopeTree[] = $bit;
1045
-            }
1046
-        }
1047
-
1048
-        return $old;
1049
-    }
1050
-
1051
-    /**
1052
-     * adds a block to the top of the block stack.
1053
-     *
1054
-     * @param string $type      block type (name)
1055
-     * @param array  $params    the parameters array
1056
-     * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1057
-     *
1058
-     * @return string the preProcessing() method's output
1059
-     */
1060
-    public function addBlock($type, array $params, $paramtype)
1061
-    {
1062
-        if ($this->debug) {
1063
-            echo 'Compiler::'.__FUNCTION__."\n";
1064
-        }
1065
-
1066
-        $class = 'Dwoo_Plugin_'.$type;
1067
-        if (class_exists($class) === false) {
1068
-            $this->dwoo->getLoader()->loadPlugin($type);
1069
-        }
1070
-        $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1071
-
1072
-        $this->stack[] = array('type' => $type, 'params' => $params, 'custom' => false, 'class' => $class, 'buffer' => null);
1073
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1074
-
1075
-        return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1076
-    }
1077
-
1078
-    /**
1079
-     * adds a custom block to the top of the block stack.
1080
-     *
1081
-     * @param string $type      block type (name)
1082
-     * @param array  $params    the parameters array
1083
-     * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1084
-     *
1085
-     * @return string the preProcessing() method's output
1086
-     */
1087
-    public function addCustomBlock($type, array $params, $paramtype)
1088
-    {
1089
-        $callback = $this->customPlugins[$type]['callback'];
1090
-        if (is_array($callback)) {
1091
-            $class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
1092
-        } else {
1093
-            $class = $callback;
1094
-        }
1095
-
1096
-        $params = $this->mapParams($params, array($class, 'init'), $paramtype);
1097
-
1098
-        $this->stack[] = array('type' => $type, 'params' => $params, 'custom' => true, 'class' => $class, 'buffer' => null);
1099
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1100
-
1101
-        return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1102
-    }
1103
-
1104
-    /**
1105
-     * injects a block at the top of the plugin stack without calling its preProcessing method.
1106
-     *
1107
-     * used by {else} blocks to re-add themselves after having closed everything up to their parent
1108
-     *
1109
-     * @param string $type   block type (name)
1110
-     * @param array  $params parameters array
1111
-     */
1112
-    public function injectBlock($type, array $params)
1113
-    {
1114
-        if ($this->debug) {
1115
-            echo 'Compiler::'.__FUNCTION__."\n";
1116
-        }
1117
-
1118
-        $class = 'Dwoo_Plugin_'.$type;
1119
-        if (class_exists($class) === false) {
1120
-            $this->dwoo->getLoader()->loadPlugin($type);
1121
-        }
1122
-        $this->stack[] = array('type' => $type, 'params' => $params, 'custom' => false, 'class' => $class, 'buffer' => null);
1123
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1124
-    }
1125
-
1126
-    /**
1127
-     * removes the closest-to-top block of the given type and all other
1128
-     * blocks encountered while going down the block stack.
1129
-     *
1130
-     * @param string $type block type (name)
1131
-     *
1132
-     * @return string the output of all postProcessing() method's return values of the closed blocks
1133
-     *
1134
-     * @throws Dwoo_Compilation_Exception
1135
-     */
1136
-    public function removeBlock($type)
1137
-    {
1138
-        if ($this->debug) {
1139
-            echo 'Compiler::'.__FUNCTION__."\n";
1140
-        }
1141
-
1142
-        $output = '';
1143
-
1144
-        $pluginType = $this->getPluginType($type);
1145
-        if ($pluginType & Dwoo_Core::SMARTY_BLOCK) {
1146
-            $type = 'smartyinterface';
1147
-        }
1148
-        while (true) {
1149
-            while ($top = array_pop($this->stack)) {
1150
-                if ($top['custom']) {
1151
-                    $class = $top['class'];
1152
-                } else {
1153
-                    $class = 'Dwoo_Plugin_'.$top['type'];
1154
-                }
1155
-                if (count($this->stack)) {
1156
-                    $this->curBlock = &$this->stack[count($this->stack) - 1];
1157
-                    $this->push(call_user_func(array($class, 'postProcessing'), $this, $top['params'], '', '', $top['buffer']), 0);
1158
-                } else {
1159
-                    $null = null;
1160
-                    $this->curBlock = &$null;
1161
-                    $output = call_user_func(array($class, 'postProcessing'), $this, $top['params'], '', '', $top['buffer']);
1162
-                }
1163
-
1164
-                if ($top['type'] === $type) {
1165
-                    break 2;
1166
-                }
1167
-            }
1168
-
1169
-            throw new Dwoo_Compilation_Exception($this, 'Syntax malformation, a block of type "'.$type.'" was closed but was not opened');
1170
-            break;
1171
-        }
1172
-
1173
-        return $output;
1174
-    }
1175
-
1176
-    /**
1177
-     * returns a reference to the first block of the given type encountered and
1178
-     * optionally closes all blocks until it finds it
1179
-     * this is mainly used by {else} plugins to close everything that was opened
1180
-     * between their parent and themselves.
1181
-     *
1182
-     * @param string $type       the block type (name)
1183
-     * @param bool   $closeAlong whether to close all blocks encountered while going down the block stack or not
1184
-     *
1185
-     * @return mixed &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1186
-     *               'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1187
-     *
1188
-     * @throws Dwoo_Compilation_Exception
1189
-     */
1190
-    public function &findBlock($type, $closeAlong = false)
1191
-    {
1192
-        if ($closeAlong === true) {
1193
-            while ($b = end($this->stack)) {
1194
-                if ($b['type'] === $type) {
1195
-                    return $this->stack[key($this->stack)];
1196
-                }
1197
-                $this->push($this->removeTopBlock(), 0);
1198
-            }
1199
-        } else {
1200
-            end($this->stack);
1201
-            while ($b = current($this->stack)) {
1202
-                if ($b['type'] === $type) {
1203
-                    return $this->stack[key($this->stack)];
1204
-                }
1205
-                prev($this->stack);
1206
-            }
1207
-        }
1208
-
1209
-        throw new Dwoo_Compilation_Exception($this, 'A parent block of type "'.$type.'" is required and can not be found');
1210
-    }
1211
-
1212
-    /**
1213
-     * returns a reference to the current block array.
1214
-     *
1215
-     * @return &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1216
-     *                'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1217
-     */
1218
-    public function &getCurrentBlock()
1219
-    {
1220
-        return $this->curBlock;
1221
-    }
1222
-
1223
-    /**
1224
-     * removes the block at the top of the stack and calls its postProcessing() method.
1225
-     *
1226
-     * @return string the postProcessing() method's output
1227
-     *
1228
-     * @throws Dwoo_Compilation_Exception
1229
-     */
1230
-    public function removeTopBlock()
1231
-    {
1232
-        if ($this->debug) {
1233
-            echo 'Compiler::'.__FUNCTION__."\n";
1234
-        }
1235
-
1236
-        $o = array_pop($this->stack);
1237
-        if ($o === null) {
1238
-            throw new Dwoo_Compilation_Exception($this, 'Syntax malformation, a block of unknown type was closed but was not opened.');
1239
-        }
1240
-        if ($o['custom']) {
1241
-            $class = $o['class'];
1242
-        } else {
1243
-            $class = 'Dwoo_Plugin_'.$o['type'];
1244
-        }
1245
-
1246
-        $this->curBlock = &$this->stack[count($this->stack) - 1];
1247
-
1248
-        return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1249
-    }
1250
-
1251
-    /**
1252
-     * returns the compiled parameters (for example a variable's compiled parameter will be "$this->scope['key']") out of the given parameter array.
1253
-     *
1254
-     * @param array $params parameter array
1255
-     *
1256
-     * @return array filtered parameters
1257
-     */
1258
-    public function getCompiledParams(array $params)
1259
-    {
1260
-        foreach ($params as $k => $p) {
1261
-            if (is_array($p)) {
1262
-                $params[$k] = $p[0];
1263
-            }
1264
-        }
1265
-
1266
-        return $params;
1267
-    }
1268
-
1269
-    /**
1270
-     * returns the real parameters (for example a variable's real parameter will be its key, etc) out of the given parameter array.
1271
-     *
1272
-     * @param array $params parameter array
1273
-     *
1274
-     * @return array filtered parameters
1275
-     */
1276
-    public function getRealParams(array $params)
1277
-    {
1278
-        foreach ($params as $k => $p) {
1279
-            if (is_array($p)) {
1280
-                $params[$k] = $p[1];
1281
-            }
1282
-        }
1283
-
1284
-        return $params;
1285
-    }
1286
-
1287
-    /**
1288
-     * returns the token of each parameter out of the given parameter array.
1289
-     *
1290
-     * @param array $params parameter array
1291
-     *
1292
-     * @return array tokens
1293
-     */
1294
-    public function getParamTokens(array $params)
1295
-    {
1296
-        foreach ($params as $k => $p) {
1297
-            if (is_array($p)) {
1298
-                $params[$k] = isset($p[2]) ? $p[2] : 0;
1299
-            }
1300
-        }
1301
-
1302
-        return $params;
1303
-    }
1304
-
1305
-    /**
1306
-     * entry point of the parser, it redirects calls to other parse* functions.
1307
-     *
1308
-     * @param string $in            the string within which we must parse something
1309
-     * @param int    $from          the starting offset of the parsed area
1310
-     * @param int    $to            the ending offset of the parsed area
1311
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
1312
-     * @param string $curBlock      the current parser-block being processed
1313
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
1314
-     *
1315
-     * @return string parsed values
1316
-     *
1317
-     * @throws Dwoo_Compilation_Exception
1318
-     */
1319
-    protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1320
-    {
1321
-        if ($this->debug) {
1322
-            echo 'Compiler::'.__FUNCTION__."\n";
1323
-        }
1324
-
1325
-        if ($to === null) {
1326
-            $to = strlen($in);
1327
-        }
1328
-        $first = substr($in, $from, 1);
1329
-
1330
-        if ($first === false) {
1331
-            throw new Dwoo_Compilation_Exception($this, 'Unexpected EOF, a template tag was not closed');
1332
-        }
1333
-
1334
-        while ($first === ' ' || $first === "\n" || $first === "\t" || $first === "\r") {
1335
-            if ($curBlock === 'root' && substr($in, $from, strlen($this->rd)) === $this->rd) {
1336
-                // end template tag
1337
-                $pointer += strlen($this->rd);
1338
-                if ($this->debug) {
1339
-                    echo 'TEMPLATE PARSING ENDED'."\n";
1340
-                }
1341
-
1342
-                return false;
1343
-            }
1344
-            ++$from;
1345
-            if ($pointer !== null) {
1346
-                ++$pointer;
1347
-            }
1348
-            if ($from >= $to) {
1349
-                if (is_array($parsingParams)) {
1350
-                    return $parsingParams;
1351
-                } else {
1352
-                    return '';
1353
-                }
1354
-            }
1355
-            $first = $in[$from];
1356
-        }
1357
-
1358
-        $substr = substr($in, $from, $to - $from);
1359
-
1360
-        if ($this->debug) {
1361
-            echo 'PARSE CALL : PARSING "<b>'.htmlentities(substr($in, $from, min($to - $from, 50))).(($to - $from) > 50 ? '...' : '').'</b>" @ '.$from.':'.$to.' in '.$curBlock.' : pointer='.$pointer."\n";
1362
-        }
1363
-        $parsed = '';
1364
-
1365
-        if ($curBlock === 'root' && $first === '*') {
1366
-            $src = $this->getTemplateSource();
1367
-            $startpos = $this->getPointer() - strlen($this->ld);
1368
-            if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1369
-                if ($startpos > 0) {
1370
-                    do {
1371
-                        $char = substr($src, --$startpos, 1);
1372
-                        if ($char == "\n") {
1373
-                            ++$startpos;
1374
-                            $whitespaceStart = true;
1375
-                            break;
1376
-                        }
1377
-                    } while ($startpos > 0 && ($char == ' ' || $char == "\t"));
1378
-                }
1379
-
1380
-                if (!isset($whitespaceStart)) {
1381
-                    $startpos = $this->getPointer();
1382
-                } else {
1383
-                    $pointer -= $this->getPointer() - $startpos;
1384
-                }
1385
-
1386
-                if ($this->allowNestedComments && strpos($src, $this->ld.'*', $this->getPointer()) !== false) {
1387
-                    $comOpen = $this->ld.'*';
1388
-                    $comClose = '*'.$this->rd;
1389
-                    $level = 1;
1390
-                    $ptr = $this->getPointer();
1391
-
1392
-                    while ($level > 0 && $ptr < strlen($src)) {
1393
-                        $open = strpos($src, $comOpen, $ptr);
1394
-                        $close = strpos($src, $comClose, $ptr);
1395
-
1396
-                        if ($open !== false && $close !== false) {
1397
-                            if ($open < $close) {
1398
-                                $ptr = $open + strlen($comOpen);
1399
-                                ++$level;
1400
-                            } else {
1401
-                                $ptr = $close + strlen($comClose);
1402
-                                --$level;
1403
-                            }
1404
-                        } elseif ($open !== false) {
1405
-                            $ptr = $open + strlen($comOpen);
1406
-                            ++$level;
1407
-                        } elseif ($close !== false) {
1408
-                            $ptr = $close + strlen($comClose);
1409
-                            --$level;
1410
-                        } else {
1411
-                            $ptr = strlen($src);
1412
-                        }
1413
-                    }
1414
-                    $endpos = $ptr - strlen('*'.$this->rd);
1415
-                } else {
1416
-                    $endpos = strpos($src, '*'.$this->rd, $startpos);
1417
-                    if ($endpos == false) {
1418
-                        throw new Dwoo_Compilation_Exception($this, 'Un-ended comment');
1419
-                    }
1420
-                }
1421
-                $pointer += $endpos - $startpos + strlen('*'.$this->rd);
1422
-                if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*'.$this->rd)), $m)) {
1423
-                    $pointer += strlen($m[0]);
1424
-                    $this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1425
-                }
1426
-
1427
-                return false;
1428
-            }
1429
-        }
1430
-
1431
-        if ($first === '$') {
1432
-            // var
1433
-            $out = $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
1434
-            $parsed = 'var';
1435
-        } elseif ($first === '%' && preg_match('#^%[a-z_]#i', $substr)) {
1436
-            // const
1437
-            $out = $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
1438
-        } elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1439
-            // string
1440
-            $out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1441
-        } 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)) {
1442
-            // func
1443
-            $out = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1444
-            $parsed = 'func';
1445
-        } elseif ($first === ';') {
1446
-            // instruction end
1447
-            if ($this->debug) {
1448
-                echo 'END OF INSTRUCTION'."\n";
1449
-            }
1450
-            if ($pointer !== null) {
1451
-                ++$pointer;
1452
-            }
1453
-
1454
-            return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1455
-        } elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1456
-            // close block
1457
-            if (!empty($match[1]) && $match[1] == 'else') {
1458
-                throw new Dwoo_Compilation_Exception($this, 'Else blocks must not be closed explicitly, they are automatically closed when their parent block is closed');
1459
-            }
1460
-            if (!empty($match[1]) && $match[1] == 'elseif') {
1461
-                throw new Dwoo_Compilation_Exception($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');
1462
-            }
1463
-            if ($pointer !== null) {
1464
-                $pointer += strlen($match[0]);
1465
-            }
1466
-            if (empty($match[1])) {
1467
-                if ($this->curBlock['type'] == 'else' || $this->curBlock['type'] == 'elseif') {
1468
-                    $pointer -= strlen($match[0]);
1469
-                }
1470
-                if ($this->debug) {
1471
-                    echo 'TOP BLOCK CLOSED'."\n";
1472
-                }
1473
-
1474
-                return $this->removeTopBlock();
1475
-            } else {
1476
-                if ($this->debug) {
1477
-                    echo 'BLOCK OF TYPE '.$match[1].' CLOSED'."\n";
1478
-                }
1479
-
1480
-                return $this->removeBlock($match[1]);
1481
-            }
1482
-        } elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1483
-            // end template tag
1484
-            if ($this->debug) {
1485
-                echo 'TAG PARSING ENDED'."\n";
1486
-            }
1487
-            $pointer += strlen($this->rd);
1488
-
1489
-            return false;
1490
-        } elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*='.($curBlock === 'array' ? '>?' : '').')(?:\s+|[^=]).*#i', $substr, $match)) {
1491
-            // named parameter
1492
-            if ($this->debug) {
1493
-                echo 'NAMED PARAM FOUND'."\n";
1494
-            }
1495
-            $len = strlen($match[1]);
1496
-            while (substr($in, $from + $len, 1) === ' ') {
1497
-                ++$len;
1498
-            }
1499
-            if ($pointer !== null) {
1500
-                $pointer += $len;
1501
-            }
1502
-
1503
-            $output = array(trim($match[1], " \t\r\n=>'\""), $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer));
1504
-
1505
-            $parsingParams[] = $output;
1506
-
1507
-            return $parsingParams;
1508
-        } elseif (preg_match('#^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*::\$[a-z0-9_]+)#i', $substr, $match)) {
1509
-            // static member access
1510
-            $parsed = 'var';
1511
-            if (is_array($parsingParams)) {
1512
-                $parsingParams[] = array($match[1], $match[1]);
1513
-                $out = $parsingParams;
1514
-            } else {
1515
-                $out = $match[1];
1516
-            }
1517
-            $pointer += strlen($match[1]);
1518
-        } elseif ($substr !== '' && (is_array($parsingParams) || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'expression')) {
1519
-            // unquoted string, bool or number
1520
-            $out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1521
-        } else {
1522
-            // parse error
1523
-            throw new Dwoo_Compilation_Exception($this, 'Parse error in "'.substr($in, $from, $to - $from).'"');
1524
-        }
1525
-
1526
-        if (empty($out)) {
1527
-            return '';
1528
-        }
1529
-
1530
-        $substr = substr($in, $pointer, $to - $pointer);
1531
-
1532
-        // var parsed, check if any var-extension applies
1533
-        if ($parsed === 'var') {
1534
-            if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1535
-                if ($this->debug) {
1536
-                    echo 'PARSING POST-VAR EXPRESSION '.$substr."\n";
1537
-                }
1538
-                // parse expressions
1539
-                $pointer += strlen($match[0]) - 1;
1540
-                if (is_array($parsingParams)) {
1541
-                    if ($match[2] == '$') {
1542
-                        $expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1543
-                    } else {
1544
-                        $expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1545
-                    }
1546
-                    $out[count($out) - 1][0] .= $match[1].$expr[0][0];
1547
-                    $out[count($out) - 1][1] .= $match[1].$expr[0][1];
1548
-                } else {
1549
-                    if ($match[2] == '$') {
1550
-                        $expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
1551
-                    } else {
1552
-                        $expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1553
-                    }
1554
-                    if (is_array($out) && is_array($expr)) {
1555
-                        $out[0] .= $match[1].$expr[0];
1556
-                        $out[1] .= $match[1].$expr[1];
1557
-                    } elseif (is_array($out)) {
1558
-                        $out[0] .= $match[1].$expr;
1559
-                        $out[1] .= $match[1].$expr;
1560
-                    } elseif (is_array($expr)) {
1561
-                        $out .= $match[1].$expr[0];
1562
-                    } else {
1563
-                        $out .= $match[1].$expr;
1564
-                    }
1565
-                }
1566
-            } elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1567
-                if ($this->debug) {
1568
-                    echo 'PARSING POST-VAR ASSIGNMENT '.$substr."\n";
1569
-                }
1570
-                // parse assignment
1571
-                $value = $match[2];
1572
-                $operator = trim($match[1]);
1573
-                if (substr($value, 0, 1) == '=') {
1574
-                    throw new Dwoo_Compilation_Exception($this, 'Unexpected "=" in <em>'.$substr.'</em>');
1575
-                }
1576
-
1577
-                if ($pointer !== null) {
1578
-                    $pointer += strlen($match[1]);
1579
-                }
1580
-
1581
-                if ($operator !== '++' && $operator !== '--') {
1582
-                    $parts = array();
1583
-                    $ptr = 0;
1584
-                    $parts = $this->parse($value, 0, strlen($value), $parts, 'condition', $ptr);
1585
-                    $pointer += $ptr;
1586
-
1587
-                    // load if plugin
1588
-                    try {
1589
-                        $this->getPluginType('if');
1590
-                    } catch (Dwoo_Exception $e) {
1591
-                        throw new Dwoo_Compilation_Exception($this, 'Assignments require the "if" plugin to be accessible');
1592
-                    }
1593
-
1594
-                    $parts = $this->mapParams($parts, array('Dwoo_Plugin_if', 'init'), 1);
1595
-                    $tokens = $this->getParamTokens($parts);
1596
-                    $parts = $this->getCompiledParams($parts);
1597
-
1598
-                    $value = Dwoo_Plugin_if::replaceKeywords($parts['*'], $tokens['*'], $this);
1599
-                    $echo = '';
1600
-                } else {
1601
-                    $value = array();
1602
-                    $echo = 'echo ';
1603
-                }
1604
-
1605
-                if ($this->autoEscape) {
1606
-                    $out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1607
-                }
1608
-                $out = self::PHP_OPEN.$echo.$out.$operator.implode(' ', $value).self::PHP_CLOSE;
1609
-            } elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1610
-                // parse namedparam with var as name (only for array)
1611
-                if ($this->debug) {
1612
-                    echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND'."\n";
1613
-                }
1614
-                $len = strlen($match[1]);
1615
-                $var = $out[count($out) - 1];
1616
-                $pointer += $len;
1617
-
1618
-                $output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
1619
-
1620
-                $parsingParams[] = $output;
1621
-
1622
-                return $parsingParams;
1623
-            }
1624
-        }
1625
-
1626
-        if ($curBlock !== 'modifier' && ($parsed === 'func' || $parsed === 'var') && preg_match('#^(\|@?[a-z0-9_]+(:.*)?)+#i', $substr, $match)) {
1627
-            // parse modifier on funcs or vars
1628
-            $srcPointer = $pointer;
1629
-            if (is_array($parsingParams)) {
1630
-                $tmp = $this->replaceModifiers(array(null, null, $out[count($out) - 1][0], $match[0]), $curBlock, $pointer);
1631
-                $out[count($out) - 1][0] = $tmp;
1632
-                $out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1633
-            } else {
1634
-                $out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1635
-            }
1636
-        }
1637
-
1638
-        // func parsed, check if any func-extension applies
1639
-        if ($parsed === 'func' && preg_match('#^->[a-z0-9_]+(\s*\(.+|->[a-z_].*)?#is', $substr, $match)) {
1640
-            // parse method call or property read
1641
-            $ptr = 0;
1642
-
1643
-            if (is_array($parsingParams)) {
1644
-                $output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1645
-
1646
-                $out[count($out) - 1][0] = $output;
1647
-                $out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1648
-            } else {
1649
-                $out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1650
-            }
1651
-
1652
-            $pointer += $ptr;
1653
-        }
1654
-
1655
-        if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1656
-            return self::PHP_OPEN.'echo '.$out.';'.self::PHP_CLOSE;
1657
-        } else {
1658
-            return $out;
1659
-        }
1660
-    }
1661
-
1662
-    /**
1663
-     * parses a function call.
1664
-     *
1665
-     * @param string $in            the string within which we must parse something
1666
-     * @param int    $from          the starting offset of the parsed area
1667
-     * @param int    $to            the ending offset of the parsed area
1668
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
1669
-     * @param string $curBlock      the current parser-block being processed
1670
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
1671
-     *
1672
-     * @return string parsed values
1673
-     *
1674
-     * @throws Dwoo_Compilation_Exception
1675
-     * @throws Dwoo_Exception
1676
-     * @throws Dwoo_Security_Exception
1677
-     */
1678
-    protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1679
-    {
1680
-        $cmdstr = substr($in, $from, $to - $from);
1681
-        preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*'.$this->rdr.'|\s*;)?/i', $cmdstr, $match);
1682
-
1683
-        if (empty($match[1])) {
1684
-            throw new Dwoo_Compilation_Exception($this, 'Parse error, invalid function name : '.substr($cmdstr, 0, 15));
1685
-        }
1686
-
1687
-        $func = $match[1];
1688
-
1689
-        if (!empty($match[2])) {
1690
-            $cmdstr = $match[1];
1691
-        }
1692
-
1693
-        if ($this->debug) {
1694
-            echo 'FUNC FOUND ('.$func.')'."\n";
1695
-        }
1696
-
1697
-        $paramsep = '';
1698
-
1699
-        if (is_array($parsingParams) || $curBlock != 'root') {
1700
-            $paramspos = strpos($cmdstr, '(');
1701
-            $paramsep = ')';
1702
-        } elseif (preg_match_all('#^\s*[\\\\:a-z0-9_]+(\s*\(|\s+[^(])#i', $cmdstr, $match, PREG_OFFSET_CAPTURE)) {
1703
-            $paramspos = $match[1][0][1];
1704
-            $paramsep = substr($match[1][0][0], -1) === '(' ? ')' : '';
1705
-            if ($paramsep === ')') {
1706
-                $paramspos += strlen($match[1][0][0]) - 1;
1707
-                if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1708
-                    $paramsep = '';
1709
-                    if (strlen($match[1][0][0]) > 1) {
1710
-                        --$paramspos;
1711
-                    }
1712
-                }
1713
-            }
1714
-        } else {
1715
-            $paramspos = false;
1716
-        }
1717
-
1718
-        $state = 0;
1719
-
1720
-        if ($paramspos === false) {
1721
-            $params = array();
1722
-
1723
-            if ($curBlock !== 'root') {
1724
-                return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1725
-            }
1726
-        } else {
1727
-            if ($curBlock === 'condition') {
1728
-                // load if plugin
1729
-                $this->getPluginType('if');
1730
-
1731
-                if (Dwoo_Plugin_if::replaceKeywords(array($func), array(self::T_UNQUOTED_STRING), $this) !== array($func)) {
1732
-                    return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1733
-                }
1734
-            }
1735
-            $whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1736
-            $paramstr = substr($cmdstr, $paramspos + 1);
1737
-            if (substr($paramstr, -1, 1) === $paramsep) {
1738
-                $paramstr = substr($paramstr, 0, -1);
1739
-            }
1740
-
1741
-            if (strlen($paramstr) === 0) {
1742
-                $params = array();
1743
-                $paramstr = '';
1744
-            } else {
1745
-                $ptr = 0;
1746
-                $params = array();
1747
-                if ($func === 'empty') {
1748
-                    $params = $this->parseVar($paramstr, $ptr, strlen($paramstr), $params, 'root', $ptr);
1749
-                } else {
1750
-                    while ($ptr < strlen($paramstr)) {
1751
-                        while (true) {
1752
-                            if ($ptr >= strlen($paramstr)) {
1753
-                                break 2;
1754
-                            }
1755
-
1756
-                            if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1757
-                                if ($this->debug) {
1758
-                                    echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT '.$ptr."\n";
1759
-                                }
1760
-                                break 2;
1761
-                            } elseif ($paramstr[$ptr] === ';') {
1762
-                                ++$ptr;
1763
-                                if ($this->debug) {
1764
-                                    echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT '.$ptr."\n";
1765
-                                }
1766
-                                break 2;
1767
-                            } elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1768
-                                if ($this->debug) {
1769
-                                    echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT '.$ptr."\n";
1770
-                                }
1771
-                                break 2;
1772
-                            } elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1773
-                                if ($this->debug) {
1774
-                                    echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT '.$ptr."\n";
1775
-                                }
1776
-                                break 2;
1777
-                            }
1778
-
1779
-                            if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1780
-                                ++$ptr;
1781
-                            } else {
1782
-                                break;
1783
-                            }
1784
-                        }
1785
-
1786
-                        if ($this->debug) {
1787
-                            echo 'FUNC START PARAM PARSING WITH POINTER AT '.$ptr."\n";
1788
-                        }
1789
-
1790
-                        if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
1791
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'condition', $ptr);
1792
-                        } elseif ($func === 'array') {
1793
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'array', $ptr);
1794
-                        } else {
1795
-                            $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'function', $ptr);
1796
-                        }
1797
-
1798
-                        if ($this->debug) {
1799
-                            echo 'PARAM PARSED, POINTER AT '.$ptr.' ('.substr($paramstr, $ptr - 1, 3).')'."\n";
1800
-                        }
1801
-                    }
1802
-                }
1803
-                $paramstr = substr($paramstr, 0, $ptr);
1804
-                $state = 0;
1805
-                foreach ($params as $k => $p) {
1806
-                    if (is_array($p) && is_array($p[1])) {
1807
-                        $state |= 2;
1808
-                    } else {
1809
-                        if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m) && $func !== 'array') {
1810
-                            $params[$k] = array($m[2], array('true', 'true'));
1811
-                        } else {
1812
-                            if ($state & 2 && $func !== 'array') {
1813
-                                throw new Dwoo_Compilation_Exception($this, 'You can not use an unnamed parameter after a named one');
1814
-                            }
1815
-                            $state |= 1;
1816
-                        }
1817
-                    }
1818
-                }
1819
-            }
1820
-        }
1821
-
1822
-        if ($pointer !== null) {
1823
-            $pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1824
-            if ($this->debug) {
1825
-                echo 'FUNC ADDS '.((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)).' TO POINTER'."\n";
1826
-            }
1827
-        }
1828
-
1829
-        if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1830
-            // handle static method calls with security policy
1831
-            if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1832
-                throw new Dwoo_Security_Exception('Call to a disallowed php function : '.$func);
1833
-            }
1834
-            $pluginType = Dwoo_Core::NATIVE_PLUGIN;
1835
-        } else {
1836
-            $pluginType = $this->getPluginType($func);
1837
-        }
1838
-
1839
-        // blocks
1840
-        if ($pluginType & Dwoo_Core::BLOCK_PLUGIN) {
1841
-            if ($curBlock !== 'root' || is_array($parsingParams)) {
1842
-                throw new Dwoo_Compilation_Exception($this, 'Block plugins can not be used as other plugin\'s arguments');
1843
-            }
1844
-            if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1845
-                return $this->addCustomBlock($func, $params, $state);
1846
-            } else {
1847
-                return $this->addBlock($func, $params, $state);
1848
-            }
1849
-        } elseif ($pluginType & Dwoo_Core::SMARTY_BLOCK) {
1850
-            if ($curBlock !== 'root' || is_array($parsingParams)) {
1851
-                throw new Dwoo_Compilation_Exception($this, 'Block plugins can not be used as other plugin\'s arguments');
1852
-            }
1853
-
1854
-            if ($state & 2) {
1855
-                array_unshift($params, array('__functype', array($pluginType, $pluginType)));
1856
-                array_unshift($params, array('__funcname', array($func, $func)));
1857
-            } else {
1858
-                array_unshift($params, array($pluginType, $pluginType));
1859
-                array_unshift($params, array($func, $func));
1860
-            }
1861
-
1862
-            return $this->addBlock('smartyinterface', $params, $state);
1863
-        }
1864
-
1865
-        // funcs
1866
-        if ($pluginType & Dwoo_Core::NATIVE_PLUGIN || $pluginType & Dwoo_Core::SMARTY_FUNCTION || $pluginType & Dwoo_Core::SMARTY_BLOCK) {
1867
-            $params = $this->mapParams($params, null, $state);
1868
-        } elseif ($pluginType & Dwoo_Core::CLASS_PLUGIN) {
1869
-            if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1870
-                $params = $this->mapParams($params, array($this->customPlugins[$func]['class'], $this->customPlugins[$func]['function']), $state);
1871
-            } else {
1872
-                $params = $this->mapParams($params, array('Dwoo_Plugin_'.$func, ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'), $state);
1873
-            }
1874
-        } elseif ($pluginType & Dwoo_Core::FUNC_PLUGIN) {
1875
-            if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1876
-                $params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1877
-            } else {
1878
-                $params = $this->mapParams($params, 'Dwoo_Plugin_'.$func.(($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? '_compile' : ''), $state);
1879
-            }
1880
-        } elseif ($pluginType & Dwoo_Core::SMARTY_MODIFIER) {
1881
-            $output = 'smarty_modifier_'.$func.'('.implode(', ', $params).')';
1882
-        } elseif ($pluginType & Dwoo_Core::PROXY_PLUGIN) {
1883
-            $params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
1884
-        } elseif ($pluginType & Dwoo_Core::TEMPLATE_PLUGIN) {
1885
-            // transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
1886
-            $map = array();
1887
-            foreach ($this->templatePlugins[$func]['params'] as $param => $defValue) {
1888
-                if ($param == 'rest') {
1889
-                    $param = '*';
1890
-                }
1891
-                $hasDefault = $defValue !== null;
1892
-                if ($defValue === 'null') {
1893
-                    $defValue = null;
1894
-                } elseif ($defValue === 'false') {
1895
-                    $defValue = false;
1896
-                } elseif ($defValue === 'true') {
1897
-                    $defValue = true;
1898
-                } elseif (preg_match('#^([\'"]).*?\1$#', $defValue)) {
1899
-                    $defValue = substr($defValue, 1, -1);
1900
-                }
1901
-                $map[] = array($param, $hasDefault, $defValue);
1902
-            }
1903
-
1904
-            $params = $this->mapParams($params, null, $state, $map);
1905
-        }
1906
-
1907
-        // only keep php-syntax-safe values for non-block plugins
1908
-        $tokens = array();
1909
-        foreach ($params as $k => $p) {
1910
-            $tokens[$k] = isset($p[2]) ? $p[2] : 0;
1911
-            $params[$k] = $p[0];
1912
-        }
1913
-        if ($pluginType & Dwoo_Core::NATIVE_PLUGIN) {
1914
-            if ($func === 'do') {
1915
-                if (isset($params['*'])) {
1916
-                    $output = implode(';', $params['*']).';';
1917
-                } else {
1918
-                    $output = '';
1919
-                }
1920
-
1921
-                if (is_array($parsingParams) || $curBlock !== 'root') {
1922
-                    throw new Dwoo_Compilation_Exception($this, 'Do can not be used inside another function or block');
1923
-                } else {
1924
-                    return self::PHP_OPEN.$output.self::PHP_CLOSE;
1925
-                }
1926
-            } else {
1927
-                if (isset($params['*'])) {
1928
-                    $output = $func.'('.implode(', ', $params['*']).')';
1929
-                } else {
1930
-                    $output = $func.'()';
1931
-                }
1932
-            }
1933
-        } elseif ($pluginType & Dwoo_Core::FUNC_PLUGIN) {
1934
-            if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
1935
-                if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1936
-                    $funcCompiler = $this->customPlugins[$func]['callback'];
1937
-                } else {
1938
-                    $funcCompiler = 'Dwoo_Plugin_'.$func.'_compile';
1939
-                }
1940
-                array_unshift($params, $this);
1941
-                if ($func === 'tif') {
1942
-                    $params[] = $tokens;
1943
-                }
1944
-                $output = call_user_func_array($funcCompiler, $params);
1945
-            } else {
1946
-                if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1947
-                    $callback = $this->customPlugins[$func]['callback'];
1948
-                    if ($callback instanceof \Closure) {
1949
-                        array_unshift($params, $this->getDwoo());
1950
-                        $output = call_user_func_array($callback, $params);
1951
-                    } else {
1952
-                        array_unshift($params, '$this');
1953
-                        $params = self::implode_r($params);
1954
-                        $output = 'call_user_func(\''.$callback.'\', '.$params.')';
1955
-                    }
1956
-                } else {
1957
-                    array_unshift($params, '$this');
1958
-                    $params = self::implode_r($params);
1959
-                    $output = 'Dwoo_Plugin_'.$func.'('.$params.')';
1960
-                }
1961
-            }
1962
-        } elseif ($pluginType & Dwoo_Core::CLASS_PLUGIN) {
1963
-            if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
1964
-                if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1965
-                    $callback = $this->customPlugins[$func]['callback'];
1966
-                    if (!is_array($callback)) {
1967
-                        if (!method_exists($callback, 'compile')) {
1968
-                            throw new Dwoo_Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
1969
-                        }
1970
-                        if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
1971
-                            $funcCompiler = array($callback, 'compile');
1972
-                        } else {
1973
-                            $funcCompiler = array(new $callback(), 'compile');
1974
-                        }
1975
-                    } else {
1976
-                        $funcCompiler = $callback;
1977
-                    }
1978
-                } else {
1979
-                    $funcCompiler = array('Dwoo_Plugin_'.$func, 'compile');
1980
-                    array_unshift($params, $this);
1981
-                }
1982
-                $output = call_user_func_array($funcCompiler, $params);
1983
-            } else {
1984
-                $params = self::implode_r($params);
1985
-                if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1986
-                    $callback = $this->customPlugins[$func]['callback'];
1987
-                    if (!is_array($callback)) {
1988
-                        if (!method_exists($callback, 'process')) {
1989
-                            throw new Dwoo_Exception('Custom plugin '.$func.' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
1990
-                        }
1991
-                        if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
1992
-                            $output = 'call_user_func(array(\''.$callback.'\', \'process\'), '.$params.')';
1993
-                        } else {
1994
-                            $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback.'\'), \'process\'), '.$params.')';
1995
-                        }
1996
-                    } elseif (is_object($callback[0])) {
1997
-                        $output = 'call_user_func(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), '.$params.')';
1998
-                    } elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
1999
-                        $output = 'call_user_func(array(\''.$callback[0].'\', \''.$callback[1].'\'), '.$params.')';
2000
-                    } else {
2001
-                        $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback[0].'\'), \''.$callback[1].'\'), '.$params.')';
2002
-                    }
2003
-                    if (empty($params)) {
2004
-                        $output = substr($output, 0, -3).')';
2005
-                    }
2006
-                } else {
2007
-                    $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
2008
-                }
2009
-            }
2010
-        } elseif ($pluginType & Dwoo_Core::PROXY_PLUGIN) {
2011
-            $output = call_user_func(array($this->dwoo->getPluginProxy(), 'getCode'), $func, $params);
2012
-        } elseif ($pluginType & Dwoo_Core::SMARTY_FUNCTION) {
2013
-            if (isset($params['*'])) {
2014
-                $params = self::implode_r($params['*'], true);
2015
-            } else {
2016
-                $params = '';
2017
-            }
2018
-
2019
-            if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
2020
-                $callback = $this->customPlugins[$func]['callback'];
2021
-                if (is_array($callback)) {
2022
-                    if (is_object($callback[0])) {
2023
-                        $output = 'call_user_func_array(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array(array('.$params.'), $this))';
2024
-                    } else {
2025
-                        $output = 'call_user_func_array(array(\''.$callback[0].'\', \''.$callback[1].'\'), array(array('.$params.'), $this))';
2026
-                    }
2027
-                } else {
2028
-                    $output = $callback.'(array('.$params.'), $this)';
2029
-                }
2030
-            } else {
2031
-                $output = 'smarty_function_'.$func.'(array('.$params.'), $this)';
2032
-            }
2033
-        } elseif ($pluginType & Dwoo_Core::TEMPLATE_PLUGIN) {
2034
-            array_unshift($params, '$this');
2035
-            $params = self::implode_r($params);
2036
-            $output = 'Dwoo_Plugin_'.$func.'('.$params.')';
2037
-            $this->templatePlugins[$func]['called'] = true;
2038
-        }
2039
-
2040
-        if (is_array($parsingParams)) {
2041
-            $parsingParams[] = array($output, $output);
2042
-
2043
-            return $parsingParams;
2044
-        } elseif ($curBlock === 'namedparam') {
2045
-            return array($output, $output);
2046
-        } else {
2047
-            return $output;
2048
-        }
2049
-    }
2050
-
2051
-    /**
2052
-     * parses a string.
2053
-     *
2054
-     * @param string $in            the string within which we must parse something
2055
-     * @param int    $from          the starting offset of the parsed area
2056
-     * @param int    $to            the ending offset of the parsed area
2057
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2058
-     * @param string $curBlock      the current parser-block being processed
2059
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2060
-     *
2061
-     * @return string parsed values
2062
-     *
2063
-     * @throws Dwoo_Compilation_Exception
2064
-     */
2065
-    protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2066
-    {
2067
-        $substr = substr($in, $from, $to - $from);
2068
-        $first = $substr[0];
2069
-
2070
-        if ($this->debug) {
2071
-            echo 'STRING FOUND (in '.htmlentities(substr($in, $from, min($to - $from, 50))).(($to - $from) > 50 ? '...' : '').')'."\n";
2072
-        }
2073
-        $strend = false;
2074
-        $o = $from + 1;
2075
-        while ($strend === false) {
2076
-            $strend = strpos($in, $first, $o);
2077
-            if ($strend === false) {
2078
-                throw new Dwoo_Compilation_Exception($this, 'Unfinished string, started with '.substr($in, $from, $to - $from));
2079
-            }
2080
-            if (substr($in, $strend - 1, 1) === '\\') {
2081
-                $o = $strend + 1;
2082
-                $strend = false;
2083
-            }
2084
-        }
2085
-        if ($this->debug) {
2086
-            echo 'STRING DELIMITED: '.substr($in, $from, $strend + 1 - $from)."\n";
2087
-        }
2088
-
2089
-        $srcOutput = substr($in, $from, $strend + 1 - $from);
2090
-
2091
-        if ($pointer !== null) {
2092
-            $pointer += strlen($srcOutput);
2093
-        }
2094
-
2095
-        $output = $this->replaceStringVars($srcOutput, $first);
2096
-
2097
-        // handle modifiers
2098
-        if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2099
-            $modstr = $match[1];
2100
-
2101
-            if ($curBlock === 'root' && substr($modstr, -1) === '}') {
2102
-                $modstr = substr($modstr, 0, -1);
2103
-            }
2104
-            $modstr = str_replace('\\'.$first, $first, $modstr);
2105
-            $ptr = 0;
2106
-            $output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2107
-
2108
-            $strend += $ptr;
2109
-            if ($pointer !== null) {
2110
-                $pointer += $ptr;
2111
-            }
2112
-            $srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2113
-        }
2114
-
2115
-        if (is_array($parsingParams)) {
2116
-            $parsingParams[] = array($output, substr($srcOutput, 1, -1));
2117
-
2118
-            return $parsingParams;
2119
-        } elseif ($curBlock === 'namedparam') {
2120
-            return array($output, substr($srcOutput, 1, -1));
2121
-        } else {
2122
-            return $output;
2123
-        }
2124
-    }
2125
-
2126
-    /**
2127
-     * parses a constant.
2128
-     *
2129
-     * @param string $in            the string within which we must parse something
2130
-     * @param int    $from          the starting offset of the parsed area
2131
-     * @param int    $to            the ending offset of the parsed area
2132
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2133
-     * @param string $curBlock      the current parser-block being processed
2134
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2135
-     *
2136
-     * @return string parsed values
2137
-     *
2138
-     * @throws Dwoo_Compilation_Exception
2139
-     */
2140
-    protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2141
-    {
2142
-        $substr = substr($in, $from, $to - $from);
2143
-
2144
-        if ($this->debug) {
2145
-            echo 'CONST FOUND : '.$substr."\n";
2146
-        }
2147
-
2148
-        if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
2149
-            throw new Dwoo_Compilation_Exception($this, 'Invalid constant');
2150
-        }
2151
-
2152
-        if ($pointer !== null) {
2153
-            $pointer += strlen($m[0]);
2154
-        }
2155
-
2156
-        $output = $this->parseConstKey($m[1], $curBlock);
2157
-
2158
-        if (is_array($parsingParams)) {
2159
-            $parsingParams[] = array($output, $m[1]);
2160
-
2161
-            return $parsingParams;
2162
-        } elseif ($curBlock === 'namedparam') {
2163
-            return array($output, $m[1]);
2164
-        } else {
2165
-            return $output;
2166
-        }
2167
-    }
2168
-
2169
-    /**
2170
-     * parses a constant.
2171
-     *
2172
-     * @param string $key      the constant to parse
2173
-     * @param string $curBlock the current parser-block being processed
2174
-     *
2175
-     * @return string parsed constant
2176
-     */
2177
-    protected function parseConstKey($key, $curBlock)
2178
-    {
2179
-        if ($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === Dwoo_Security_Policy::CONST_DISALLOW) {
2180
-            return 'null';
2181
-        }
2182
-
2183
-        if ($curBlock !== 'root') {
2184
-            $output = '(defined("'.$key.'") ? '.$key.' : null)';
2185
-        } else {
2186
-            $output = $key;
2187
-        }
2188
-
2189
-        return $output;
2190
-    }
2191
-
2192
-    /**
2193
-     * parses a variable.
2194
-     *
2195
-     * @param string $in            the string within which we must parse something
2196
-     * @param int    $from          the starting offset of the parsed area
2197
-     * @param int    $to            the ending offset of the parsed area
2198
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2199
-     * @param string $curBlock      the current parser-block being processed
2200
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2201
-     *
2202
-     * @return string parsed values
2203
-     *
2204
-     * @throws Dwoo_Compilation_Exception
2205
-     */
2206
-    protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2207
-    {
2208
-        $substr = substr($in, $from, $to - $from);
2209
-
2210
-        if (preg_match('#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)'. // var key
2211
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()'). // method call
2212
-            ($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()'). // simple math expressions
2213
-            ($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())'). // modifiers
2214
-            '#i', $substr, $match)) {
2215
-            $key = substr($match[1], 1);
2216
-
2217
-            $matchedLength = strlen($match[0]);
2218
-            $hasModifiers = !empty($match[5]);
2219
-            $hasExpression = !empty($match[4]);
2220
-            $hasMethodCall = !empty($match[3]);
2221
-
2222
-            if (substr($key, -1) == '.') {
2223
-                $key = substr($key, 0, -1);
2224
-                --$matchedLength;
2225
-            }
2226
-
2227
-            if ($hasMethodCall) {
2228
-                $matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2229
-                $key = substr($match[1], 1, strrpos($match[1], '->') - 1);
2230
-                $methodCall = substr($match[1], strrpos($match[1], '->')).$match[3];
2231
-            }
2232
-
2233
-            if ($hasModifiers) {
2234
-                $matchedLength -= strlen($match[5]);
2235
-            }
2236
-
2237
-            if ($pointer !== null) {
2238
-                $pointer += $matchedLength;
2239
-            }
2240
-
2241
-            // replace useless brackets by dot accessed vars and strip enclosing quotes if present
2242
-            $key = preg_replace('#\[(["\']?)([^$%\[.>-]+)\1\]#', '.$2', $key);
2243
-
2244
-            if ($this->debug) {
2245
-                if ($hasMethodCall) {
2246
-                    echo 'METHOD CALL FOUND : $'.$key.substr($methodCall, 0, 30)."\n";
2247
-                } else {
2248
-                    echo 'VAR FOUND : $'.$key."\n";
2249
-                }
2250
-            }
2251
-
2252
-            $key = str_replace('"', '\\"', $key);
2253
-
2254
-            $cnt = substr_count($key, '$');
2255
-            if ($cnt > 0) {
2256
-                $uid = 0;
2257
-                $parsed = array($uid => '');
2258
-                $current = &$parsed;
2259
-                $curTxt = &$parsed[$uid++];
2260
-                $tree = array();
2261
-                $chars = str_split($key, 1);
2262
-                $inSplittedVar = false;
2263
-                $bracketCount = 0;
2264
-
2265
-                while (($char = array_shift($chars)) !== null) {
2266
-                    if ($char === '[') {
2267
-                        if (count($tree) > 0) {
2268
-                            ++$bracketCount;
2269
-                        } else {
2270
-                            $tree[] = &$current;
2271
-                            $current[$uid] = array($uid + 1 => '');
2272
-                            $current = &$current[$uid++];
2273
-                            $curTxt = &$current[$uid++];
2274
-                            continue;
2275
-                        }
2276
-                    } elseif ($char === ']') {
2277
-                        if ($bracketCount > 0) {
2278
-                            --$bracketCount;
2279
-                        } else {
2280
-                            $current = &$tree[count($tree) - 1];
2281
-                            array_pop($tree);
2282
-                            if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2283
-                                $current[$uid] = '';
2284
-                                $curTxt = &$current[$uid++];
2285
-                            }
2286
-                            continue;
2287
-                        }
2288
-                    } elseif ($char === '$') {
2289
-                        if (count($tree) == 0) {
2290
-                            $curTxt = &$current[$uid++];
2291
-                            $inSplittedVar = true;
2292
-                        }
2293
-                    } elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2294
-                        $curTxt = &$current[$uid++];
2295
-                        $inSplittedVar = false;
2296
-                    }
2297
-
2298
-                    $curTxt .= $char;
2299
-                }
2300
-                unset($uid, $current, $curTxt, $tree, $chars);
2301
-
2302
-                if ($this->debug) {
2303
-                    echo 'RECURSIVE VAR REPLACEMENT : '.$key."\n";
2304
-                }
2305
-
2306
-                $key = $this->flattenVarTree($parsed);
2307
-
2308
-                if ($this->debug) {
2309
-                    echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2310
-                }
2311
-
2312
-                $output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("'.$key.'")');
2313
-            } else {
2314
-                $output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2315
-            }
2316
-
2317
-            // methods
2318
-            if ($hasMethodCall) {
2319
-                $ptr = 0;
2320
-
2321
-                $output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
2322
-
2323
-                if ($pointer !== null) {
2324
-                    $pointer += $ptr;
2325
-                }
2326
-                $matchedLength += $ptr;
2327
-            }
2328
-
2329
-            if ($hasExpression) {
2330
-                // expressions
2331
-                preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[4], $expMatch);
2332
-
2333
-                foreach ($expMatch[1] as $k => $operator) {
2334
-                    if (substr($expMatch[2][$k], 0, 1) === '=') {
2335
-                        $assign = true;
2336
-                        if ($operator === '=') {
2337
-                            throw new Dwoo_Compilation_Exception($this, 'Invalid expression <em>'.$substr.'</em>, can not use "==" in expressions');
2338
-                        }
2339
-                        if ($curBlock !== 'root') {
2340
-                            throw new Dwoo_Compilation_Exception($this, 'Invalid expression <em>'.$substr.'</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2341
-                        }
2342
-                        $operator .= '=';
2343
-                        $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2344
-                    }
2345
-
2346
-                    if (substr($expMatch[2][$k], 0, 1) === '-' && strlen($expMatch[2][$k]) > 1) {
2347
-                        $operator .= '-';
2348
-                        $expMatch[2][$k] = substr($expMatch[2][$k], 1);
2349
-                    }
2350
-                    if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2351
-                        $output = '('.$output.$operator.$operator.')';
2352
-                        break;
2353
-                    } elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2354
-                        $output = '('.$output.' '.$operator.' '.$this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2355
-                    } elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2356
-                        $output = '('.$output.' '.$operator.' '.$this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2357
-                    } elseif (!empty($expMatch[2][$k])) {
2358
-                        $output = '('.$output.' '.$operator.' '.str_replace(',', '.', $expMatch[2][$k]).')';
2359
-                    } else {
2360
-                        throw new Dwoo_Compilation_Exception($this, 'Unfinished expression <em>'.$substr.'</em>, missing var or number after math operator');
2361
-                    }
2362
-                }
2363
-            }
2364
-
2365
-            if ($this->autoEscape === true && $curBlock !== 'condition') {
2366
-                $output = '(is_string($tmp='.$output.') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2367
-            }
2368
-
2369
-            // handle modifiers
2370
-            if ($curBlock !== 'modifier' && $hasModifiers) {
2371
-                $ptr = 0;
2372
-                $output = $this->replaceModifiers(array(null, null, $output, $match[5]), 'var', $ptr);
2373
-                if ($pointer !== null) {
2374
-                    $pointer += $ptr;
2375
-                }
2376
-                $matchedLength += $ptr;
2377
-            }
2378
-
2379
-            if (is_array($parsingParams)) {
2380
-                $parsingParams[] = array($output, $key);
2381
-
2382
-                return $parsingParams;
2383
-            } elseif ($curBlock === 'namedparam') {
2384
-                return array($output, $key);
2385
-            } elseif ($curBlock === 'string' || $curBlock === 'delimited_string') {
2386
-                return array($matchedLength, $output);
2387
-            } elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2388
-                return $output;
2389
-            } elseif (isset($assign)) {
2390
-                return self::PHP_OPEN.$output.';'.self::PHP_CLOSE;
2391
-            } else {
2392
-                return $output;
2393
-            }
2394
-        } else {
2395
-            if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2396
-                return array(0, '');
2397
-            } else {
2398
-                throw new Dwoo_Compilation_Exception($this, 'Invalid variable name <em>'.$substr.'</em>');
2399
-            }
2400
-        }
2401
-    }
2402
-
2403
-    /**
2404
-     * parses any number of chained method calls/property reads.
2405
-     *
2406
-     * @param string $output     the variable or whatever upon which the method are called
2407
-     * @param string $methodCall method call source, starting at "->"
2408
-     * @param string $curBlock   the current parser-block being processed
2409
-     * @param int    $pointer    a reference to a pointer that will be increased by the amount of characters parsed
2410
-     *
2411
-     * @return string parsed call(s)/read(s)
2412
-     */
2413
-    protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
2414
-    {
2415
-        $ptr = 0;
2416
-        $len = strlen($methodCall);
2417
-
2418
-        while ($ptr < $len) {
2419
-            if (strpos($methodCall, '->', $ptr) === $ptr) {
2420
-                $ptr += 2;
2421
-            }
2422
-
2423
-            if (in_array($methodCall[$ptr], array(';', ',', '/', ' ', "\t", "\r", "\n", ')', '+', '*', '%', '=', '-', '|')) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd) {
2424
-                // break char found
2425
-                break;
2426
-            }
2427
-
2428
-            if (!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
2429
-                break;
2430
-            }
2431
-
2432
-            if (empty($methMatch[2])) {
2433
-                // property
2434
-                if ($curBlock === 'root') {
2435
-                    $output .= '->'.$methMatch[1];
2436
-                } else {
2437
-                    $output = '(($tmp = '.$output.') ? $tmp->'.$methMatch[1].' : null)';
2438
-                }
2439
-                $ptr += strlen($methMatch[1]);
2440
-            } else {
2441
-                // method
2442
-                if (substr($methMatch[2], 0, 2) === '()') {
2443
-                    $parsedCall = $methMatch[1].'()';
2444
-                    $ptr += strlen($methMatch[1]) + 2;
2445
-                } else {
2446
-                    $parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2447
-                }
2448
-                if ($this->securityPolicy !== null) {
2449
-                    $argPos = strpos($parsedCall, '(');
2450
-                    $method = strtolower(substr($parsedCall, 0, $argPos));
2451
-                    $args = substr($parsedCall, $argPos);
2452
-                    if ($curBlock === 'root') {
2453
-                        $output = '$this->getSecurityPolicy()->callMethod($this, '.$output.', '.var_export($method, true).', array'.$args.')';
2454
-                    } else {
2455
-                        $output = '(($tmp = '.$output.') ? $this->getSecurityPolicy()->callMethod($this, $tmp, '.var_export($method, true).', array'.$args.') : null)';
2456
-                    }
2457
-                } else {
2458
-                    if ($curBlock === 'root') {
2459
-                        $output .= '->'.$parsedCall;
2460
-                    } else {
2461
-                        $output = '(($tmp = '.$output.') ? $tmp->'.$parsedCall.' : null)';
2462
-                    }
2463
-                }
2464
-            }
2465
-        }
2466
-
2467
-        $pointer += $ptr;
2468
-
2469
-        return $output;
2470
-    }
2471
-
2472
-    /**
2473
-     * parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save runtime processing time.
2474
-     *
2475
-     * @param string $key      the variable to parse
2476
-     * @param string $curBlock the current parser-block being processed
2477
-     *
2478
-     * @return string parsed variable
2479
-     */
2480
-    protected function parseVarKey($key, $curBlock)
2481
-    {
2482
-        if ($key === '') {
2483
-            return '$this->scope';
2484
-        }
2485
-        if (substr($key, 0, 1) === '.') {
2486
-            $key = 'dwoo'.$key;
2487
-        }
2488
-        if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2489
-            $global = strtoupper($m[1]);
2490
-            if ($global === 'COOKIES') {
2491
-                $global = 'COOKIE';
2492
-            }
2493
-            $key = '$_'.$global;
2494
-            foreach (explode('.', ltrim($m[2], '.')) as $part) {
2495
-                $key .= '['.var_export($part, true).']';
2496
-            }
2497
-            if ($curBlock === 'root') {
2498
-                $output = $key;
2499
-            } else {
2500
-                $output = '(isset('.$key.')?'.$key.':null)';
2501
-            }
2502
-        } elseif (preg_match('#dwoo\.const\.([a-z0-9_:]+)#i', $key, $m)) {
2503
-            return $this->parseConstKey($m[1], $curBlock);
2504
-        } elseif ($this->scope !== null) {
2505
-            if (strstr($key, '.') === false && strstr($key, '[') === false && strstr($key, '->') === false) {
2506
-                if ($key === 'dwoo') {
2507
-                    $output = '$this->globals';
2508
-                } elseif ($key === '_root' || $key === '__') {
2509
-                    $output = '$this->data';
2510
-                } elseif ($key === '_parent' || $key === '_') {
2511
-                    $output = '$this->readParentVar(1)';
2512
-                } elseif ($key === '_key') {
2513
-                    $output = '$tmp_key';
2514
-                } else {
2515
-                    if ($curBlock === 'root') {
2516
-                        $output = '$this->scope["'.$key.'"]';
2517
-                    } else {
2518
-                        $output = '(isset($this->scope["'.$key.'"]) ? $this->scope["'.$key.'"] : null)';
2519
-                    }
2520
-                }
2521
-            } else {
2522
-                preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+|(\\\?[\'"])[^\3]*?\3)\]?#i', $key, $m);
2523
-
2524
-                $i = $m[2][0];
2525
-                if ($i === '_parent' || $i === '_') {
2526
-                    $parentCnt = 0;
2527
-
2528
-                    while (true) {
2529
-                        ++$parentCnt;
2530
-                        array_shift($m[2]);
2531
-                        array_shift($m[1]);
2532
-                        if (current($m[2]) === '_parent') {
2533
-                            continue;
2534
-                        }
2535
-                        break;
2536
-                    }
2537
-
2538
-                    $output = '$this->readParentVar('.$parentCnt.')';
2539
-                } else {
2540
-                    if ($i === 'dwoo') {
2541
-                        $output = '$this->globals';
2542
-                        array_shift($m[2]);
2543
-                        array_shift($m[1]);
2544
-                    } elseif ($i === '_root' || $i === '__') {
2545
-                        $output = '$this->data';
2546
-                        array_shift($m[2]);
2547
-                        array_shift($m[1]);
2548
-                    } elseif ($i === '_key') {
2549
-                        $output = '$tmp_key';
2550
-                    } else {
2551
-                        $output = '$this->scope';
2552
-                    }
2553
-
2554
-                    while (count($m[1]) && $m[1][0] !== '->') {
2555
-                        $m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2556
-                        if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2557
-                            $output .= '['.$m[2][0].']';
2558
-                        } else {
2559
-                            $output .= '["'.$m[2][0].'"]';
2560
-                        }
2561
-                        array_shift($m[2]);
2562
-                        array_shift($m[1]);
2563
-                    }
2564
-
2565
-                    if ($curBlock !== 'root') {
2566
-                        $output = '(isset('.$output.') ? '.$output.':null)';
2567
-                    }
2568
-                }
2569
-
2570
-                if (count($m[2])) {
2571
-                    unset($m[0]);
2572
-                    $output = '$this->readVarInto('.str_replace("\n", '', var_export($m, true)).', '.$output.', '.($curBlock == 'root' ? 'false' : 'true').')';
2573
-                }
2574
-            }
2575
-        } else {
2576
-            preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2577
-            unset($m[0]);
2578
-            $output = '$this->readVar('.str_replace("\n", '', var_export($m, true)).')';
2579
-        }
2580
-
2581
-        return $output;
2582
-    }
2583
-
2584
-    /**
2585
-     * flattens a variable tree, this helps in parsing very complex variables such as $var.foo[$foo.bar->baz].baz,
2586
-     * it computes the contents of the brackets first and works out from there.
2587
-     *
2588
-     * @param array $tree     the variable tree parsed by he parseVar() method that must be flattened
2589
-     * @param bool  $recursed leave that to false by default, it is only for internal use
2590
-     *
2591
-     * @return string flattened tree
2592
-     */
2593
-    protected function flattenVarTree(array $tree, $recursed = false)
2594
-    {
2595
-        $out = $recursed ? '".$this->readVarInto(' : '';
2596
-        foreach ($tree as $bit) {
2597
-            if (is_array($bit)) {
2598
-                $out .= '.'.$this->flattenVarTree($bit, false);
2599
-            } else {
2600
-                $key = str_replace('"', '\\"', $bit);
2601
-
2602
-                if (substr($key, 0, 1) === '$') {
2603
-                    $out .= '".'.$this->parseVar($key, 0, strlen($key), false, 'variable').'."';
2604
-                } else {
2605
-                    $cnt = substr_count($key, '$');
2606
-
2607
-                    if ($this->debug) {
2608
-                        echo 'PARSING SUBVARS IN : '.$key."\n";
2609
-                    }
2610
-                    if ($cnt > 0) {
2611
-                        while (--$cnt >= 0) {
2612
-                            if (isset($last)) {
2613
-                                $last = strrpos($key, '$', -(strlen($key) - $last + 1));
2614
-                            } else {
2615
-                                $last = strrpos($key, '$');
2616
-                            }
2617
-                            preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*'.
2618
-                                      '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2619
-
2620
-                            $len = strlen($submatch[0]);
2621
-                            $key = substr_replace(
2622
-                                $key,
2623
-                                preg_replace_callback(
2624
-                                    '#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)'.
2625
-                                    '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i',
2626
-                                    array($this, 'replaceVarKeyHelper'), substr($key, $last, $len)
2627
-                                ),
2628
-                                $last,
2629
-                                $len
2630
-                            );
2631
-                            if ($this->debug) {
2632
-                                echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2633
-                            }
2634
-                        }
2635
-                        unset($last);
2636
-
2637
-                        $out .= $key;
2638
-                    } else {
2639
-                        $out .= $key;
2640
-                    }
2641
-                }
2642
-            }
2643
-        }
2644
-        $out .= $recursed ? ', true)."' : '';
2645
-
2646
-        return $out;
2647
-    }
2648
-
2649
-    /**
2650
-     * helper function that parses a variable.
2651
-     *
2652
-     * @param array $match the matched variable, array(1=>"string match")
2653
-     *
2654
-     * @return string parsed variable
2655
-     */
2656
-    protected function replaceVarKeyHelper($match)
2657
-    {
2658
-        return '".'.$this->parseVar($match[0], 0, strlen($match[0]), false, 'variable').'."';
2659
-    }
2660
-
2661
-    /**
2662
-     * parses various constants, operators or non-quoted strings.
2663
-     *
2664
-     * @param string $in            the string within which we must parse something
2665
-     * @param int    $from          the starting offset of the parsed area
2666
-     * @param int    $to            the ending offset of the parsed area
2667
-     * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2668
-     * @param string $curBlock      the current parser-block being processed
2669
-     * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2670
-     *
2671
-     * @return string parsed values
2672
-     *
2673
-     * @throws Exception
2674
-     */
2675
-    protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2676
-    {
2677
-        $first = $in[$from];
2678
-        $substr = substr($in, $from, $to - $from);
2679
-
2680
-        $end = strlen($substr);
2681
-
2682
-        if ($curBlock === 'condition') {
2683
-            $breakChars = array('(', ')', ' ', '||', '&&', '|', '&', '>=', '<=', '===', '==', '=', '!==', '!=', '<<', '<', '>>', '>', '^', '~', ',', '+', '-', '*', '/', '%', '!', '?', ':', $this->rd, ';');
2684
-        } elseif ($curBlock === 'modifier') {
2685
-            $breakChars = array(' ', ',', ')', ':', '|', "\r", "\n", "\t", ';', $this->rd);
2686
-        } elseif ($curBlock === 'expression') {
2687
-            $breakChars = array('/', '%', '+', '-', '*', ' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2688
-        } else {
2689
-            $breakChars = array(' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2690
-        }
2691
-
2692
-        $breaker = false;
2693
-        while (list($k, $char) = each($breakChars)) {
2694
-            $test = strpos($substr, $char);
2695
-            if ($test !== false && $test < $end) {
2696
-                $end = $test;
2697
-                $breaker = $k;
2698
-            }
2699
-        }
2700
-
2701
-        if ($curBlock === 'condition') {
2702
-            if ($end === 0 && $breaker !== false) {
2703
-                $end = strlen($breakChars[$breaker]);
2704
-            }
2705
-        }
2706
-
2707
-        if ($end !== false) {
2708
-            $substr = substr($substr, 0, $end);
2709
-        }
2710
-
2711
-        if ($pointer !== null) {
2712
-            $pointer += strlen($substr);
2713
-        }
2714
-
2715
-        $src = $substr;
2716
-        $substr = trim($substr);
2717
-
2718
-        if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2719
-            if ($this->debug) {
2720
-                echo 'BOOLEAN(FALSE) PARSED'."\n";
2721
-            }
2722
-            $substr = 'false';
2723
-            $type = self::T_BOOL;
2724
-        } elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2725
-            if ($this->debug) {
2726
-                echo 'BOOLEAN(TRUE) PARSED'."\n";
2727
-            }
2728
-            $substr = 'true';
2729
-            $type = self::T_BOOL;
2730
-        } elseif ($substr === 'null' || $substr === 'NULL') {
2731
-            if ($this->debug) {
2732
-                echo 'NULL PARSED'."\n";
2733
-            }
2734
-            $substr = 'null';
2735
-            $type = self::T_NULL;
2736
-        } elseif (is_numeric($substr)) {
2737
-            $substr = (float) $substr;
2738
-            if ((int) $substr == $substr) {
2739
-                $substr = (int) $substr;
2740
-            }
2741
-            $type = self::T_NUMERIC;
2742
-            if ($this->debug) {
2743
-                echo 'NUMBER ('.$substr.') PARSED'."\n";
2744
-            }
2745
-        } elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2746
-            if ($this->debug) {
2747
-                echo 'SIMPLE MATH PARSED . "\n"';
2748
-            }
2749
-            $type = self::T_MATH;
2750
-            $substr = '('.$substr.')';
2751
-        } elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2752
-            if ($this->debug) {
2753
-                echo 'BREAKCHAR ('.$substr.') PARSED'."\n";
2754
-            }
2755
-            $type = self::T_BREAKCHAR;
2756
-            //$substr = '"'.$substr.'"';
2757
-        } else {
2758
-            $substr = $this->replaceStringVars('\''.str_replace('\'', '\\\'', $substr).'\'', '\'', $curBlock);
2759
-            $type = self::T_UNQUOTED_STRING;
2760
-            if ($this->debug) {
2761
-                echo 'BLABBER ('.$substr.') CASTED AS STRING'."\n";
2762
-            }
2763
-        }
2764
-
2765
-        if (is_array($parsingParams)) {
2766
-            $parsingParams[] = array($substr, $src, $type);
2767
-
2768
-            return $parsingParams;
2769
-        } elseif ($curBlock === 'namedparam') {
2770
-            return array($substr, $src, $type);
2771
-        } elseif ($curBlock === 'expression') {
2772
-            return $substr;
2773
-        } else {
2774
-            throw new Exception('Something went wrong');
2775
-        }
2776
-    }
2777
-
2778
-    /**
2779
-     * replaces variables within a parsed string.
2780
-     *
2781
-     * @param string $string   the parsed string
2782
-     * @param string $first    the first character parsed in the string, which is the string delimiter (' or ")
2783
-     * @param string $curBlock the current parser-block being processed
2784
-     *
2785
-     * @return string the original string with variables replaced
2786
-     */
2787
-    protected function replaceStringVars($string, $first, $curBlock = '')
2788
-    {
2789
-        $pos = 0;
2790
-        if ($this->debug) {
2791
-            echo 'STRING VAR REPLACEMENT : '.$string."\n";
2792
-        }
2793
-        // replace vars
2794
-        while (($pos = strpos($string, '$', $pos)) !== false) {
2795
-            $prev = substr($string, $pos - 1, 1);
2796
-            if ($prev === '\\') {
2797
-                ++$pos;
2798
-                continue;
2799
-            }
2800
-
2801
-            $var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2802
-            $len = $var[0];
2803
-            $var = $this->parse(str_replace('\\'.$first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2804
-
2805
-            if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
2806
-                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos - 1, $len + 2);
2807
-            } else {
2808
-                $string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos, $len);
2809
-            }
2810
-            $pos += strlen($var[1]) + 2;
2811
-            if ($this->debug) {
2812
-                echo 'STRING VAR REPLACEMENT DONE : '.$string."\n";
2813
-            }
2814
-        }
2815
-
2816
-        // handle modifiers
2817
-        // TODO Obsolete?
2818
-        $string = preg_replace_callback('#("|\')\.(.+?)\.\1((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\4|:[^`]*))*))+)#i', array($this, 'replaceModifiers'), $string);
2819
-
2820
-        // replace escaped dollar operators by unescaped ones if required
2821
-        if ($first === "'") {
2822
-            $string = str_replace('\\$', '$', $string);
2823
-        }
2824
-
2825
-        return $string;
2826
-    }
2827
-
2828
-    /**
2829
-     * replaces the modifiers applied to a string or a variable.
2830
-     *
2831
-     * @param array  $m        the regex matches that must be array(1=>"double or single quotes enclosing a string, when applicable", 2=>"the string or var", 3=>"the modifiers matched")
2832
-     * @param string $curBlock the current parser-block being processed
2833
-     * @param null   $pointer
2834
-     *
2835
-     * @return string the input enclosed with various function calls according to the modifiers found
2836
-     *
2837
-     * @throws Dwoo_Compilation_Exception
2838
-     * @throws Dwoo_Exception
2839
-     */
2840
-    protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
2841
-    {
2842
-        if ($this->debug) {
2843
-            echo 'PARSING MODIFIERS : '.$m[3]."\n";
2844
-        }
2845
-
2846
-        if ($pointer !== null) {
2847
-            $pointer += strlen($m[3]);
2848
-        }
2849
-        // remove first pipe
2850
-        $cmdstrsrc = substr($m[3], 1);
2851
-        // remove last quote if present
2852
-        if (substr($cmdstrsrc, -1, 1) === $m[1]) {
2853
-            $cmdstrsrc = substr($cmdstrsrc, 0, -1);
2854
-            $add = $m[1];
2855
-        }
2856
-
2857
-        $output = $m[2];
2858
-
2859
-        $continue = true;
2860
-        while (strlen($cmdstrsrc) > 0 && $continue) {
2861
-            if ($cmdstrsrc[0] === '|') {
2862
-                $cmdstrsrc = substr($cmdstrsrc, 1);
2863
-                continue;
2864
-            }
2865
-            if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
2866
-                if ($this->debug) {
2867
-                    echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND'."\n";
2868
-                }
2869
-                $continue = false;
2870
-                if ($pointer !== null) {
2871
-                    $pointer -= strlen($cmdstrsrc);
2872
-                }
2873
-                break;
2874
-            }
2875
-            $cmdstr = $cmdstrsrc;
2876
-            $paramsep = ':';
2877
-            if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
2878
-                throw new Dwoo_Compilation_Exception($this, 'Invalid modifier name, started with : '.substr($cmdstr, 0, 10));
2879
-            }
2880
-            $paramspos = !empty($match[2]) ? strlen($match[1]) : false;
2881
-            $func = $match[1];
2882
-
2883
-            $state = 0;
2884
-            if ($paramspos === false) {
2885
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func));
2886
-                $params = array();
2887
-                if ($this->debug) {
2888
-                    echo 'MODIFIER ('.$func.') CALLED WITH NO PARAMS'."\n";
2889
-                }
2890
-            } else {
2891
-                $paramstr = substr($cmdstr, $paramspos + 1);
2892
-                if (substr($paramstr, -1, 1) === $paramsep) {
2893
-                    $paramstr = substr($paramstr, 0, -1);
2894
-                }
2895
-
2896
-                $ptr = 0;
2897
-                $params = array();
2898
-                while ($ptr < strlen($paramstr)) {
2899
-                    if ($this->debug) {
2900
-                        echo 'MODIFIER ('.$func.') START PARAM PARSING WITH POINTER AT '.$ptr."\n";
2901
-                    }
2902
-                    if ($this->debug) {
2903
-                        echo $paramstr.'--'.$ptr.'--'.strlen($paramstr).'--modifier'."\n";
2904
-                    }
2905
-                    $params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
2906
-                    if ($this->debug) {
2907
-                        echo 'PARAM PARSED, POINTER AT '.$ptr."\n";
2908
-                    }
2909
-
2910
-                    if ($ptr >= strlen($paramstr)) {
2911
-                        if ($this->debug) {
2912
-                            echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED'."\n";
2913
-                        }
2914
-                        break;
2915
-                    }
2916
-
2917
-                    if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
2918
-                        if ($this->debug) {
2919
-                            echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT '.$ptr."\n";
2920
-                        }
2921
-                        if ($paramstr[$ptr] !== '|') {
2922
-                            $continue = false;
2923
-                            if ($pointer !== null) {
2924
-                                $pointer -= strlen($paramstr) - $ptr;
2925
-                            }
2926
-                        }
2927
-                        ++$ptr;
2928
-                        break;
2929
-                    }
2930
-                    if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
2931
-                        ++$ptr;
2932
-                    }
2933
-                }
2934
-                $cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
2935
-                $paramstr = substr($paramstr, 0, $ptr);
2936
-                foreach ($params as $k => $p) {
2937
-                    if (is_array($p) && is_array($p[1])) {
2938
-                        $state |= 2;
2939
-                    } else {
2940
-                        if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m)) {
2941
-                            $params[$k] = array($m[2], array('true', 'true'));
2942
-                        } else {
2943
-                            if ($state & 2) {
2944
-                                throw new Dwoo_Compilation_Exception($this, 'You can not use an unnamed parameter after a named one');
2945
-                            }
2946
-                            $state |= 1;
2947
-                        }
2948
-                    }
2949
-                }
2950
-            }
2951
-
2952
-            // check if we must use array_map with this plugin or not
2953
-            $mapped = false;
2954
-            if (substr($func, 0, 1) === '@') {
2955
-                $func = substr($func, 1);
2956
-                $mapped = true;
2957
-            }
2958
-
2959
-            $pluginType = $this->getPluginType($func);
2960
-
2961
-            if ($state & 2) {
2962
-                array_unshift($params, array('value', is_array($output) ? $output : array($output, $output)));
2963
-            } else {
2964
-                array_unshift($params, is_array($output) ? $output : array($output, $output));
2965
-            }
2966
-
2967
-            if ($pluginType & Dwoo_Core::NATIVE_PLUGIN) {
2968
-                $params = $this->mapParams($params, null, $state);
2969
-
2970
-                $params = $params['*'][0];
2971
-
2972
-                $params = self::implode_r($params);
2973
-
2974
-                if ($mapped) {
2975
-                    $output = '$this->arrayMap(\''.$func.'\', array('.$params.'))';
2976
-                } else {
2977
-                    $output = $func.'('.$params.')';
2978
-                }
2979
-            } elseif ($pluginType & Dwoo_Core::PROXY_PLUGIN) {
2980
-                $params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
2981
-                foreach ($params as &$p) {
2982
-                    $p = $p[0];
2983
-                }
2984
-                $output = call_user_func(array($this->dwoo->getPluginProxy(), 'getCode'), $func, $params);
2985
-            } elseif ($pluginType & Dwoo_Core::SMARTY_MODIFIER) {
2986
-                $params = $this->mapParams($params, null, $state);
2987
-                $params = $params['*'][0];
2988
-
2989
-                $params = self::implode_r($params);
2990
-
2991
-                if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
2992
-                    $callback = $this->customPlugins[$func]['callback'];
2993
-                    if (is_array($callback)) {
2994
-                        if (is_object($callback[0])) {
2995
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
2996
-                        } else {
2997
-                            $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
2998
-                        }
2999
-                    } elseif ($mapped) {
3000
-                        $output = '$this->arrayMap(\''.$callback.'\', array('.$params.'))';
3001
-                    } else {
3002
-                        $output = $callback.'('.$params.')';
3003
-                    }
3004
-                } elseif ($mapped) {
3005
-                    $output = '$this->arrayMap(\'smarty_modifier_'.$func.'\', array('.$params.'))';
3006
-                } else {
3007
-                    $output = 'smarty_modifier_'.$func.'('.$params.')';
3008
-                }
3009
-            } else {
3010
-                if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3011
-                    $callback = $this->customPlugins[$func]['callback'];
3012
-                    $pluginName = $callback;
3013
-                } else {
3014
-                    $pluginName = 'Dwoo_Plugin_'.$func;
3015
-
3016
-                    if ($pluginType & Dwoo_Core::CLASS_PLUGIN) {
3017
-                        $callback = array($pluginName, ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3018
-                    } else {
3019
-                        $callback = $pluginName.(($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? '_compile' : '');
3020
-                    }
3021
-                }
3022
-
3023
-                $params = $this->mapParams($params, $callback, $state);
3024
-
3025
-                foreach ($params as &$p) {
3026
-                    $p = $p[0];
3027
-                }
3028
-
3029
-                if ($pluginType & Dwoo_Core::FUNC_PLUGIN) {
3030
-                    if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
3031
-                        if ($mapped) {
3032
-                            throw new Dwoo_Compilation_Exception($this, 'The @ operator can not be used on compiled plugins.');
3033
-                        }
3034
-                        if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3035
-                            $funcCompiler = $this->customPlugins[$func]['callback'];
3036
-                        } else {
3037
-                            $funcCompiler = 'Dwoo_Plugin_'.$func.'_compile';
3038
-                        }
3039
-                        array_unshift($params, $this);
3040
-                        $output = call_user_func_array($funcCompiler, $params);
3041
-                    } else {
3042
-                        array_unshift($params, '$this');
3043
-
3044
-                        $params = self::implode_r($params);
3045
-                        if ($mapped) {
3046
-                            $output = '$this->arrayMap(\''.$pluginName.'\', array('.$params.'))';
3047
-                        } else {
3048
-                            $output = $pluginName.'('.$params.')';
3049
-                        }
3050
-                    }
3051
-                } else {
3052
-                    if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
3053
-                        if ($mapped) {
3054
-                            throw new Dwoo_Compilation_Exception($this, 'The @ operator can not be used on compiled plugins.');
3055
-                        }
3056
-                        if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3057
-                            $callback = $this->customPlugins[$func]['callback'];
3058
-                            if (!is_array($callback)) {
3059
-                                if (!method_exists($callback, 'compile')) {
3060
-                                    throw new Dwoo_Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3061
-                                }
3062
-                                if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3063
-                                    $funcCompiler = array($callback, 'compile');
3064
-                                } else {
3065
-                                    $funcCompiler = array(new $callback(), 'compile');
3066
-                                }
3067
-                            } else {
3068
-                                $funcCompiler = $callback;
3069
-                            }
3070
-                        } else {
3071
-                            $funcCompiler = array('Dwoo_Plugin_'.$func, 'compile');
3072
-                            array_unshift($params, $this);
3073
-                        }
3074
-                        $output = call_user_func_array($funcCompiler, $params);
3075
-                    } else {
3076
-                        $params = self::implode_r($params);
3077
-
3078
-                        if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3079
-                            if (is_object($callback[0])) {
3080
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
3081
-                            } else {
3082
-                                $output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
3083
-                            }
3084
-                        } elseif ($mapped) {
3085
-                            $output = '$this->arrayMap(array($this->getObjectPlugin(\'Dwoo_Plugin_'.$func.'\'), \'process\'), array('.$params.'))';
3086
-                        } else {
3087
-                            $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
3088
-                        }
3089
-                    }
3090
-                }
3091
-            }
3092
-        }
3093
-
3094
-        if ($curBlock === 'namedparam') {
3095
-            return array($output, $output);
3096
-        } elseif ($curBlock === 'var' || $m[1] === null) {
3097
-            return $output;
3098
-        } elseif ($curBlock === 'string' || $curBlock === 'root') {
3099
-            return $m[1].'.'.$output.'.'.$m[1].(isset($add) ? $add : null);
3100
-        }
3101
-
3102
-        return '';
3103
-    }
3104
-
3105
-    /**
3106
-     * recursively implodes an array in a similar manner as var_export() does but with some tweaks
3107
-     * to handle pre-compiled values and the fact that we do not need to enclose everything with
3108
-     * "array" and do not require top-level keys to be displayed.
3109
-     *
3110
-     * @param array $params        the array to implode
3111
-     * @param bool  $recursiveCall if set to true, the function outputs key names for the top level
3112
-     *
3113
-     * @return string the imploded array
3114
-     */
3115
-    public static function implode_r(array $params, $recursiveCall = false)
3116
-    {
3117
-        $out = '';
3118
-        foreach ($params as $k => $p) {
3119
-            if (is_array($p)) {
3120
-                $out2 = 'array(';
3121
-                foreach ($p as $k2 => $v) {
3122
-                    $out2 .= var_export($k2, true).' => '.(is_array($v) ? 'array('.self::implode_r($v, true).')' : $v).', ';
3123
-                }
3124
-                $p = rtrim($out2, ', ').')';
3125
-            }
3126
-            if ($recursiveCall) {
3127
-                $out .= var_export($k, true).' => '.$p.', ';
3128
-            } else {
3129
-                $out .= $p.', ';
3130
-            }
3131
-        }
3132
-
3133
-        return rtrim($out, ', ');
3134
-    }
3135
-
3136
-    /**
3137
-     * returns the plugin type of a plugin and adds it to the used plugins array if required.
3138
-     *
3139
-     * @param string $name plugin name, as found in the template
3140
-     *
3141
-     * @return int type as a multi bit flag composed of the Dwoo plugin types constants
3142
-     *
3143
-     * @throws Dwoo_Exception
3144
-     * @throws Dwoo_Security_Exception
3145
-     * @throws Exception
3146
-     */
3147
-    protected function getPluginType($name)
3148
-    {
3149
-        $pluginType = -1;
3150
-
3151
-        if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) ||
3152
-            ($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3153
-            $phpFunc = true;
3154
-        } elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3155
-            throw new Dwoo_Security_Exception('Call to a disallowed php function : '.$name);
3156
-        }
3157
-
3158
-        while ($pluginType <= 0) {
3159
-            if (isset($this->templatePlugins[$name])) {
3160
-                $pluginType = Dwoo_Core::TEMPLATE_PLUGIN | Dwoo_Core::COMPILABLE_PLUGIN;
3161
-            } elseif (isset($this->customPlugins[$name])) {
3162
-                $pluginType = $this->customPlugins[$name]['type'] | Dwoo_Core::CUSTOM_PLUGIN;
3163
-            } elseif (class_exists('Dwoo_Plugin_'.$name) !== false) {
3164
-                if (is_subclass_of('Dwoo_Plugin_'.$name, 'Dwoo_Block_Plugin')) {
3165
-                    $pluginType = Dwoo_Core::BLOCK_PLUGIN;
3166
-                } else {
3167
-                    $pluginType = Dwoo_Core::CLASS_PLUGIN;
3168
-                }
3169
-                $interfaces = class_implements('Dwoo_Plugin_'.$name);
3170
-                if (in_array('Dwoo_ICompilable', $interfaces) !== false || in_array('Dwoo_ICompilable_Block', $interfaces) !== false) {
3171
-                    $pluginType |= Dwoo_Core::COMPILABLE_PLUGIN;
3172
-                }
3173
-            } elseif (function_exists('Dwoo_Plugin_'.$name) !== false) {
3174
-                $pluginType = Dwoo_Core::FUNC_PLUGIN;
3175
-            } elseif (function_exists('Dwoo_Plugin_'.$name.'_compile')) {
3176
-                $pluginType = Dwoo_Core::FUNC_PLUGIN | Dwoo_Core::COMPILABLE_PLUGIN;
3177
-            } elseif (function_exists('smarty_modifier_'.$name) !== false) {
3178
-                $pluginType = Dwoo_Core::SMARTY_MODIFIER;
3179
-            } elseif (function_exists('smarty_function_'.$name) !== false) {
3180
-                $pluginType = Dwoo_Core::SMARTY_FUNCTION;
3181
-            } elseif (function_exists('smarty_block_'.$name) !== false) {
3182
-                $pluginType = Dwoo_Core::SMARTY_BLOCK;
3183
-            } else {
3184
-                if ($pluginType === -1) {
3185
-                    try {
3186
-                        $this->dwoo->getLoader()->loadPlugin($name, isset($phpFunc) === false);
3187
-                    } catch (Exception $e) {
3188
-                        if (isset($phpFunc)) {
3189
-                            $pluginType = Dwoo_Core::NATIVE_PLUGIN;
3190
-                        } elseif (is_object($this->dwoo->getPluginProxy()) && $this->dwoo->getPluginProxy()->handles($name)) {
3191
-                            $pluginType = Dwoo_Core::PROXY_PLUGIN;
3192
-                            break;
3193
-                        } else {
3194
-                            throw $e;
3195
-                        }
3196
-                    }
3197
-                } else {
3198
-                    throw new Dwoo_Exception('Plugin "'.$name.'" could not be found');
3199
-                }
3200
-                ++$pluginType;
3201
-            }
3202
-        }
3203
-
3204
-        if (($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) === 0 && ($pluginType & Dwoo_Core::NATIVE_PLUGIN) === 0 && ($pluginType & Dwoo_Core::PROXY_PLUGIN) === 0) {
3205
-            $this->addUsedPlugin($name, $pluginType);
3206
-        }
3207
-
3208
-        return $pluginType;
3209
-    }
3210
-
3211
-    /**
3212
-     * allows a plugin to load another one at compile time, this will also mark
3213
-     * it as used by this template so it will be loaded at runtime (which can be
3214
-     * useful for compiled plugins that rely on another plugin when their compiled
3215
-     * code runs).
3216
-     *
3217
-     * @param string $name the plugin name
3218
-     */
3219
-    public function loadPlugin($name)
3220
-    {
3221
-        $this->getPluginType($name);
3222
-    }
3223
-
3224
-    /**
3225
-     * runs htmlentities over the matched <?php ?> blocks when the security policy enforces that.
3226
-     *
3227
-     * @param array $match matched php block
3228
-     *
3229
-     * @return string the htmlentities-converted string
3230
-     */
3231
-    protected function phpTagEncodingHelper($match)
3232
-    {
3233
-        return htmlspecialchars($match[0]);
3234
-    }
3235
-
3236
-    /**
3237
-     * maps the parameters received from the template onto the parameters required by the given callback.
3238
-     *
3239
-     * @param array    $params   the array of parameters
3240
-     * @param callback $callback the function or method to reflect on to find out the required parameters
3241
-     * @param int      $callType the type of call in the template, 0 = no params, 1 = php-style call, 2 = named parameters call
3242
-     * @param array    $map      the parameter map to use, if not provided it will be built from the callback
3243
-     *
3244
-     * @return array parameters sorted in the correct order with missing optional parameters filled
3245
-     *
3246
-     * @throws Dwoo_Compilation_Exception
3247
-     */
3248
-    protected function mapParams(array $params, $callback, $callType = 2, $map = null)
3249
-    {
3250
-        if (!$map) {
3251
-            $map = $this->getParamMap($callback);
3252
-        }
3253
-
3254
-        $paramlist = array();
3255
-
3256
-        // transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
3257
-        $ps = array();
3258
-        foreach ($params as $p) {
3259
-            if (is_array($p[1])) {
3260
-                $ps[$p[0]] = $p[1];
3261
-            } else {
3262
-                $ps[] = $p;
3263
-            }
3264
-        }
3265
-
3266
-        // loops over the param map and assigns values from the template or default value for unset optional params
3267
-        while (list($k, $v) = each($map)) {
3268
-            if ($v[0] === '*') {
3269
-                // "rest" array parameter, fill every remaining params in it and then break
3270
-                if (count($ps) === 0) {
3271
-                    if ($v[1] === false) {
3272
-                        throw new Dwoo_Compilation_Exception($this, 'Rest argument missing for '.str_replace(array('Dwoo_Plugin_', '_compile'), '', (is_array($callback) ? $callback[0] : $callback)));
3273
-                    } else {
3274
-                        break;
3275
-                    }
3276
-                }
3277
-                $tmp = array();
3278
-                $tmp2 = array();
3279
-                $tmp3 = array();
3280
-                foreach ($ps as $i => $p) {
3281
-                    $tmp[$i] = $p[0];
3282
-                    $tmp2[$i] = $p[1];
3283
-                    $tmp3[$i] = isset($p[2]) ? $p[2] : 0;
3284
-                    unset($ps[$i]);
3285
-                }
3286
-                $paramlist[$v[0]] = array($tmp, $tmp2, $tmp3);
3287
-                unset($tmp, $tmp2, $i, $p);
3288
-                break;
3289
-            } elseif (isset($ps[$v[0]])) {
3290
-                // parameter is defined as named param
3291
-                $paramlist[$v[0]] = $ps[$v[0]];
3292
-                unset($ps[$v[0]]);
3293
-            } elseif (isset($ps[$k])) {
3294
-                // parameter is defined as ordered param
3295
-                $paramlist[$v[0]] = $ps[$k];
3296
-                unset($ps[$k]);
3297
-            } elseif ($v[1] === false) {
3298
-                // parameter is not defined and not optional, throw error
3299
-                if (is_array($callback)) {
3300
-                    if (is_object($callback[0])) {
3301
-                        $name = get_class($callback[0]).'::'.$callback[1];
3302
-                    } else {
3303
-                        $name = $callback[0];
3304
-                    }
3305
-                } else {
3306
-                    $name = $callback;
3307
-                }
3308
-
3309
-                throw new Dwoo_Compilation_Exception($this, 'Argument '.$k.'/'.$v[0].' missing for '.str_replace(array('Dwoo_Plugin_', '_compile'), '', $name));
3310
-            } elseif ($v[2] === null) {
3311
-                // enforce lowercased null if default value is null (php outputs NULL with var export)
3312
-                $paramlist[$v[0]] = array('null', null, self::T_NULL);
3313
-            } else {
3314
-                // outputs default value with var_export
3315
-                $paramlist[$v[0]] = array(var_export($v[2], true), $v[2]);
3316
-            }
3317
-        }
3318
-
3319
-        if (count($ps)) {
3320
-            foreach ($ps as $i => $p) {
3321
-                array_push($paramlist, $p);
3322
-            }
3323
-        }
3324
-
3325
-        return $paramlist;
3326
-    }
3327
-
3328
-    /**
3329
-     * returns the parameter map of the given callback, it filters out entries typed as Dwoo and Dwoo_Compiler and turns the rest parameter into a "*".
3330
-     *
3331
-     * @param callback $callback the function/method to reflect on
3332
-     *
3333
-     * @return array processed parameter map
3334
-     */
3335
-    protected function getParamMap($callback)
3336
-    {
3337
-        if (is_null($callback)) {
3338
-            return array(array('*', true));
3339
-        }
3340
-        if (is_array($callback)) {
3341
-            $ref = new ReflectionMethod($callback[0], $callback[1]);
3342
-        } else {
3343
-            $ref = new ReflectionFunction($callback);
3344
-        }
3345
-
3346
-        $out = array();
3347
-        foreach ($ref->getParameters() as $param) {
3348
-            if (($class = $param->getClass()) !== null && ($class->name === 'Dwoo' || $class->name === 'Dwoo_Core')) {
3349
-                continue;
3350
-            }
3351
-            if (($class = $param->getClass()) !== null && $class->name === 'Dwoo_Compiler') {
3352
-                continue;
3353
-            }
3354
-            if ($param->getName() === 'rest' && $param->isArray() === true) {
3355
-                $out[] = array('*', $param->isOptional(), null);
3356
-                continue;
3357
-            }
3358
-            $out[] = array($param->getName(), $param->isOptional(), $param->isOptional() ? $param->getDefaultValue() : null);
3359
-        }
3360
-
3361
-        return $out;
3362
-    }
3363
-
3364
-    /**
3365
-     * returns a default instance of this compiler, used by default by all Dwoo templates that do not have a
3366
-     * specific compiler assigned and when you do not override the default compiler factory function.
3367
-     *
3368
-     * @see Dwoo_Core::setDefaultCompilerFactory()
3369
-     *
3370
-     * @return Dwoo_Compiler
3371
-     */
3372
-    public static function compilerFactory()
3373
-    {
3374
-        if (self::$instance === null) {
3375
-            new self();
3376
-        }
3377
-
3378
-        return self::$instance;
3379
-    }
22
+	/**
23
+	 * constant that represents a php opening tag.
24
+	 *
25
+	 * use it in case it needs to be adjusted
26
+	 *
27
+	 * @var string
28
+	 */
29
+	const PHP_OPEN = '<?php ';
30
+
31
+	/**
32
+	 * constant that represents a php closing tag.
33
+	 *
34
+	 * use it in case it needs to be adjusted
35
+	 *
36
+	 * @var string
37
+	 */
38
+	const PHP_CLOSE = '?>';
39
+
40
+	/**
41
+	 * boolean flag to enable or disable debugging output.
42
+	 *
43
+	 * @var bool
44
+	 */
45
+	public $debug = false;
46
+
47
+	/**
48
+	 * left script delimiter.
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $ld = '{';
53
+
54
+	/**
55
+	 * left script delimiter with escaped regex meta characters.
56
+	 *
57
+	 * @var string
58
+	 */
59
+	protected $ldr = '\\{';
60
+
61
+	/**
62
+	 * right script delimiter.
63
+	 *
64
+	 * @var string
65
+	 */
66
+	protected $rd = '}';
67
+
68
+	/**
69
+	 * right script delimiter with escaped regex meta characters.
70
+	 *
71
+	 * @var string
72
+	 */
73
+	protected $rdr = '\\}';
74
+
75
+	/**
76
+	 * defines whether the nested comments should be parsed as nested or not.
77
+	 *
78
+	 * defaults to false (classic block comment parsing as in all languages)
79
+	 *
80
+	 * @var bool
81
+	 */
82
+	protected $allowNestedComments = false;
83
+
84
+	/**
85
+	 * defines whether opening and closing tags can contain spaces before valid data or not.
86
+	 *
87
+	 * turn to true if you want to be sloppy with the syntax, but when set to false it allows
88
+	 * to skip javascript and css tags as long as they are in the form "{ something", which is
89
+	 * nice. default is false.
90
+	 *
91
+	 * @var bool
92
+	 */
93
+	protected $allowLooseOpenings = false;
94
+
95
+	/**
96
+	 * defines whether the compiler will automatically html-escape variables or not.
97
+	 *
98
+	 * default is false
99
+	 *
100
+	 * @var bool
101
+	 */
102
+	protected $autoEscape = false;
103
+
104
+	/**
105
+	 * security policy object.
106
+	 *
107
+	 * @var Dwoo_Security_Policy
108
+	 */
109
+	protected $securityPolicy;
110
+
111
+	/**
112
+	 * stores the custom plugins registered with this compiler.
113
+	 *
114
+	 * @var array
115
+	 */
116
+	protected $customPlugins = array();
117
+
118
+	/**
119
+	 * stores the template plugins registered with this compiler.
120
+	 *
121
+	 * @var array
122
+	 */
123
+	protected $templatePlugins = array();
124
+
125
+	/**
126
+	 * stores the pre- and post-processors callbacks.
127
+	 *
128
+	 * @var array
129
+	 */
130
+	protected $processors = array('pre' => array(), 'post' => array());
131
+
132
+	/**
133
+	 * stores a list of plugins that are used in the currently compiled
134
+	 * template, and that are not compilable. these plugins will be loaded
135
+	 * during the template's runtime if required.
136
+	 *
137
+	 * it is a 1D array formatted as key:pluginName value:pluginType
138
+	 *
139
+	 * @var array
140
+	 */
141
+	protected $usedPlugins;
142
+
143
+	/**
144
+	 * stores the template undergoing compilation.
145
+	 *
146
+	 * @var string
147
+	 */
148
+	protected $template;
149
+
150
+	/**
151
+	 * stores the current pointer position inside the template.
152
+	 *
153
+	 * @var int
154
+	 */
155
+	protected $pointer;
156
+
157
+	/**
158
+	 * stores the current line count inside the template for debugging purposes.
159
+	 *
160
+	 * @var int
161
+	 */
162
+	protected $line;
163
+
164
+	/**
165
+	 * stores the current template source while compiling it.
166
+	 *
167
+	 * @var string
168
+	 */
169
+	protected $templateSource;
170
+
171
+	/**
172
+	 * stores the data within which the scope moves.
173
+	 *
174
+	 * @var array
175
+	 */
176
+	protected $data;
177
+
178
+	/**
179
+	 * variable scope of the compiler, set to null if
180
+	 * it can not be resolved to a static string (i.e. if some
181
+	 * plugin defines a new scope based on a variable array key).
182
+	 *
183
+	 * @var mixed
184
+	 */
185
+	protected $scope;
186
+
187
+	/**
188
+	 * variable scope tree, that allows to rebuild the current
189
+	 * scope if required, i.e. when going to a parent level.
190
+	 *
191
+	 * @var array
192
+	 */
193
+	protected $scopeTree;
194
+
195
+	/**
196
+	 * block plugins stack, accessible through some methods.
197
+	 *
198
+	 * @see findBlock
199
+	 * @see getCurrentBlock
200
+	 * @see addBlock
201
+	 * @see addCustomBlock
202
+	 * @see injectBlock
203
+	 * @see removeBlock
204
+	 * @see removeTopBlock
205
+	 *
206
+	 * @var array
207
+	 */
208
+	protected $stack = array();
209
+
210
+	/**
211
+	 * current block at the top of the block plugins stack,
212
+	 * accessible through getCurrentBlock.
213
+	 *
214
+	 * @see getCurrentBlock
215
+	 *
216
+	 * @var Dwoo_Block_Plugin
217
+	 */
218
+	protected $curBlock;
219
+
220
+	/**
221
+	 * current dwoo object that uses this compiler, or null.
222
+	 *
223
+	 * @var Dwoo
224
+	 */
225
+	protected $dwoo;
226
+
227
+	/**
228
+	 * holds an instance of this class, used by getInstance when you don't
229
+	 * provide a custom compiler in order to save resources.
230
+	 *
231
+	 * @var Dwoo_Compiler
232
+	 */
233
+	protected static $instance;
234
+
235
+	/**
236
+	 * token types.
237
+	 *
238
+	 * @var int
239
+	 */
240
+	const T_UNQUOTED_STRING = 1;
241
+	const T_NUMERIC = 2;
242
+	const T_NULL = 4;
243
+	const T_BOOL = 8;
244
+	const T_MATH = 16;
245
+	const T_BREAKCHAR = 32;
246
+
247
+	/**
248
+	 * constructor.
249
+	 *
250
+	 * saves the created instance so that child templates get the same one
251
+	 */
252
+	public function __construct()
253
+	{
254
+		self::$instance = $this;
255
+	}
256
+
257
+	/**
258
+	 * sets the delimiters to use in the templates.
259
+	 *
260
+	 * delimiters can be multi-character strings but should not be one of those as they will
261
+	 * make it very hard to work with templates or might even break the compiler entirely : "\", "$", "|", ":" and finally "#" only if you intend to use config-vars with the #var# syntax.
262
+	 *
263
+	 * @param string $left  left delimiter
264
+	 * @param string $right right delimiter
265
+	 */
266
+	public function setDelimiters($left, $right)
267
+	{
268
+		$this->ld = $left;
269
+		$this->rd = $right;
270
+		$this->ldr = preg_quote($left, '/');
271
+		$this->rdr = preg_quote($right, '/');
272
+	}
273
+
274
+	/**
275
+	 * returns the left and right template delimiters.
276
+	 *
277
+	 * @return array containing the left and the right delimiters
278
+	 */
279
+	public function getDelimiters()
280
+	{
281
+		return array($this->ld, $this->rd);
282
+	}
283
+
284
+	/**
285
+	 * sets the way to handle nested comments, if set to true
286
+	 * {* foo {* some other *} comment *} will be stripped correctly.
287
+	 *
288
+	 * if false it will remove {* foo {* some other *} and leave "comment *}" alone,
289
+	 * this is the default behavior
290
+	 *
291
+	 * @param bool $allow allow nested comments or not, defaults to true (but the default internal value is false)
292
+	 */
293
+	public function setNestedCommentsHandling($allow = true)
294
+	{
295
+		$this->allowNestedComments = (bool) $allow;
296
+	}
297
+
298
+	/**
299
+	 * returns the nested comments handling setting.
300
+	 *
301
+	 * @see setNestedCommentsHandling
302
+	 *
303
+	 * @return bool true if nested comments are allowed
304
+	 */
305
+	public function getNestedCommentsHandling()
306
+	{
307
+		return $this->allowNestedComments;
308
+	}
309
+
310
+	/**
311
+	 * sets the tag openings handling strictness, if set to true, template tags can
312
+	 * contain spaces before the first function/string/variable such as { $foo} is valid.
313
+	 *
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
+	 *
330
+	 * @return bool true if loose tags are allowed
331
+	 */
332
+	public function getLooseOpeningHandling()
333
+	{
334
+		return $this->allowLooseOpenings;
335
+	}
336
+
337
+	/**
338
+	 * changes the auto escape setting.
339
+	 *
340
+	 * if enabled, the compiler will automatically html-escape variables,
341
+	 * unless they are passed through the safe function such as {$var|safe}
342
+	 * or {safe $var}
343
+	 *
344
+	 * default setting is disabled/false
345
+	 *
346
+	 * @param bool $enabled set to true to enable, false to disable
347
+	 */
348
+	public function setAutoEscape($enabled)
349
+	{
350
+		$this->autoEscape = (bool) $enabled;
351
+	}
352
+
353
+	/**
354
+	 * returns the auto escape setting.
355
+	 *
356
+	 * default setting is disabled/false
357
+	 *
358
+	 * @return bool
359
+	 */
360
+	public function getAutoEscape()
361
+	{
362
+		return $this->autoEscape;
363
+	}
364
+
365
+	/**
366
+	 * adds a preprocessor to the compiler, it will be called
367
+	 * before the template is compiled.
368
+	 *
369
+	 * @param mixed $callback either a valid callback to the preprocessor or a simple name if the autoload is set to true
370
+	 * @param bool  $autoload if set to true, the preprocessor is auto-loaded from one of the plugin directories, else you must provide a valid callback
371
+	 */
372
+	public function addPreProcessor($callback, $autoload = false)
373
+	{
374
+		if ($autoload) {
375
+			$name = str_replace('Dwoo_Processor_', '', $callback);
376
+			$class = 'Dwoo_Processor_'.$name;
377
+
378
+			if (class_exists($class)) {
379
+				$callback = array(new $class($this), 'process');
380
+			} elseif (function_exists($class)) {
381
+				$callback = $class;
382
+			} else {
383
+				$callback = array('autoload' => true, 'class' => $class, 'name' => $name);
384
+			}
385
+
386
+			$this->processors['pre'][] = $callback;
387
+		} else {
388
+			$this->processors['pre'][] = $callback;
389
+		}
390
+	}
391
+
392
+	/**
393
+	 * removes a preprocessor from the compiler.
394
+	 *
395
+	 * @param mixed $callback either a valid callback to the preprocessor or a simple name if it was autoloaded
396
+	 */
397
+	public function removePreProcessor($callback)
398
+	{
399
+		if (($index = array_search($callback, $this->processors['pre'], true)) !== false) {
400
+			unset($this->processors['pre'][$index]);
401
+		} elseif (($index = array_search('Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $callback), $this->processors['pre'], true)) !== false) {
402
+			unset($this->processors['pre'][$index]);
403
+		} else {
404
+			$class = 'Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $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 true
419
+	 * @param bool  $autoload if set to true, the postprocessor is auto-loaded from one of the plugin directories, else you must provide a valid callback
420
+	 */
421
+	public function addPostProcessor($callback, $autoload = false)
422
+	{
423
+		if ($autoload) {
424
+			$name = str_replace('Dwoo_Processor_', '', $callback);
425
+			$class = 'Dwoo_Processor_'.$name;
426
+
427
+			if (class_exists($class)) {
428
+				$callback = array(new $class($this), 'process');
429
+			} elseif (function_exists($class)) {
430
+				$callback = $class;
431
+			} else {
432
+				$callback = array('autoload' => true, 'class' => $class, 'name' => $name);
433
+			}
434
+
435
+			$this->processors['post'][] = $callback;
436
+		} else {
437
+			$this->processors['post'][] = $callback;
438
+		}
439
+	}
440
+
441
+	/**
442
+	 * removes a postprocessor from the compiler.
443
+	 *
444
+	 * @param mixed $callback either a valid callback to the postprocessor or a simple name if it was autoloaded
445
+	 */
446
+	public function removePostProcessor($callback)
447
+	{
448
+		if (($index = array_search($callback, $this->processors['post'], true)) !== false) {
449
+			unset($this->processors['post'][$index]);
450
+		} elseif (($index = array_search('Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $callback), $this->processors['post'], true)) !== false) {
451
+			unset($this->processors['post'][$index]);
452
+		} else {
453
+			$class = 'Dwoo_Processor_'.str_replace('Dwoo_Processor_', '', $callback);
454
+			foreach ($this->processors['post'] as $index => $proc) {
455
+				if (is_array($proc) && ($proc[0] instanceof $class) || (isset($proc['class']) && $proc['class'] == $class)) {
456
+					unset($this->processors['post'][$index]);
457
+					break;
458
+				}
459
+			}
460
+		}
461
+	}
462
+
463
+	/**
464
+	 * internal function to autoload processors at runtime if required.
465
+	 *
466
+	 * @param string $class the class/function name
467
+	 * @param string $name  the plugin name (without Dwoo_Plugin_ prefix)
468
+	 *
469
+	 * @return array|string
470
+	 *
471
+	 * @throws Dwoo_Exception
472
+	 */
473
+	protected function loadProcessor($class, $name)
474
+	{
475
+		if (!class_exists($class) && !function_exists($class)) {
476
+			try {
477
+				$this->dwoo->getLoader()->loadPlugin($name);
478
+			} catch (Dwoo_Exception $e) {
479
+				throw new Dwoo_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');
480
+			}
481
+		}
482
+
483
+		if (class_exists($class)) {
484
+			return array(new $class($this), 'process');
485
+		}
486
+
487
+		if (function_exists($class)) {
488
+			return $class;
489
+		}
490
+
491
+		throw new Dwoo_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"');
492
+	}
493
+
494
+	/**
495
+	 * adds an used plugin, this is reserved for use by the {template} plugin.
496
+	 *
497
+	 * this is required so that plugin loading bubbles up from loaded
498
+	 * template files to the current one
499
+	 *
500
+	 * @private
501
+	 *
502
+	 * @param string $name function name
503
+	 * @param int    $type plugin type (Dwoo_Core::*_PLUGIN)
504
+	 */
505
+	public function addUsedPlugin($name, $type)
506
+	{
507
+		$this->usedPlugins[$name] = $type;
508
+	}
509
+
510
+	/**
511
+	 * returns all the plugins this template uses.
512
+	 *
513
+	 * @private
514
+	 *
515
+	 * @return array the list of used plugins in the parsed template
516
+	 */
517
+	public function getUsedPlugins()
518
+	{
519
+		return $this->usedPlugins;
520
+	}
521
+
522
+	/**
523
+	 * adds a template plugin, this is reserved for use by the {template} plugin.
524
+	 *
525
+	 * this is required because the template functions are not declared yet
526
+	 * during compilation, so we must have a way of validating their argument
527
+	 * signature without using the reflection api
528
+	 *
529
+	 * @private
530
+	 *
531
+	 * @param string $name   function name
532
+	 * @param array  $params parameter array to help validate the function call
533
+	 * @param string $uuid   unique id of the function
534
+	 * @param string $body   function php code
535
+	 */
536
+	public function addTemplatePlugin($name, array $params, $uuid, $body = null, Dwoo_ITemplate $sourceTpl = null)
537
+	{
538
+		if (!array_key_exists($name, $this->templatePlugins) || $this->templatePlugins[$name]['uuid'] == $uuid) {
539
+			$this->templatePlugins[$name] = array('params'=> $params, 'body' => $body, 'uuid' => $uuid, 'sourceTpl' => $sourceTpl);
540
+		}
541
+	}
542
+
543
+	/**
544
+	 * returns all the parsed sub-templates.
545
+	 *
546
+	 * @private
547
+	 *
548
+	 * @return array the parsed sub-templates
549
+	 */
550
+	public function getTemplatePlugins()
551
+	{
552
+		return $this->templatePlugins;
553
+	}
554
+
555
+	/**
556
+	 * marks a template plugin as being called, which means its source must be included in the compiled template.
557
+	 *
558
+	 * @param string $name function name
559
+	 */
560
+	public function useTemplatePlugin($name)
561
+	{
562
+		$this->templatePlugins[$name]['called'] = true;
563
+	}
564
+
565
+	/**
566
+	 * adds the custom plugins loaded into Dwoo to the compiler so it can load them.
567
+	 *
568
+	 * @see Dwoo_Core::addPlugin
569
+	 *
570
+	 * @param array $customPlugins an array of custom plugins
571
+	 */
572
+	public function setCustomPlugins(array $customPlugins)
573
+	{
574
+		$this->customPlugins = $customPlugins;
575
+	}
576
+
577
+	/**
578
+	 * sets the security policy object to enforce some php security settings.
579
+	 *
580
+	 * use this if untrusted persons can modify templates,
581
+	 * set it on the Dwoo object as it will be passed onto the compiler automatically
582
+	 *
583
+	 * @param Dwoo_Security_Policy $policy the security policy object
584
+	 */
585
+	public function setSecurityPolicy(Dwoo_Security_Policy $policy = null)
586
+	{
587
+		$this->securityPolicy = $policy;
588
+	}
589
+
590
+	/**
591
+	 * returns the current security policy object or null by default.
592
+	 *
593
+	 * @return Dwoo_Security_Policy|null the security policy object if any
594
+	 */
595
+	public function getSecurityPolicy()
596
+	{
597
+		return $this->securityPolicy;
598
+	}
599
+
600
+	/**
601
+	 * sets the pointer position.
602
+	 *
603
+	 * @param int  $position the new pointer position
604
+	 * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
605
+	 */
606
+	public function setPointer($position, $isOffset = false)
607
+	{
608
+		if ($isOffset) {
609
+			$this->pointer += $position;
610
+		} else {
611
+			$this->pointer = $position;
612
+		}
613
+	}
614
+
615
+	/**
616
+	 * returns the current pointer position, only available during compilation of a template.
617
+	 *
618
+	 * @return int
619
+	 */
620
+	public function getPointer()
621
+	{
622
+		return $this->pointer;
623
+	}
624
+
625
+	/**
626
+	 * sets the line number.
627
+	 *
628
+	 * @param int  $number   the new line number
629
+	 * @param bool $isOffset if set to true, the position acts as an offset and not an absolute position
630
+	 */
631
+	public function setLine($number, $isOffset = false)
632
+	{
633
+		if ($isOffset) {
634
+			$this->line += $number;
635
+		} else {
636
+			$this->line = $number;
637
+		}
638
+	}
639
+
640
+	/**
641
+	 * returns the current line number, only available during compilation of a template.
642
+	 *
643
+	 * @return int
644
+	 */
645
+	public function getLine()
646
+	{
647
+		return $this->line;
648
+	}
649
+
650
+	/**
651
+	 * returns the dwoo object that initiated this template compilation, only available during compilation of a template.
652
+	 *
653
+	 * @return Dwoo
654
+	 */
655
+	public function getDwoo()
656
+	{
657
+		return $this->dwoo;
658
+	}
659
+
660
+	/**
661
+	 * overwrites the template that is being compiled.
662
+	 *
663
+	 * @param string $newSource   the template source that must replace the current one
664
+	 * @param bool   $fromPointer if set to true, only the source from the current pointer position is replaced
665
+	 *
666
+	 * @return string the template or partial template
667
+	 */
668
+	public function setTemplateSource($newSource, $fromPointer = false)
669
+	{
670
+		if ($fromPointer === true) {
671
+			$this->templateSource = substr($this->templateSource, 0, $this->pointer).$newSource;
672
+		} else {
673
+			$this->templateSource = $newSource;
674
+		}
675
+	}
676
+
677
+	/**
678
+	 * returns the template that is being compiled.
679
+	 *
680
+	 * @param mixed $fromPointer if set to true, only the source from the current pointer
681
+	 *                           position is returned, if a number is given it overrides the current pointer
682
+	 *
683
+	 * @return string the template or partial template
684
+	 */
685
+	public function getTemplateSource($fromPointer = false)
686
+	{
687
+		if ($fromPointer === true) {
688
+			return substr($this->templateSource, $this->pointer);
689
+		} elseif (is_numeric($fromPointer)) {
690
+			return substr($this->templateSource, $fromPointer);
691
+		} else {
692
+			return $this->templateSource;
693
+		}
694
+	}
695
+
696
+	/**
697
+	 * resets the compilation pointer, effectively restarting the compilation process.
698
+	 *
699
+	 * this is useful if a plugin modifies the template source since it might need to be recompiled
700
+	 */
701
+	public function recompile()
702
+	{
703
+		$this->setPointer(0);
704
+	}
705
+
706
+	/**
707
+	 * compiles the provided string down to php code.
708
+	 *
709
+	 * @param Dwoo_Core      $dwoo
710
+	 * @param Dwoo_ITemplate $template the template to compile
711
+	 *
712
+	 * @return string a compiled php string
713
+	 *
714
+	 * @throws Dwoo_Compilation_Exception
715
+	 */
716
+	public function compile(Dwoo_Core $dwoo, Dwoo_ITemplate $template)
717
+	{
718
+		// init vars
719
+		$tpl = $template->getSource();
720
+		$ptr = 0;
721
+		$this->dwoo = $dwoo;
722
+		$this->template = $template;
723
+		$this->templateSource = &$tpl;
724
+		$this->pointer = &$ptr;
725
+
726
+		while (true) {
727
+			// if pointer is at the beginning, reset everything, that allows a plugin to externally reset the compiler if everything must be reparsed
728
+			if ($ptr === 0) {
729
+				// resets variables
730
+				$this->usedPlugins = array();
731
+				$this->data = array();
732
+				$this->scope = &$this->data;
733
+				$this->scopeTree = array();
734
+				$this->stack = array();
735
+				$this->line = 1;
736
+				$this->templatePlugins = array();
737
+				// add top level block
738
+				$compiled = $this->addBlock('topLevelBlock', array(), 0);
739
+				$this->stack[0]['buffer'] = '';
740
+
741
+				if ($this->debug) {
742
+					echo "\n";
743
+					echo 'COMPILER INIT'."\n";
744
+				}
745
+
746
+				if ($this->debug) {
747
+					echo 'PROCESSING PREPROCESSORS ('.count($this->processors['pre']).')'."\n";
748
+				}
749
+
750
+				// runs preprocessors
751
+				foreach ($this->processors['pre'] as $preProc) {
752
+					if (is_array($preProc) && isset($preProc['autoload'])) {
753
+						$preProc = $this->loadProcessor($preProc['class'], $preProc['name']);
754
+					}
755
+					if (is_array($preProc) && $preProc[0] instanceof Dwoo_Processor) {
756
+						$tpl = call_user_func($preProc, $tpl);
757
+					} else {
758
+						$tpl = call_user_func($preProc, $this, $tpl);
759
+					}
760
+				}
761
+				unset($preProc);
762
+
763
+				// show template source if debug
764
+				if ($this->debug) {
765
+					echo '<pre>'.print_r(htmlentities($tpl), true).'</pre>'."\n";
766
+				}
767
+
768
+				// strips php tags if required by the security policy
769
+				if ($this->securityPolicy !== null) {
770
+					$search = array('{<\?php.*?\?>}');
771
+					if (ini_get('short_open_tags')) {
772
+						$search = array('{<\?.*?\?>}', '{<%.*?%>}');
773
+					}
774
+					switch ($this->securityPolicy->getPhpHandling()) {
775
+
776
+					case Dwoo_Security_Policy::PHP_ALLOW:
777
+						break;
778
+					case Dwoo_Security_Policy::PHP_ENCODE:
779
+						$tpl = preg_replace_callback($search, array($this, 'phpTagEncodingHelper'), $tpl);
780
+						break;
781
+					case Dwoo_Security_Policy::PHP_REMOVE:
782
+						$tpl = preg_replace($search, '', $tpl);
783
+
784
+					}
785
+				}
786
+			}
787
+
788
+			$pos = strpos($tpl, $this->ld, $ptr);
789
+
790
+			if ($pos === false) {
791
+				$this->push(substr($tpl, $ptr), 0);
792
+				break;
793
+			} elseif (substr($tpl, $pos - 1, 1) === '\\' && substr($tpl, $pos - 2, 1) !== '\\') {
794
+				$this->push(substr($tpl, $ptr, $pos - $ptr - 1).$this->ld);
795
+				$ptr = $pos + strlen($this->ld);
796
+			} elseif (preg_match('/^'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', substr($tpl, $pos), $litOpen)) {
797
+				if (!preg_match('/'.$this->ldr.($this->allowLooseOpenings ? '\s*' : '').'\/literal'.($this->allowLooseOpenings ? '\s*' : '').$this->rdr.'/s', $tpl, $litClose, PREG_OFFSET_CAPTURE, $pos)) {
798
+					throw new Dwoo_Compilation_Exception($this, 'The {literal} blocks must be closed explicitly with {/literal}');
799
+				}
800
+				$endpos = $litClose[0][1];
801
+				$this->push(substr($tpl, $ptr, $pos - $ptr).substr($tpl, $pos + strlen($litOpen[0]), $endpos - $pos - strlen($litOpen[0])));
802
+				$ptr = $endpos + strlen($litClose[0][0]);
803
+			} else {
804
+				if (substr($tpl, $pos - 2, 1) === '\\' && substr($tpl, $pos - 1, 1) === '\\') {
805
+					$this->push(substr($tpl, $ptr, $pos - $ptr - 1));
806
+					$ptr = $pos;
807
+				}
808
+
809
+				$this->push(substr($tpl, $ptr, $pos - $ptr));
810
+				$ptr = $pos;
811
+
812
+				$pos += strlen($this->ld);
813
+				if ($this->allowLooseOpenings) {
814
+					while (substr($tpl, $pos, 1) === ' ') {
815
+						$pos += 1;
816
+					}
817
+				} else {
818
+					if (substr($tpl, $pos, 1) === ' ' || substr($tpl, $pos, 1) === "\r" || substr($tpl, $pos, 1) === "\n" || substr($tpl, $pos, 1) === "\t") {
819
+						$ptr = $pos;
820
+						$this->push($this->ld);
821
+						continue;
822
+					}
823
+				}
824
+
825
+				// check that there is an end tag present
826
+				if (strpos($tpl, $this->rd, $pos) === false) {
827
+					throw new Dwoo_Compilation_Exception($this, 'A template tag was not closed, started with "'.substr($tpl, $ptr, 30).'"');
828
+				}
829
+
830
+				$ptr += strlen($this->ld);
831
+				$subptr = $ptr;
832
+
833
+				while (true) {
834
+					$parsed = $this->parse($tpl, $subptr, null, false, 'root', $subptr);
835
+
836
+					// reload loop if the compiler was reset
837
+					if ($ptr === 0) {
838
+						continue 2;
839
+					}
840
+
841
+					$len = $subptr - $ptr;
842
+					$this->push($parsed, substr_count(substr($tpl, $ptr, $len), "\n"));
843
+					$ptr += $len;
844
+
845
+					if ($parsed === false) {
846
+						break;
847
+					}
848
+				}
849
+			}
850
+		}
851
+
852
+		$compiled .= $this->removeBlock('topLevelBlock');
853
+
854
+		if ($this->debug) {
855
+			echo 'PROCESSING POSTPROCESSORS'."\n";
856
+		}
857
+
858
+		foreach ($this->processors['post'] as $postProc) {
859
+			if (is_array($postProc) && isset($postProc['autoload'])) {
860
+				$postProc = $this->loadProcessor($postProc['class'], $postProc['name']);
861
+			}
862
+			if (is_array($postProc) && $postProc[0] instanceof Dwoo_Processor) {
863
+				$compiled = call_user_func($postProc, $compiled);
864
+			} else {
865
+				$compiled = call_user_func($postProc, $this, $compiled);
866
+			}
867
+		}
868
+		unset($postProc);
869
+
870
+		if ($this->debug) {
871
+			echo 'COMPILATION COMPLETE : MEM USAGE : '.memory_get_usage()."\n";
872
+		}
873
+
874
+		$output = "<?php\n/* template head */\n";
875
+
876
+		// build plugin preloader
877
+		foreach ($this->usedPlugins as $plugin => $type) {
878
+			if ($type & Dwoo_Core::CUSTOM_PLUGIN) {
879
+				continue;
880
+			}
881
+
882
+			switch ($type) {
883
+
884
+			case Dwoo_Core::BLOCK_PLUGIN:
885
+			case Dwoo_Core::CLASS_PLUGIN:
886
+				$output .= "if (class_exists('Dwoo_Plugin_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
887
+				break;
888
+			case Dwoo_Core::FUNC_PLUGIN:
889
+				$output .= "if (function_exists('Dwoo_Plugin_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
890
+				break;
891
+			case Dwoo_Core::SMARTY_MODIFIER:
892
+				$output .= "if (function_exists('smarty_modifier_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
893
+				break;
894
+			case Dwoo_Core::SMARTY_FUNCTION:
895
+				$output .= "if (function_exists('smarty_function_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
896
+				break;
897
+			case Dwoo_Core::SMARTY_BLOCK:
898
+				$output .= "if (function_exists('smarty_block_$plugin')===false)\n\t\$this->getLoader()->loadPlugin('$plugin');\n";
899
+				break;
900
+			case Dwoo_Core::PROXY_PLUGIN:
901
+				$output .= $this->getDwoo()->getPluginProxy()->getPreloader($plugin);
902
+				break;
903
+			default:
904
+				throw new Dwoo_Compilation_Exception($this, 'Type error for '.$plugin.' with type'.$type);
905
+
906
+			}
907
+		}
908
+
909
+		foreach ($this->templatePlugins as $function => $attr) {
910
+			if (isset($attr['called']) && $attr['called'] === true && !isset($attr['checked'])) {
911
+				$this->resolveSubTemplateDependencies($function);
912
+			}
913
+		}
914
+		foreach ($this->templatePlugins as $function) {
915
+			if (isset($function['called']) && $function['called'] === true) {
916
+				$output .= $function['body'].PHP_EOL;
917
+			}
918
+		}
919
+
920
+		$output .= $compiled."\n?>";
921
+
922
+		$output = preg_replace('/(?<!;|\}|\*\/|\n|\{)(\s*'.preg_quote(self::PHP_CLOSE, '/').preg_quote(self::PHP_OPEN, '/').')/', ";\n", $output);
923
+		$output = str_replace(self::PHP_CLOSE.self::PHP_OPEN, "\n", $output);
924
+
925
+		// handle <?xml tag at the beginning
926
+		$output = preg_replace('#(/\* template body \*/ \?>\s*)<\?xml#is', '$1<?php echo \'<?xml\'; ?>', $output);
927
+
928
+		// add another line break after PHP closing tags that have a line break following,
929
+		// as we do not know whether it's intended, and PHP will strip it otherwise
930
+		$output = preg_replace('/(?<!"|<\?xml)\s*\?>\n/', '$0'."\n", $output);
931
+
932
+		if ($this->debug) {
933
+			echo '============================================================================================='."\n";
934
+			$lines = preg_split('{\r\n|\n|<br />}', $output);
935
+			array_shift($lines);
936
+			foreach ($lines as $i => $line) {
937
+				echo($i + 1).'. '.$line."\r\n";
938
+			}
939
+			echo '============================================================================================='."\n";
940
+		}
941
+
942
+		$this->template = $this->dwoo = null;
943
+		$tpl = null;
944
+
945
+		return $output;
946
+	}
947
+
948
+	/**
949
+	 * checks what sub-templates are used in every sub-template so that we're sure they are all compiled.
950
+	 *
951
+	 * @param string $function the sub-template name
952
+	 */
953
+	protected function resolveSubTemplateDependencies($function)
954
+	{
955
+		if ($this->debug) {
956
+			echo 'Compiler::'.__FUNCTION__."\n";
957
+		}
958
+
959
+		$body = $this->templatePlugins[$function]['body'];
960
+		foreach ($this->templatePlugins as $func => $attr) {
961
+			if ($func !== $function && !isset($attr['called']) && strpos($body, 'Dwoo_Plugin_'.$func) !== false) {
962
+				$this->templatePlugins[$func]['called'] = true;
963
+				$this->resolveSubTemplateDependencies($func);
964
+			}
965
+		}
966
+		$this->templatePlugins[$function]['checked'] = true;
967
+	}
968
+
969
+	/**
970
+	 * adds compiled content to the current block.
971
+	 *
972
+	 * @param string $content   the content to push
973
+	 * @param int    $lineCount newlines count in content, optional
974
+	 *
975
+	 * @throws Dwoo_Compilation_Exception
976
+	 */
977
+	public function push($content, $lineCount = null)
978
+	{
979
+		if ($lineCount === null) {
980
+			$lineCount = substr_count($content, "\n");
981
+		}
982
+
983
+		if ($this->curBlock['buffer'] === null && count($this->stack) > 1) {
984
+			// buffer is not initialized yet (the block has just been created)
985
+			$this->stack[count($this->stack) - 2]['buffer'] .= (string) $content;
986
+			$this->curBlock['buffer'] = '';
987
+		} else {
988
+			if (!isset($this->curBlock['buffer'])) {
989
+				throw new Dwoo_Compilation_Exception($this, 'The template has been closed too early, you probably have an extra block-closing tag somewhere');
990
+			}
991
+			// append current content to current block's buffer
992
+			$this->curBlock['buffer'] .= (string) $content;
993
+		}
994
+		$this->line += $lineCount;
995
+	}
996
+
997
+	/**
998
+	 * sets the scope.
999
+	 *
1000
+	 * set to null if the scope becomes "unstable" (i.e. too variable or unknown) so that
1001
+	 * variables are compiled in a more evaluative way than just $this->scope['key']
1002
+	 *
1003
+	 * @param mixed $scope    a string i.e. "level1.level2" or an array i.e. array("level1", "level2")
1004
+	 * @param bool  $absolute if true, the scope is set from the top level scope and not from the current scope
1005
+	 *
1006
+	 * @return array the current scope tree
1007
+	 */
1008
+	public function setScope($scope, $absolute = false)
1009
+	{
1010
+		$old = $this->scopeTree;
1011
+
1012
+		if ($scope === null) {
1013
+			unset($this->scope);
1014
+			$this->scope = null;
1015
+		}
1016
+
1017
+		if (is_array($scope) === false) {
1018
+			$scope = explode('.', $scope);
1019
+		}
1020
+
1021
+		if ($absolute === true) {
1022
+			$this->scope = &$this->data;
1023
+			$this->scopeTree = array();
1024
+		}
1025
+
1026
+		while (($bit = array_shift($scope)) !== null) {
1027
+			if ($bit === '_parent' || $bit === '_') {
1028
+				array_pop($this->scopeTree);
1029
+				reset($this->scopeTree);
1030
+				$this->scope = &$this->data;
1031
+				$cnt = count($this->scopeTree);
1032
+				for ($i = 0; $i < $cnt; ++$i) {
1033
+					$this->scope = &$this->scope[$this->scopeTree[$i]];
1034
+				}
1035
+			} elseif ($bit === '_root' || $bit === '__') {
1036
+				$this->scope = &$this->data;
1037
+				$this->scopeTree = array();
1038
+			} elseif (isset($this->scope[$bit])) {
1039
+				$this->scope = &$this->scope[$bit];
1040
+				$this->scopeTree[] = $bit;
1041
+			} else {
1042
+				$this->scope[$bit] = array();
1043
+				$this->scope = &$this->scope[$bit];
1044
+				$this->scopeTree[] = $bit;
1045
+			}
1046
+		}
1047
+
1048
+		return $old;
1049
+	}
1050
+
1051
+	/**
1052
+	 * adds a block to the top of the block stack.
1053
+	 *
1054
+	 * @param string $type      block type (name)
1055
+	 * @param array  $params    the parameters array
1056
+	 * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1057
+	 *
1058
+	 * @return string the preProcessing() method's output
1059
+	 */
1060
+	public function addBlock($type, array $params, $paramtype)
1061
+	{
1062
+		if ($this->debug) {
1063
+			echo 'Compiler::'.__FUNCTION__."\n";
1064
+		}
1065
+
1066
+		$class = 'Dwoo_Plugin_'.$type;
1067
+		if (class_exists($class) === false) {
1068
+			$this->dwoo->getLoader()->loadPlugin($type);
1069
+		}
1070
+		$params = $this->mapParams($params, array($class, 'init'), $paramtype);
1071
+
1072
+		$this->stack[] = array('type' => $type, 'params' => $params, 'custom' => false, 'class' => $class, 'buffer' => null);
1073
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1074
+
1075
+		return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1076
+	}
1077
+
1078
+	/**
1079
+	 * adds a custom block to the top of the block stack.
1080
+	 *
1081
+	 * @param string $type      block type (name)
1082
+	 * @param array  $params    the parameters array
1083
+	 * @param int    $paramtype the parameters type (see mapParams), 0, 1 or 2
1084
+	 *
1085
+	 * @return string the preProcessing() method's output
1086
+	 */
1087
+	public function addCustomBlock($type, array $params, $paramtype)
1088
+	{
1089
+		$callback = $this->customPlugins[$type]['callback'];
1090
+		if (is_array($callback)) {
1091
+			$class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
1092
+		} else {
1093
+			$class = $callback;
1094
+		}
1095
+
1096
+		$params = $this->mapParams($params, array($class, 'init'), $paramtype);
1097
+
1098
+		$this->stack[] = array('type' => $type, 'params' => $params, 'custom' => true, 'class' => $class, 'buffer' => null);
1099
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1100
+
1101
+		return call_user_func(array($class, 'preProcessing'), $this, $params, '', '', $type);
1102
+	}
1103
+
1104
+	/**
1105
+	 * injects a block at the top of the plugin stack without calling its preProcessing method.
1106
+	 *
1107
+	 * used by {else} blocks to re-add themselves after having closed everything up to their parent
1108
+	 *
1109
+	 * @param string $type   block type (name)
1110
+	 * @param array  $params parameters array
1111
+	 */
1112
+	public function injectBlock($type, array $params)
1113
+	{
1114
+		if ($this->debug) {
1115
+			echo 'Compiler::'.__FUNCTION__."\n";
1116
+		}
1117
+
1118
+		$class = 'Dwoo_Plugin_'.$type;
1119
+		if (class_exists($class) === false) {
1120
+			$this->dwoo->getLoader()->loadPlugin($type);
1121
+		}
1122
+		$this->stack[] = array('type' => $type, 'params' => $params, 'custom' => false, 'class' => $class, 'buffer' => null);
1123
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1124
+	}
1125
+
1126
+	/**
1127
+	 * removes the closest-to-top block of the given type and all other
1128
+	 * blocks encountered while going down the block stack.
1129
+	 *
1130
+	 * @param string $type block type (name)
1131
+	 *
1132
+	 * @return string the output of all postProcessing() method's return values of the closed blocks
1133
+	 *
1134
+	 * @throws Dwoo_Compilation_Exception
1135
+	 */
1136
+	public function removeBlock($type)
1137
+	{
1138
+		if ($this->debug) {
1139
+			echo 'Compiler::'.__FUNCTION__."\n";
1140
+		}
1141
+
1142
+		$output = '';
1143
+
1144
+		$pluginType = $this->getPluginType($type);
1145
+		if ($pluginType & Dwoo_Core::SMARTY_BLOCK) {
1146
+			$type = 'smartyinterface';
1147
+		}
1148
+		while (true) {
1149
+			while ($top = array_pop($this->stack)) {
1150
+				if ($top['custom']) {
1151
+					$class = $top['class'];
1152
+				} else {
1153
+					$class = 'Dwoo_Plugin_'.$top['type'];
1154
+				}
1155
+				if (count($this->stack)) {
1156
+					$this->curBlock = &$this->stack[count($this->stack) - 1];
1157
+					$this->push(call_user_func(array($class, 'postProcessing'), $this, $top['params'], '', '', $top['buffer']), 0);
1158
+				} else {
1159
+					$null = null;
1160
+					$this->curBlock = &$null;
1161
+					$output = call_user_func(array($class, 'postProcessing'), $this, $top['params'], '', '', $top['buffer']);
1162
+				}
1163
+
1164
+				if ($top['type'] === $type) {
1165
+					break 2;
1166
+				}
1167
+			}
1168
+
1169
+			throw new Dwoo_Compilation_Exception($this, 'Syntax malformation, a block of type "'.$type.'" was closed but was not opened');
1170
+			break;
1171
+		}
1172
+
1173
+		return $output;
1174
+	}
1175
+
1176
+	/**
1177
+	 * returns a reference to the first block of the given type encountered and
1178
+	 * optionally closes all blocks until it finds it
1179
+	 * this is mainly used by {else} plugins to close everything that was opened
1180
+	 * between their parent and themselves.
1181
+	 *
1182
+	 * @param string $type       the block type (name)
1183
+	 * @param bool   $closeAlong whether to close all blocks encountered while going down the block stack or not
1184
+	 *
1185
+	 * @return mixed &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1186
+	 *               'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1187
+	 *
1188
+	 * @throws Dwoo_Compilation_Exception
1189
+	 */
1190
+	public function &findBlock($type, $closeAlong = false)
1191
+	{
1192
+		if ($closeAlong === true) {
1193
+			while ($b = end($this->stack)) {
1194
+				if ($b['type'] === $type) {
1195
+					return $this->stack[key($this->stack)];
1196
+				}
1197
+				$this->push($this->removeTopBlock(), 0);
1198
+			}
1199
+		} else {
1200
+			end($this->stack);
1201
+			while ($b = current($this->stack)) {
1202
+				if ($b['type'] === $type) {
1203
+					return $this->stack[key($this->stack)];
1204
+				}
1205
+				prev($this->stack);
1206
+			}
1207
+		}
1208
+
1209
+		throw new Dwoo_Compilation_Exception($this, 'A parent block of type "'.$type.'" is required and can not be found');
1210
+	}
1211
+
1212
+	/**
1213
+	 * returns a reference to the current block array.
1214
+	 *
1215
+	 * @return &array the array is as such: array('type'=>pluginName, 'params'=>parameter array,
1216
+	 *                'custom'=>bool defining whether it's a custom plugin or not, for internal use)
1217
+	 */
1218
+	public function &getCurrentBlock()
1219
+	{
1220
+		return $this->curBlock;
1221
+	}
1222
+
1223
+	/**
1224
+	 * removes the block at the top of the stack and calls its postProcessing() method.
1225
+	 *
1226
+	 * @return string the postProcessing() method's output
1227
+	 *
1228
+	 * @throws Dwoo_Compilation_Exception
1229
+	 */
1230
+	public function removeTopBlock()
1231
+	{
1232
+		if ($this->debug) {
1233
+			echo 'Compiler::'.__FUNCTION__."\n";
1234
+		}
1235
+
1236
+		$o = array_pop($this->stack);
1237
+		if ($o === null) {
1238
+			throw new Dwoo_Compilation_Exception($this, 'Syntax malformation, a block of unknown type was closed but was not opened.');
1239
+		}
1240
+		if ($o['custom']) {
1241
+			$class = $o['class'];
1242
+		} else {
1243
+			$class = 'Dwoo_Plugin_'.$o['type'];
1244
+		}
1245
+
1246
+		$this->curBlock = &$this->stack[count($this->stack) - 1];
1247
+
1248
+		return call_user_func(array($class, 'postProcessing'), $this, $o['params'], '', '', $o['buffer']);
1249
+	}
1250
+
1251
+	/**
1252
+	 * returns the compiled parameters (for example a variable's compiled parameter will be "$this->scope['key']") out of the given parameter array.
1253
+	 *
1254
+	 * @param array $params parameter array
1255
+	 *
1256
+	 * @return array filtered parameters
1257
+	 */
1258
+	public function getCompiledParams(array $params)
1259
+	{
1260
+		foreach ($params as $k => $p) {
1261
+			if (is_array($p)) {
1262
+				$params[$k] = $p[0];
1263
+			}
1264
+		}
1265
+
1266
+		return $params;
1267
+	}
1268
+
1269
+	/**
1270
+	 * returns the real parameters (for example a variable's real parameter will be its key, etc) out of the given parameter array.
1271
+	 *
1272
+	 * @param array $params parameter array
1273
+	 *
1274
+	 * @return array filtered parameters
1275
+	 */
1276
+	public function getRealParams(array $params)
1277
+	{
1278
+		foreach ($params as $k => $p) {
1279
+			if (is_array($p)) {
1280
+				$params[$k] = $p[1];
1281
+			}
1282
+		}
1283
+
1284
+		return $params;
1285
+	}
1286
+
1287
+	/**
1288
+	 * returns the token of each parameter out of the given parameter array.
1289
+	 *
1290
+	 * @param array $params parameter array
1291
+	 *
1292
+	 * @return array tokens
1293
+	 */
1294
+	public function getParamTokens(array $params)
1295
+	{
1296
+		foreach ($params as $k => $p) {
1297
+			if (is_array($p)) {
1298
+				$params[$k] = isset($p[2]) ? $p[2] : 0;
1299
+			}
1300
+		}
1301
+
1302
+		return $params;
1303
+	}
1304
+
1305
+	/**
1306
+	 * entry point of the parser, it redirects calls to other parse* functions.
1307
+	 *
1308
+	 * @param string $in            the string within which we must parse something
1309
+	 * @param int    $from          the starting offset of the parsed area
1310
+	 * @param int    $to            the ending offset of the parsed area
1311
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
1312
+	 * @param string $curBlock      the current parser-block being processed
1313
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
1314
+	 *
1315
+	 * @return string parsed values
1316
+	 *
1317
+	 * @throws Dwoo_Compilation_Exception
1318
+	 */
1319
+	protected function parse($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1320
+	{
1321
+		if ($this->debug) {
1322
+			echo 'Compiler::'.__FUNCTION__."\n";
1323
+		}
1324
+
1325
+		if ($to === null) {
1326
+			$to = strlen($in);
1327
+		}
1328
+		$first = substr($in, $from, 1);
1329
+
1330
+		if ($first === false) {
1331
+			throw new Dwoo_Compilation_Exception($this, 'Unexpected EOF, a template tag was not closed');
1332
+		}
1333
+
1334
+		while ($first === ' ' || $first === "\n" || $first === "\t" || $first === "\r") {
1335
+			if ($curBlock === 'root' && substr($in, $from, strlen($this->rd)) === $this->rd) {
1336
+				// end template tag
1337
+				$pointer += strlen($this->rd);
1338
+				if ($this->debug) {
1339
+					echo 'TEMPLATE PARSING ENDED'."\n";
1340
+				}
1341
+
1342
+				return false;
1343
+			}
1344
+			++$from;
1345
+			if ($pointer !== null) {
1346
+				++$pointer;
1347
+			}
1348
+			if ($from >= $to) {
1349
+				if (is_array($parsingParams)) {
1350
+					return $parsingParams;
1351
+				} else {
1352
+					return '';
1353
+				}
1354
+			}
1355
+			$first = $in[$from];
1356
+		}
1357
+
1358
+		$substr = substr($in, $from, $to - $from);
1359
+
1360
+		if ($this->debug) {
1361
+			echo 'PARSE CALL : PARSING "<b>'.htmlentities(substr($in, $from, min($to - $from, 50))).(($to - $from) > 50 ? '...' : '').'</b>" @ '.$from.':'.$to.' in '.$curBlock.' : pointer='.$pointer."\n";
1362
+		}
1363
+		$parsed = '';
1364
+
1365
+		if ($curBlock === 'root' && $first === '*') {
1366
+			$src = $this->getTemplateSource();
1367
+			$startpos = $this->getPointer() - strlen($this->ld);
1368
+			if (substr($src, $startpos, strlen($this->ld)) === $this->ld) {
1369
+				if ($startpos > 0) {
1370
+					do {
1371
+						$char = substr($src, --$startpos, 1);
1372
+						if ($char == "\n") {
1373
+							++$startpos;
1374
+							$whitespaceStart = true;
1375
+							break;
1376
+						}
1377
+					} while ($startpos > 0 && ($char == ' ' || $char == "\t"));
1378
+				}
1379
+
1380
+				if (!isset($whitespaceStart)) {
1381
+					$startpos = $this->getPointer();
1382
+				} else {
1383
+					$pointer -= $this->getPointer() - $startpos;
1384
+				}
1385
+
1386
+				if ($this->allowNestedComments && strpos($src, $this->ld.'*', $this->getPointer()) !== false) {
1387
+					$comOpen = $this->ld.'*';
1388
+					$comClose = '*'.$this->rd;
1389
+					$level = 1;
1390
+					$ptr = $this->getPointer();
1391
+
1392
+					while ($level > 0 && $ptr < strlen($src)) {
1393
+						$open = strpos($src, $comOpen, $ptr);
1394
+						$close = strpos($src, $comClose, $ptr);
1395
+
1396
+						if ($open !== false && $close !== false) {
1397
+							if ($open < $close) {
1398
+								$ptr = $open + strlen($comOpen);
1399
+								++$level;
1400
+							} else {
1401
+								$ptr = $close + strlen($comClose);
1402
+								--$level;
1403
+							}
1404
+						} elseif ($open !== false) {
1405
+							$ptr = $open + strlen($comOpen);
1406
+							++$level;
1407
+						} elseif ($close !== false) {
1408
+							$ptr = $close + strlen($comClose);
1409
+							--$level;
1410
+						} else {
1411
+							$ptr = strlen($src);
1412
+						}
1413
+					}
1414
+					$endpos = $ptr - strlen('*'.$this->rd);
1415
+				} else {
1416
+					$endpos = strpos($src, '*'.$this->rd, $startpos);
1417
+					if ($endpos == false) {
1418
+						throw new Dwoo_Compilation_Exception($this, 'Un-ended comment');
1419
+					}
1420
+				}
1421
+				$pointer += $endpos - $startpos + strlen('*'.$this->rd);
1422
+				if (isset($whitespaceStart) && preg_match('#^[\t ]*\r?\n#', substr($src, $endpos + strlen('*'.$this->rd)), $m)) {
1423
+					$pointer += strlen($m[0]);
1424
+					$this->curBlock['buffer'] = substr($this->curBlock['buffer'], 0, strlen($this->curBlock['buffer']) - ($this->getPointer() - $startpos - strlen($this->ld)));
1425
+				}
1426
+
1427
+				return false;
1428
+			}
1429
+		}
1430
+
1431
+		if ($first === '$') {
1432
+			// var
1433
+			$out = $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
1434
+			$parsed = 'var';
1435
+		} elseif ($first === '%' && preg_match('#^%[a-z_]#i', $substr)) {
1436
+			// const
1437
+			$out = $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
1438
+		} elseif (($first === '"' || $first === "'") && !(is_array($parsingParams) && preg_match('#^([\'"])[a-z0-9_]+\1\s*=>?(?:\s+|[^=])#i', $substr))) {
1439
+			// string
1440
+			$out = $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
1441
+		} 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)) {
1442
+			// func
1443
+			$out = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
1444
+			$parsed = 'func';
1445
+		} elseif ($first === ';') {
1446
+			// instruction end
1447
+			if ($this->debug) {
1448
+				echo 'END OF INSTRUCTION'."\n";
1449
+			}
1450
+			if ($pointer !== null) {
1451
+				++$pointer;
1452
+			}
1453
+
1454
+			return $this->parse($in, $from + 1, $to, false, 'root', $pointer);
1455
+		} elseif ($curBlock === 'root' && preg_match('#^/([a-z_][a-z0-9_]*)?#i', $substr, $match)) {
1456
+			// close block
1457
+			if (!empty($match[1]) && $match[1] == 'else') {
1458
+				throw new Dwoo_Compilation_Exception($this, 'Else blocks must not be closed explicitly, they are automatically closed when their parent block is closed');
1459
+			}
1460
+			if (!empty($match[1]) && $match[1] == 'elseif') {
1461
+				throw new Dwoo_Compilation_Exception($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');
1462
+			}
1463
+			if ($pointer !== null) {
1464
+				$pointer += strlen($match[0]);
1465
+			}
1466
+			if (empty($match[1])) {
1467
+				if ($this->curBlock['type'] == 'else' || $this->curBlock['type'] == 'elseif') {
1468
+					$pointer -= strlen($match[0]);
1469
+				}
1470
+				if ($this->debug) {
1471
+					echo 'TOP BLOCK CLOSED'."\n";
1472
+				}
1473
+
1474
+				return $this->removeTopBlock();
1475
+			} else {
1476
+				if ($this->debug) {
1477
+					echo 'BLOCK OF TYPE '.$match[1].' CLOSED'."\n";
1478
+				}
1479
+
1480
+				return $this->removeBlock($match[1]);
1481
+			}
1482
+		} elseif ($curBlock === 'root' && substr($substr, 0, strlen($this->rd)) === $this->rd) {
1483
+			// end template tag
1484
+			if ($this->debug) {
1485
+				echo 'TAG PARSING ENDED'."\n";
1486
+			}
1487
+			$pointer += strlen($this->rd);
1488
+
1489
+			return false;
1490
+		} elseif (is_array($parsingParams) && preg_match('#^(([\'"]?)[a-z0-9_]+\2\s*='.($curBlock === 'array' ? '>?' : '').')(?:\s+|[^=]).*#i', $substr, $match)) {
1491
+			// named parameter
1492
+			if ($this->debug) {
1493
+				echo 'NAMED PARAM FOUND'."\n";
1494
+			}
1495
+			$len = strlen($match[1]);
1496
+			while (substr($in, $from + $len, 1) === ' ') {
1497
+				++$len;
1498
+			}
1499
+			if ($pointer !== null) {
1500
+				$pointer += $len;
1501
+			}
1502
+
1503
+			$output = array(trim($match[1], " \t\r\n=>'\""), $this->parse($in, $from + $len, $to, false, 'namedparam', $pointer));
1504
+
1505
+			$parsingParams[] = $output;
1506
+
1507
+			return $parsingParams;
1508
+		} elseif (preg_match('#^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*::\$[a-z0-9_]+)#i', $substr, $match)) {
1509
+			// static member access
1510
+			$parsed = 'var';
1511
+			if (is_array($parsingParams)) {
1512
+				$parsingParams[] = array($match[1], $match[1]);
1513
+				$out = $parsingParams;
1514
+			} else {
1515
+				$out = $match[1];
1516
+			}
1517
+			$pointer += strlen($match[1]);
1518
+		} elseif ($substr !== '' && (is_array($parsingParams) || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'expression')) {
1519
+			// unquoted string, bool or number
1520
+			$out = $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1521
+		} else {
1522
+			// parse error
1523
+			throw new Dwoo_Compilation_Exception($this, 'Parse error in "'.substr($in, $from, $to - $from).'"');
1524
+		}
1525
+
1526
+		if (empty($out)) {
1527
+			return '';
1528
+		}
1529
+
1530
+		$substr = substr($in, $pointer, $to - $pointer);
1531
+
1532
+		// var parsed, check if any var-extension applies
1533
+		if ($parsed === 'var') {
1534
+			if (preg_match('#^\s*([/%+*-])\s*([a-z0-9]|\$)#i', $substr, $match)) {
1535
+				if ($this->debug) {
1536
+					echo 'PARSING POST-VAR EXPRESSION '.$substr."\n";
1537
+				}
1538
+				// parse expressions
1539
+				$pointer += strlen($match[0]) - 1;
1540
+				if (is_array($parsingParams)) {
1541
+					if ($match[2] == '$') {
1542
+						$expr = $this->parseVar($in, $pointer, $to, array(), $curBlock, $pointer);
1543
+					} else {
1544
+						$expr = $this->parse($in, $pointer, $to, array(), 'expression', $pointer);
1545
+					}
1546
+					$out[count($out) - 1][0] .= $match[1].$expr[0][0];
1547
+					$out[count($out) - 1][1] .= $match[1].$expr[0][1];
1548
+				} else {
1549
+					if ($match[2] == '$') {
1550
+						$expr = $this->parseVar($in, $pointer, $to, false, $curBlock, $pointer);
1551
+					} else {
1552
+						$expr = $this->parse($in, $pointer, $to, false, 'expression', $pointer);
1553
+					}
1554
+					if (is_array($out) && is_array($expr)) {
1555
+						$out[0] .= $match[1].$expr[0];
1556
+						$out[1] .= $match[1].$expr[1];
1557
+					} elseif (is_array($out)) {
1558
+						$out[0] .= $match[1].$expr;
1559
+						$out[1] .= $match[1].$expr;
1560
+					} elseif (is_array($expr)) {
1561
+						$out .= $match[1].$expr[0];
1562
+					} else {
1563
+						$out .= $match[1].$expr;
1564
+					}
1565
+				}
1566
+			} elseif ($curBlock === 'root' && preg_match('#^(\s*(?:[+/*%-.]=|=|\+\+|--)\s*)(.*)#s', $substr, $match)) {
1567
+				if ($this->debug) {
1568
+					echo 'PARSING POST-VAR ASSIGNMENT '.$substr."\n";
1569
+				}
1570
+				// parse assignment
1571
+				$value = $match[2];
1572
+				$operator = trim($match[1]);
1573
+				if (substr($value, 0, 1) == '=') {
1574
+					throw new Dwoo_Compilation_Exception($this, 'Unexpected "=" in <em>'.$substr.'</em>');
1575
+				}
1576
+
1577
+				if ($pointer !== null) {
1578
+					$pointer += strlen($match[1]);
1579
+				}
1580
+
1581
+				if ($operator !== '++' && $operator !== '--') {
1582
+					$parts = array();
1583
+					$ptr = 0;
1584
+					$parts = $this->parse($value, 0, strlen($value), $parts, 'condition', $ptr);
1585
+					$pointer += $ptr;
1586
+
1587
+					// load if plugin
1588
+					try {
1589
+						$this->getPluginType('if');
1590
+					} catch (Dwoo_Exception $e) {
1591
+						throw new Dwoo_Compilation_Exception($this, 'Assignments require the "if" plugin to be accessible');
1592
+					}
1593
+
1594
+					$parts = $this->mapParams($parts, array('Dwoo_Plugin_if', 'init'), 1);
1595
+					$tokens = $this->getParamTokens($parts);
1596
+					$parts = $this->getCompiledParams($parts);
1597
+
1598
+					$value = Dwoo_Plugin_if::replaceKeywords($parts['*'], $tokens['*'], $this);
1599
+					$echo = '';
1600
+				} else {
1601
+					$value = array();
1602
+					$echo = 'echo ';
1603
+				}
1604
+
1605
+				if ($this->autoEscape) {
1606
+					$out = preg_replace('#\(is_string\(\$tmp=(.+?)\) \? htmlspecialchars\(\$tmp, ENT_QUOTES, \$this->charset\) : \$tmp\)#', '$1', $out);
1607
+				}
1608
+				$out = self::PHP_OPEN.$echo.$out.$operator.implode(' ', $value).self::PHP_CLOSE;
1609
+			} elseif ($curBlock === 'array' && is_array($parsingParams) && preg_match('#^(\s*=>?\s*)#', $substr, $match)) {
1610
+				// parse namedparam with var as name (only for array)
1611
+				if ($this->debug) {
1612
+					echo 'VARIABLE NAMED PARAM (FOR ARRAY) FOUND'."\n";
1613
+				}
1614
+				$len = strlen($match[1]);
1615
+				$var = $out[count($out) - 1];
1616
+				$pointer += $len;
1617
+
1618
+				$output = array($var[0], $this->parse($substr, $len, null, false, 'namedparam', $pointer));
1619
+
1620
+				$parsingParams[] = $output;
1621
+
1622
+				return $parsingParams;
1623
+			}
1624
+		}
1625
+
1626
+		if ($curBlock !== 'modifier' && ($parsed === 'func' || $parsed === 'var') && preg_match('#^(\|@?[a-z0-9_]+(:.*)?)+#i', $substr, $match)) {
1627
+			// parse modifier on funcs or vars
1628
+			$srcPointer = $pointer;
1629
+			if (is_array($parsingParams)) {
1630
+				$tmp = $this->replaceModifiers(array(null, null, $out[count($out) - 1][0], $match[0]), $curBlock, $pointer);
1631
+				$out[count($out) - 1][0] = $tmp;
1632
+				$out[count($out) - 1][1] .= substr($substr, $srcPointer, $srcPointer - $pointer);
1633
+			} else {
1634
+				$out = $this->replaceModifiers(array(null, null, $out, $match[0]), $curBlock, $pointer);
1635
+			}
1636
+		}
1637
+
1638
+		// func parsed, check if any func-extension applies
1639
+		if ($parsed === 'func' && preg_match('#^->[a-z0-9_]+(\s*\(.+|->[a-z_].*)?#is', $substr, $match)) {
1640
+			// parse method call or property read
1641
+			$ptr = 0;
1642
+
1643
+			if (is_array($parsingParams)) {
1644
+				$output = $this->parseMethodCall($out[count($out) - 1][1], $match[0], $curBlock, $ptr);
1645
+
1646
+				$out[count($out) - 1][0] = $output;
1647
+				$out[count($out) - 1][1] .= substr($match[0], 0, $ptr);
1648
+			} else {
1649
+				$out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
1650
+			}
1651
+
1652
+			$pointer += $ptr;
1653
+		}
1654
+
1655
+		if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
1656
+			return self::PHP_OPEN.'echo '.$out.';'.self::PHP_CLOSE;
1657
+		} else {
1658
+			return $out;
1659
+		}
1660
+	}
1661
+
1662
+	/**
1663
+	 * parses a function call.
1664
+	 *
1665
+	 * @param string $in            the string within which we must parse something
1666
+	 * @param int    $from          the starting offset of the parsed area
1667
+	 * @param int    $to            the ending offset of the parsed area
1668
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
1669
+	 * @param string $curBlock      the current parser-block being processed
1670
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
1671
+	 *
1672
+	 * @return string parsed values
1673
+	 *
1674
+	 * @throws Dwoo_Compilation_Exception
1675
+	 * @throws Dwoo_Exception
1676
+	 * @throws Dwoo_Security_Exception
1677
+	 */
1678
+	protected function parseFunction($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
1679
+	{
1680
+		$cmdstr = substr($in, $from, $to - $from);
1681
+		preg_match('/^(\\\\?[a-z_](?:\\\\?[a-z0-9_]+)*(?:::[a-z_][a-z0-9_]*)?)(\s*'.$this->rdr.'|\s*;)?/i', $cmdstr, $match);
1682
+
1683
+		if (empty($match[1])) {
1684
+			throw new Dwoo_Compilation_Exception($this, 'Parse error, invalid function name : '.substr($cmdstr, 0, 15));
1685
+		}
1686
+
1687
+		$func = $match[1];
1688
+
1689
+		if (!empty($match[2])) {
1690
+			$cmdstr = $match[1];
1691
+		}
1692
+
1693
+		if ($this->debug) {
1694
+			echo 'FUNC FOUND ('.$func.')'."\n";
1695
+		}
1696
+
1697
+		$paramsep = '';
1698
+
1699
+		if (is_array($parsingParams) || $curBlock != 'root') {
1700
+			$paramspos = strpos($cmdstr, '(');
1701
+			$paramsep = ')';
1702
+		} elseif (preg_match_all('#^\s*[\\\\:a-z0-9_]+(\s*\(|\s+[^(])#i', $cmdstr, $match, PREG_OFFSET_CAPTURE)) {
1703
+			$paramspos = $match[1][0][1];
1704
+			$paramsep = substr($match[1][0][0], -1) === '(' ? ')' : '';
1705
+			if ($paramsep === ')') {
1706
+				$paramspos += strlen($match[1][0][0]) - 1;
1707
+				if (substr($cmdstr, 0, 2) === 'if' || substr($cmdstr, 0, 6) === 'elseif') {
1708
+					$paramsep = '';
1709
+					if (strlen($match[1][0][0]) > 1) {
1710
+						--$paramspos;
1711
+					}
1712
+				}
1713
+			}
1714
+		} else {
1715
+			$paramspos = false;
1716
+		}
1717
+
1718
+		$state = 0;
1719
+
1720
+		if ($paramspos === false) {
1721
+			$params = array();
1722
+
1723
+			if ($curBlock !== 'root') {
1724
+				return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1725
+			}
1726
+		} else {
1727
+			if ($curBlock === 'condition') {
1728
+				// load if plugin
1729
+				$this->getPluginType('if');
1730
+
1731
+				if (Dwoo_Plugin_if::replaceKeywords(array($func), array(self::T_UNQUOTED_STRING), $this) !== array($func)) {
1732
+					return $this->parseOthers($in, $from, $to, $parsingParams, $curBlock, $pointer);
1733
+				}
1734
+			}
1735
+			$whitespace = strlen(substr($cmdstr, strlen($func), $paramspos - strlen($func)));
1736
+			$paramstr = substr($cmdstr, $paramspos + 1);
1737
+			if (substr($paramstr, -1, 1) === $paramsep) {
1738
+				$paramstr = substr($paramstr, 0, -1);
1739
+			}
1740
+
1741
+			if (strlen($paramstr) === 0) {
1742
+				$params = array();
1743
+				$paramstr = '';
1744
+			} else {
1745
+				$ptr = 0;
1746
+				$params = array();
1747
+				if ($func === 'empty') {
1748
+					$params = $this->parseVar($paramstr, $ptr, strlen($paramstr), $params, 'root', $ptr);
1749
+				} else {
1750
+					while ($ptr < strlen($paramstr)) {
1751
+						while (true) {
1752
+							if ($ptr >= strlen($paramstr)) {
1753
+								break 2;
1754
+							}
1755
+
1756
+							if ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === ')') {
1757
+								if ($this->debug) {
1758
+									echo 'PARAM PARSING ENDED, ")" FOUND, POINTER AT '.$ptr."\n";
1759
+								}
1760
+								break 2;
1761
+							} elseif ($paramstr[$ptr] === ';') {
1762
+								++$ptr;
1763
+								if ($this->debug) {
1764
+									echo 'PARAM PARSING ENDED, ";" FOUND, POINTER AT '.$ptr."\n";
1765
+								}
1766
+								break 2;
1767
+							} elseif ($func !== 'if' && $func !== 'elseif' && $paramstr[$ptr] === '/') {
1768
+								if ($this->debug) {
1769
+									echo 'PARAM PARSING ENDED, "/" FOUND, POINTER AT '.$ptr."\n";
1770
+								}
1771
+								break 2;
1772
+							} elseif (substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
1773
+								if ($this->debug) {
1774
+									echo 'PARAM PARSING ENDED, RIGHT DELIMITER FOUND, POINTER AT '.$ptr."\n";
1775
+								}
1776
+								break 2;
1777
+							}
1778
+
1779
+							if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === ',' || $paramstr[$ptr] === "\r" || $paramstr[$ptr] === "\n" || $paramstr[$ptr] === "\t") {
1780
+								++$ptr;
1781
+							} else {
1782
+								break;
1783
+							}
1784
+						}
1785
+
1786
+						if ($this->debug) {
1787
+							echo 'FUNC START PARAM PARSING WITH POINTER AT '.$ptr."\n";
1788
+						}
1789
+
1790
+						if ($func === 'if' || $func === 'elseif' || $func === 'tif') {
1791
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'condition', $ptr);
1792
+						} elseif ($func === 'array') {
1793
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'array', $ptr);
1794
+						} else {
1795
+							$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'function', $ptr);
1796
+						}
1797
+
1798
+						if ($this->debug) {
1799
+							echo 'PARAM PARSED, POINTER AT '.$ptr.' ('.substr($paramstr, $ptr - 1, 3).')'."\n";
1800
+						}
1801
+					}
1802
+				}
1803
+				$paramstr = substr($paramstr, 0, $ptr);
1804
+				$state = 0;
1805
+				foreach ($params as $k => $p) {
1806
+					if (is_array($p) && is_array($p[1])) {
1807
+						$state |= 2;
1808
+					} else {
1809
+						if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m) && $func !== 'array') {
1810
+							$params[$k] = array($m[2], array('true', 'true'));
1811
+						} else {
1812
+							if ($state & 2 && $func !== 'array') {
1813
+								throw new Dwoo_Compilation_Exception($this, 'You can not use an unnamed parameter after a named one');
1814
+							}
1815
+							$state |= 1;
1816
+						}
1817
+					}
1818
+				}
1819
+			}
1820
+		}
1821
+
1822
+		if ($pointer !== null) {
1823
+			$pointer += (isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func) + (isset($whitespace) ? $whitespace : 0);
1824
+			if ($this->debug) {
1825
+				echo 'FUNC ADDS '.((isset($paramstr) ? strlen($paramstr) : 0) + (')' === $paramsep ? 2 : ($paramspos === false ? 0 : 1)) + strlen($func)).' TO POINTER'."\n";
1826
+			}
1827
+		}
1828
+
1829
+		if ($curBlock === 'method' || $func === 'do' || strstr($func, '::') !== false) {
1830
+			// handle static method calls with security policy
1831
+			if (strstr($func, '::') !== false && $this->securityPolicy !== null && $this->securityPolicy->isMethodAllowed(explode('::', strtolower($func))) !== true) {
1832
+				throw new Dwoo_Security_Exception('Call to a disallowed php function : '.$func);
1833
+			}
1834
+			$pluginType = Dwoo_Core::NATIVE_PLUGIN;
1835
+		} else {
1836
+			$pluginType = $this->getPluginType($func);
1837
+		}
1838
+
1839
+		// blocks
1840
+		if ($pluginType & Dwoo_Core::BLOCK_PLUGIN) {
1841
+			if ($curBlock !== 'root' || is_array($parsingParams)) {
1842
+				throw new Dwoo_Compilation_Exception($this, 'Block plugins can not be used as other plugin\'s arguments');
1843
+			}
1844
+			if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1845
+				return $this->addCustomBlock($func, $params, $state);
1846
+			} else {
1847
+				return $this->addBlock($func, $params, $state);
1848
+			}
1849
+		} elseif ($pluginType & Dwoo_Core::SMARTY_BLOCK) {
1850
+			if ($curBlock !== 'root' || is_array($parsingParams)) {
1851
+				throw new Dwoo_Compilation_Exception($this, 'Block plugins can not be used as other plugin\'s arguments');
1852
+			}
1853
+
1854
+			if ($state & 2) {
1855
+				array_unshift($params, array('__functype', array($pluginType, $pluginType)));
1856
+				array_unshift($params, array('__funcname', array($func, $func)));
1857
+			} else {
1858
+				array_unshift($params, array($pluginType, $pluginType));
1859
+				array_unshift($params, array($func, $func));
1860
+			}
1861
+
1862
+			return $this->addBlock('smartyinterface', $params, $state);
1863
+		}
1864
+
1865
+		// funcs
1866
+		if ($pluginType & Dwoo_Core::NATIVE_PLUGIN || $pluginType & Dwoo_Core::SMARTY_FUNCTION || $pluginType & Dwoo_Core::SMARTY_BLOCK) {
1867
+			$params = $this->mapParams($params, null, $state);
1868
+		} elseif ($pluginType & Dwoo_Core::CLASS_PLUGIN) {
1869
+			if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1870
+				$params = $this->mapParams($params, array($this->customPlugins[$func]['class'], $this->customPlugins[$func]['function']), $state);
1871
+			} else {
1872
+				$params = $this->mapParams($params, array('Dwoo_Plugin_'.$func, ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? 'compile' : 'process'), $state);
1873
+			}
1874
+		} elseif ($pluginType & Dwoo_Core::FUNC_PLUGIN) {
1875
+			if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1876
+				$params = $this->mapParams($params, $this->customPlugins[$func]['callback'], $state);
1877
+			} else {
1878
+				$params = $this->mapParams($params, 'Dwoo_Plugin_'.$func.(($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? '_compile' : ''), $state);
1879
+			}
1880
+		} elseif ($pluginType & Dwoo_Core::SMARTY_MODIFIER) {
1881
+			$output = 'smarty_modifier_'.$func.'('.implode(', ', $params).')';
1882
+		} elseif ($pluginType & Dwoo_Core::PROXY_PLUGIN) {
1883
+			$params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
1884
+		} elseif ($pluginType & Dwoo_Core::TEMPLATE_PLUGIN) {
1885
+			// transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
1886
+			$map = array();
1887
+			foreach ($this->templatePlugins[$func]['params'] as $param => $defValue) {
1888
+				if ($param == 'rest') {
1889
+					$param = '*';
1890
+				}
1891
+				$hasDefault = $defValue !== null;
1892
+				if ($defValue === 'null') {
1893
+					$defValue = null;
1894
+				} elseif ($defValue === 'false') {
1895
+					$defValue = false;
1896
+				} elseif ($defValue === 'true') {
1897
+					$defValue = true;
1898
+				} elseif (preg_match('#^([\'"]).*?\1$#', $defValue)) {
1899
+					$defValue = substr($defValue, 1, -1);
1900
+				}
1901
+				$map[] = array($param, $hasDefault, $defValue);
1902
+			}
1903
+
1904
+			$params = $this->mapParams($params, null, $state, $map);
1905
+		}
1906
+
1907
+		// only keep php-syntax-safe values for non-block plugins
1908
+		$tokens = array();
1909
+		foreach ($params as $k => $p) {
1910
+			$tokens[$k] = isset($p[2]) ? $p[2] : 0;
1911
+			$params[$k] = $p[0];
1912
+		}
1913
+		if ($pluginType & Dwoo_Core::NATIVE_PLUGIN) {
1914
+			if ($func === 'do') {
1915
+				if (isset($params['*'])) {
1916
+					$output = implode(';', $params['*']).';';
1917
+				} else {
1918
+					$output = '';
1919
+				}
1920
+
1921
+				if (is_array($parsingParams) || $curBlock !== 'root') {
1922
+					throw new Dwoo_Compilation_Exception($this, 'Do can not be used inside another function or block');
1923
+				} else {
1924
+					return self::PHP_OPEN.$output.self::PHP_CLOSE;
1925
+				}
1926
+			} else {
1927
+				if (isset($params['*'])) {
1928
+					$output = $func.'('.implode(', ', $params['*']).')';
1929
+				} else {
1930
+					$output = $func.'()';
1931
+				}
1932
+			}
1933
+		} elseif ($pluginType & Dwoo_Core::FUNC_PLUGIN) {
1934
+			if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
1935
+				if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1936
+					$funcCompiler = $this->customPlugins[$func]['callback'];
1937
+				} else {
1938
+					$funcCompiler = 'Dwoo_Plugin_'.$func.'_compile';
1939
+				}
1940
+				array_unshift($params, $this);
1941
+				if ($func === 'tif') {
1942
+					$params[] = $tokens;
1943
+				}
1944
+				$output = call_user_func_array($funcCompiler, $params);
1945
+			} else {
1946
+				if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1947
+					$callback = $this->customPlugins[$func]['callback'];
1948
+					if ($callback instanceof \Closure) {
1949
+						array_unshift($params, $this->getDwoo());
1950
+						$output = call_user_func_array($callback, $params);
1951
+					} else {
1952
+						array_unshift($params, '$this');
1953
+						$params = self::implode_r($params);
1954
+						$output = 'call_user_func(\''.$callback.'\', '.$params.')';
1955
+					}
1956
+				} else {
1957
+					array_unshift($params, '$this');
1958
+					$params = self::implode_r($params);
1959
+					$output = 'Dwoo_Plugin_'.$func.'('.$params.')';
1960
+				}
1961
+			}
1962
+		} elseif ($pluginType & Dwoo_Core::CLASS_PLUGIN) {
1963
+			if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
1964
+				if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1965
+					$callback = $this->customPlugins[$func]['callback'];
1966
+					if (!is_array($callback)) {
1967
+						if (!method_exists($callback, 'compile')) {
1968
+							throw new Dwoo_Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
1969
+						}
1970
+						if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
1971
+							$funcCompiler = array($callback, 'compile');
1972
+						} else {
1973
+							$funcCompiler = array(new $callback(), 'compile');
1974
+						}
1975
+					} else {
1976
+						$funcCompiler = $callback;
1977
+					}
1978
+				} else {
1979
+					$funcCompiler = array('Dwoo_Plugin_'.$func, 'compile');
1980
+					array_unshift($params, $this);
1981
+				}
1982
+				$output = call_user_func_array($funcCompiler, $params);
1983
+			} else {
1984
+				$params = self::implode_r($params);
1985
+				if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
1986
+					$callback = $this->customPlugins[$func]['callback'];
1987
+					if (!is_array($callback)) {
1988
+						if (!method_exists($callback, 'process')) {
1989
+							throw new Dwoo_Exception('Custom plugin '.$func.' must implement the "process" method to be usable, or you should provide a full callback to the method to use');
1990
+						}
1991
+						if (($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic()) {
1992
+							$output = 'call_user_func(array(\''.$callback.'\', \'process\'), '.$params.')';
1993
+						} else {
1994
+							$output = 'call_user_func(array($this->getObjectPlugin(\''.$callback.'\'), \'process\'), '.$params.')';
1995
+						}
1996
+					} elseif (is_object($callback[0])) {
1997
+						$output = 'call_user_func(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), '.$params.')';
1998
+					} elseif (($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic()) {
1999
+						$output = 'call_user_func(array(\''.$callback[0].'\', \''.$callback[1].'\'), '.$params.')';
2000
+					} else {
2001
+						$output = 'call_user_func(array($this->getObjectPlugin(\''.$callback[0].'\'), \''.$callback[1].'\'), '.$params.')';
2002
+					}
2003
+					if (empty($params)) {
2004
+						$output = substr($output, 0, -3).')';
2005
+					}
2006
+				} else {
2007
+					$output = '$this->classCall(\''.$func.'\', array('.$params.'))';
2008
+				}
2009
+			}
2010
+		} elseif ($pluginType & Dwoo_Core::PROXY_PLUGIN) {
2011
+			$output = call_user_func(array($this->dwoo->getPluginProxy(), 'getCode'), $func, $params);
2012
+		} elseif ($pluginType & Dwoo_Core::SMARTY_FUNCTION) {
2013
+			if (isset($params['*'])) {
2014
+				$params = self::implode_r($params['*'], true);
2015
+			} else {
2016
+				$params = '';
2017
+			}
2018
+
2019
+			if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
2020
+				$callback = $this->customPlugins[$func]['callback'];
2021
+				if (is_array($callback)) {
2022
+					if (is_object($callback[0])) {
2023
+						$output = 'call_user_func_array(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array(array('.$params.'), $this))';
2024
+					} else {
2025
+						$output = 'call_user_func_array(array(\''.$callback[0].'\', \''.$callback[1].'\'), array(array('.$params.'), $this))';
2026
+					}
2027
+				} else {
2028
+					$output = $callback.'(array('.$params.'), $this)';
2029
+				}
2030
+			} else {
2031
+				$output = 'smarty_function_'.$func.'(array('.$params.'), $this)';
2032
+			}
2033
+		} elseif ($pluginType & Dwoo_Core::TEMPLATE_PLUGIN) {
2034
+			array_unshift($params, '$this');
2035
+			$params = self::implode_r($params);
2036
+			$output = 'Dwoo_Plugin_'.$func.'('.$params.')';
2037
+			$this->templatePlugins[$func]['called'] = true;
2038
+		}
2039
+
2040
+		if (is_array($parsingParams)) {
2041
+			$parsingParams[] = array($output, $output);
2042
+
2043
+			return $parsingParams;
2044
+		} elseif ($curBlock === 'namedparam') {
2045
+			return array($output, $output);
2046
+		} else {
2047
+			return $output;
2048
+		}
2049
+	}
2050
+
2051
+	/**
2052
+	 * parses a string.
2053
+	 *
2054
+	 * @param string $in            the string within which we must parse something
2055
+	 * @param int    $from          the starting offset of the parsed area
2056
+	 * @param int    $to            the ending offset of the parsed area
2057
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2058
+	 * @param string $curBlock      the current parser-block being processed
2059
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2060
+	 *
2061
+	 * @return string parsed values
2062
+	 *
2063
+	 * @throws Dwoo_Compilation_Exception
2064
+	 */
2065
+	protected function parseString($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2066
+	{
2067
+		$substr = substr($in, $from, $to - $from);
2068
+		$first = $substr[0];
2069
+
2070
+		if ($this->debug) {
2071
+			echo 'STRING FOUND (in '.htmlentities(substr($in, $from, min($to - $from, 50))).(($to - $from) > 50 ? '...' : '').')'."\n";
2072
+		}
2073
+		$strend = false;
2074
+		$o = $from + 1;
2075
+		while ($strend === false) {
2076
+			$strend = strpos($in, $first, $o);
2077
+			if ($strend === false) {
2078
+				throw new Dwoo_Compilation_Exception($this, 'Unfinished string, started with '.substr($in, $from, $to - $from));
2079
+			}
2080
+			if (substr($in, $strend - 1, 1) === '\\') {
2081
+				$o = $strend + 1;
2082
+				$strend = false;
2083
+			}
2084
+		}
2085
+		if ($this->debug) {
2086
+			echo 'STRING DELIMITED: '.substr($in, $from, $strend + 1 - $from)."\n";
2087
+		}
2088
+
2089
+		$srcOutput = substr($in, $from, $strend + 1 - $from);
2090
+
2091
+		if ($pointer !== null) {
2092
+			$pointer += strlen($srcOutput);
2093
+		}
2094
+
2095
+		$output = $this->replaceStringVars($srcOutput, $first);
2096
+
2097
+		// handle modifiers
2098
+		if ($curBlock !== 'modifier' && preg_match('#^((?:\|(?:@?[a-z0-9_]+(?::.*)*))+)#i', substr($substr, $strend + 1 - $from), $match)) {
2099
+			$modstr = $match[1];
2100
+
2101
+			if ($curBlock === 'root' && substr($modstr, -1) === '}') {
2102
+				$modstr = substr($modstr, 0, -1);
2103
+			}
2104
+			$modstr = str_replace('\\'.$first, $first, $modstr);
2105
+			$ptr = 0;
2106
+			$output = $this->replaceModifiers(array(null, null, $output, $modstr), 'string', $ptr);
2107
+
2108
+			$strend += $ptr;
2109
+			if ($pointer !== null) {
2110
+				$pointer += $ptr;
2111
+			}
2112
+			$srcOutput .= substr($substr, $strend + 1 - $from, $ptr);
2113
+		}
2114
+
2115
+		if (is_array($parsingParams)) {
2116
+			$parsingParams[] = array($output, substr($srcOutput, 1, -1));
2117
+
2118
+			return $parsingParams;
2119
+		} elseif ($curBlock === 'namedparam') {
2120
+			return array($output, substr($srcOutput, 1, -1));
2121
+		} else {
2122
+			return $output;
2123
+		}
2124
+	}
2125
+
2126
+	/**
2127
+	 * parses a constant.
2128
+	 *
2129
+	 * @param string $in            the string within which we must parse something
2130
+	 * @param int    $from          the starting offset of the parsed area
2131
+	 * @param int    $to            the ending offset of the parsed area
2132
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2133
+	 * @param string $curBlock      the current parser-block being processed
2134
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2135
+	 *
2136
+	 * @return string parsed values
2137
+	 *
2138
+	 * @throws Dwoo_Compilation_Exception
2139
+	 */
2140
+	protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2141
+	{
2142
+		$substr = substr($in, $from, $to - $from);
2143
+
2144
+		if ($this->debug) {
2145
+			echo 'CONST FOUND : '.$substr."\n";
2146
+		}
2147
+
2148
+		if (!preg_match('#^%([\\\\a-z0-9_:]+)#i', $substr, $m)) {
2149
+			throw new Dwoo_Compilation_Exception($this, 'Invalid constant');
2150
+		}
2151
+
2152
+		if ($pointer !== null) {
2153
+			$pointer += strlen($m[0]);
2154
+		}
2155
+
2156
+		$output = $this->parseConstKey($m[1], $curBlock);
2157
+
2158
+		if (is_array($parsingParams)) {
2159
+			$parsingParams[] = array($output, $m[1]);
2160
+
2161
+			return $parsingParams;
2162
+		} elseif ($curBlock === 'namedparam') {
2163
+			return array($output, $m[1]);
2164
+		} else {
2165
+			return $output;
2166
+		}
2167
+	}
2168
+
2169
+	/**
2170
+	 * parses a constant.
2171
+	 *
2172
+	 * @param string $key      the constant to parse
2173
+	 * @param string $curBlock the current parser-block being processed
2174
+	 *
2175
+	 * @return string parsed constant
2176
+	 */
2177
+	protected function parseConstKey($key, $curBlock)
2178
+	{
2179
+		if ($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === Dwoo_Security_Policy::CONST_DISALLOW) {
2180
+			return 'null';
2181
+		}
2182
+
2183
+		if ($curBlock !== 'root') {
2184
+			$output = '(defined("'.$key.'") ? '.$key.' : null)';
2185
+		} else {
2186
+			$output = $key;
2187
+		}
2188
+
2189
+		return $output;
2190
+	}
2191
+
2192
+	/**
2193
+	 * parses a variable.
2194
+	 *
2195
+	 * @param string $in            the string within which we must parse something
2196
+	 * @param int    $from          the starting offset of the parsed area
2197
+	 * @param int    $to            the ending offset of the parsed area
2198
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2199
+	 * @param string $curBlock      the current parser-block being processed
2200
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2201
+	 *
2202
+	 * @return string parsed values
2203
+	 *
2204
+	 * @throws Dwoo_Compilation_Exception
2205
+	 */
2206
+	protected function parseVar($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2207
+	{
2208
+		$substr = substr($in, $from, $to - $from);
2209
+
2210
+		if (preg_match('#(\$?\.?[a-z0-9_:]*(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R)|(["\'])[^\2]*?\2)\]))*)'. // var key
2211
+			($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'expression' || $curBlock === 'delimited_string' ? '(\(.*)?' : '()'). // method call
2212
+			($curBlock === 'root' || $curBlock === 'function' || $curBlock === 'namedparam' || $curBlock === 'condition' || $curBlock === 'variable' || $curBlock === 'delimited_string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)' : '()'). // simple math expressions
2213
+			($curBlock !== 'modifier' ? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').*?\5|:[^`]*))*))+)?' : '(())'). // modifiers
2214
+			'#i', $substr, $match)) {
2215
+			$key = substr($match[1], 1);
2216
+
2217
+			$matchedLength = strlen($match[0]);
2218
+			$hasModifiers = !empty($match[5]);
2219
+			$hasExpression = !empty($match[4]);
2220
+			$hasMethodCall = !empty($match[3]);
2221
+
2222
+			if (substr($key, -1) == '.') {
2223
+				$key = substr($key, 0, -1);
2224
+				--$matchedLength;
2225
+			}
2226
+
2227
+			if ($hasMethodCall) {
2228
+				$matchedLength -= strlen($match[3]) + strlen(substr($match[1], strrpos($match[1], '->')));
2229
+				$key = substr($match[1], 1, strrpos($match[1], '->') - 1);
2230
+				$methodCall = substr($match[1], strrpos($match[1], '->')).$match[3];
2231
+			}
2232
+
2233
+			if ($hasModifiers) {
2234
+				$matchedLength -= strlen($match[5]);
2235
+			}
2236
+
2237
+			if ($pointer !== null) {
2238
+				$pointer += $matchedLength;
2239
+			}
2240
+
2241
+			// replace useless brackets by dot accessed vars and strip enclosing quotes if present
2242
+			$key = preg_replace('#\[(["\']?)([^$%\[.>-]+)\1\]#', '.$2', $key);
2243
+
2244
+			if ($this->debug) {
2245
+				if ($hasMethodCall) {
2246
+					echo 'METHOD CALL FOUND : $'.$key.substr($methodCall, 0, 30)."\n";
2247
+				} else {
2248
+					echo 'VAR FOUND : $'.$key."\n";
2249
+				}
2250
+			}
2251
+
2252
+			$key = str_replace('"', '\\"', $key);
2253
+
2254
+			$cnt = substr_count($key, '$');
2255
+			if ($cnt > 0) {
2256
+				$uid = 0;
2257
+				$parsed = array($uid => '');
2258
+				$current = &$parsed;
2259
+				$curTxt = &$parsed[$uid++];
2260
+				$tree = array();
2261
+				$chars = str_split($key, 1);
2262
+				$inSplittedVar = false;
2263
+				$bracketCount = 0;
2264
+
2265
+				while (($char = array_shift($chars)) !== null) {
2266
+					if ($char === '[') {
2267
+						if (count($tree) > 0) {
2268
+							++$bracketCount;
2269
+						} else {
2270
+							$tree[] = &$current;
2271
+							$current[$uid] = array($uid + 1 => '');
2272
+							$current = &$current[$uid++];
2273
+							$curTxt = &$current[$uid++];
2274
+							continue;
2275
+						}
2276
+					} elseif ($char === ']') {
2277
+						if ($bracketCount > 0) {
2278
+							--$bracketCount;
2279
+						} else {
2280
+							$current = &$tree[count($tree) - 1];
2281
+							array_pop($tree);
2282
+							if (current($chars) !== '[' && current($chars) !== false && current($chars) !== ']') {
2283
+								$current[$uid] = '';
2284
+								$curTxt = &$current[$uid++];
2285
+							}
2286
+							continue;
2287
+						}
2288
+					} elseif ($char === '$') {
2289
+						if (count($tree) == 0) {
2290
+							$curTxt = &$current[$uid++];
2291
+							$inSplittedVar = true;
2292
+						}
2293
+					} elseif (($char === '.' || $char === '-') && count($tree) == 0 && $inSplittedVar) {
2294
+						$curTxt = &$current[$uid++];
2295
+						$inSplittedVar = false;
2296
+					}
2297
+
2298
+					$curTxt .= $char;
2299
+				}
2300
+				unset($uid, $current, $curTxt, $tree, $chars);
2301
+
2302
+				if ($this->debug) {
2303
+					echo 'RECURSIVE VAR REPLACEMENT : '.$key."\n";
2304
+				}
2305
+
2306
+				$key = $this->flattenVarTree($parsed);
2307
+
2308
+				if ($this->debug) {
2309
+					echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2310
+				}
2311
+
2312
+				$output = preg_replace('#(^""\.|""\.|\.""$|(\()""\.|\.""(\)))#', '$2$3', '$this->readVar("'.$key.'")');
2313
+			} else {
2314
+				$output = $this->parseVarKey($key, $hasModifiers ? 'modifier' : $curBlock);
2315
+			}
2316
+
2317
+			// methods
2318
+			if ($hasMethodCall) {
2319
+				$ptr = 0;
2320
+
2321
+				$output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
2322
+
2323
+				if ($pointer !== null) {
2324
+					$pointer += $ptr;
2325
+				}
2326
+				$matchedLength += $ptr;
2327
+			}
2328
+
2329
+			if ($hasExpression) {
2330
+				// expressions
2331
+				preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[4], $expMatch);
2332
+
2333
+				foreach ($expMatch[1] as $k => $operator) {
2334
+					if (substr($expMatch[2][$k], 0, 1) === '=') {
2335
+						$assign = true;
2336
+						if ($operator === '=') {
2337
+							throw new Dwoo_Compilation_Exception($this, 'Invalid expression <em>'.$substr.'</em>, can not use "==" in expressions');
2338
+						}
2339
+						if ($curBlock !== 'root') {
2340
+							throw new Dwoo_Compilation_Exception($this, 'Invalid expression <em>'.$substr.'</em>, assignments can only be used in top level expressions like {$foo+=3} or {$foo="bar"}');
2341
+						}
2342
+						$operator .= '=';
2343
+						$expMatch[2][$k] = substr($expMatch[2][$k], 1);
2344
+					}
2345
+
2346
+					if (substr($expMatch[2][$k], 0, 1) === '-' && strlen($expMatch[2][$k]) > 1) {
2347
+						$operator .= '-';
2348
+						$expMatch[2][$k] = substr($expMatch[2][$k], 1);
2349
+					}
2350
+					if (($operator === '+' || $operator === '-') && $expMatch[2][$k] === $operator) {
2351
+						$output = '('.$output.$operator.$operator.')';
2352
+						break;
2353
+					} elseif (substr($expMatch[2][$k], 0, 1) === '$') {
2354
+						$output = '('.$output.' '.$operator.' '.$this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2355
+					} elseif (substr($expMatch[2][$k], 0, 1) === '%') {
2356
+						$output = '('.$output.' '.$operator.' '.$this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
2357
+					} elseif (!empty($expMatch[2][$k])) {
2358
+						$output = '('.$output.' '.$operator.' '.str_replace(',', '.', $expMatch[2][$k]).')';
2359
+					} else {
2360
+						throw new Dwoo_Compilation_Exception($this, 'Unfinished expression <em>'.$substr.'</em>, missing var or number after math operator');
2361
+					}
2362
+				}
2363
+			}
2364
+
2365
+			if ($this->autoEscape === true && $curBlock !== 'condition') {
2366
+				$output = '(is_string($tmp='.$output.') ? htmlspecialchars($tmp, ENT_QUOTES, $this->charset) : $tmp)';
2367
+			}
2368
+
2369
+			// handle modifiers
2370
+			if ($curBlock !== 'modifier' && $hasModifiers) {
2371
+				$ptr = 0;
2372
+				$output = $this->replaceModifiers(array(null, null, $output, $match[5]), 'var', $ptr);
2373
+				if ($pointer !== null) {
2374
+					$pointer += $ptr;
2375
+				}
2376
+				$matchedLength += $ptr;
2377
+			}
2378
+
2379
+			if (is_array($parsingParams)) {
2380
+				$parsingParams[] = array($output, $key);
2381
+
2382
+				return $parsingParams;
2383
+			} elseif ($curBlock === 'namedparam') {
2384
+				return array($output, $key);
2385
+			} elseif ($curBlock === 'string' || $curBlock === 'delimited_string') {
2386
+				return array($matchedLength, $output);
2387
+			} elseif ($curBlock === 'expression' || $curBlock === 'variable') {
2388
+				return $output;
2389
+			} elseif (isset($assign)) {
2390
+				return self::PHP_OPEN.$output.';'.self::PHP_CLOSE;
2391
+			} else {
2392
+				return $output;
2393
+			}
2394
+		} else {
2395
+			if ($curBlock === 'string' || $curBlock === 'delimited_string') {
2396
+				return array(0, '');
2397
+			} else {
2398
+				throw new Dwoo_Compilation_Exception($this, 'Invalid variable name <em>'.$substr.'</em>');
2399
+			}
2400
+		}
2401
+	}
2402
+
2403
+	/**
2404
+	 * parses any number of chained method calls/property reads.
2405
+	 *
2406
+	 * @param string $output     the variable or whatever upon which the method are called
2407
+	 * @param string $methodCall method call source, starting at "->"
2408
+	 * @param string $curBlock   the current parser-block being processed
2409
+	 * @param int    $pointer    a reference to a pointer that will be increased by the amount of characters parsed
2410
+	 *
2411
+	 * @return string parsed call(s)/read(s)
2412
+	 */
2413
+	protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
2414
+	{
2415
+		$ptr = 0;
2416
+		$len = strlen($methodCall);
2417
+
2418
+		while ($ptr < $len) {
2419
+			if (strpos($methodCall, '->', $ptr) === $ptr) {
2420
+				$ptr += 2;
2421
+			}
2422
+
2423
+			if (in_array($methodCall[$ptr], array(';', ',', '/', ' ', "\t", "\r", "\n", ')', '+', '*', '%', '=', '-', '|')) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd) {
2424
+				// break char found
2425
+				break;
2426
+			}
2427
+
2428
+			if (!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
2429
+				break;
2430
+			}
2431
+
2432
+			if (empty($methMatch[2])) {
2433
+				// property
2434
+				if ($curBlock === 'root') {
2435
+					$output .= '->'.$methMatch[1];
2436
+				} else {
2437
+					$output = '(($tmp = '.$output.') ? $tmp->'.$methMatch[1].' : null)';
2438
+				}
2439
+				$ptr += strlen($methMatch[1]);
2440
+			} else {
2441
+				// method
2442
+				if (substr($methMatch[2], 0, 2) === '()') {
2443
+					$parsedCall = $methMatch[1].'()';
2444
+					$ptr += strlen($methMatch[1]) + 2;
2445
+				} else {
2446
+					$parsedCall = $this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
2447
+				}
2448
+				if ($this->securityPolicy !== null) {
2449
+					$argPos = strpos($parsedCall, '(');
2450
+					$method = strtolower(substr($parsedCall, 0, $argPos));
2451
+					$args = substr($parsedCall, $argPos);
2452
+					if ($curBlock === 'root') {
2453
+						$output = '$this->getSecurityPolicy()->callMethod($this, '.$output.', '.var_export($method, true).', array'.$args.')';
2454
+					} else {
2455
+						$output = '(($tmp = '.$output.') ? $this->getSecurityPolicy()->callMethod($this, $tmp, '.var_export($method, true).', array'.$args.') : null)';
2456
+					}
2457
+				} else {
2458
+					if ($curBlock === 'root') {
2459
+						$output .= '->'.$parsedCall;
2460
+					} else {
2461
+						$output = '(($tmp = '.$output.') ? $tmp->'.$parsedCall.' : null)';
2462
+					}
2463
+				}
2464
+			}
2465
+		}
2466
+
2467
+		$pointer += $ptr;
2468
+
2469
+		return $output;
2470
+	}
2471
+
2472
+	/**
2473
+	 * parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save runtime processing time.
2474
+	 *
2475
+	 * @param string $key      the variable to parse
2476
+	 * @param string $curBlock the current parser-block being processed
2477
+	 *
2478
+	 * @return string parsed variable
2479
+	 */
2480
+	protected function parseVarKey($key, $curBlock)
2481
+	{
2482
+		if ($key === '') {
2483
+			return '$this->scope';
2484
+		}
2485
+		if (substr($key, 0, 1) === '.') {
2486
+			$key = 'dwoo'.$key;
2487
+		}
2488
+		if (preg_match('#dwoo\.(get|post|server|cookies|session|env|request)((?:\.[a-z0-9_-]+)+)#i', $key, $m)) {
2489
+			$global = strtoupper($m[1]);
2490
+			if ($global === 'COOKIES') {
2491
+				$global = 'COOKIE';
2492
+			}
2493
+			$key = '$_'.$global;
2494
+			foreach (explode('.', ltrim($m[2], '.')) as $part) {
2495
+				$key .= '['.var_export($part, true).']';
2496
+			}
2497
+			if ($curBlock === 'root') {
2498
+				$output = $key;
2499
+			} else {
2500
+				$output = '(isset('.$key.')?'.$key.':null)';
2501
+			}
2502
+		} elseif (preg_match('#dwoo\.const\.([a-z0-9_:]+)#i', $key, $m)) {
2503
+			return $this->parseConstKey($m[1], $curBlock);
2504
+		} elseif ($this->scope !== null) {
2505
+			if (strstr($key, '.') === false && strstr($key, '[') === false && strstr($key, '->') === false) {
2506
+				if ($key === 'dwoo') {
2507
+					$output = '$this->globals';
2508
+				} elseif ($key === '_root' || $key === '__') {
2509
+					$output = '$this->data';
2510
+				} elseif ($key === '_parent' || $key === '_') {
2511
+					$output = '$this->readParentVar(1)';
2512
+				} elseif ($key === '_key') {
2513
+					$output = '$tmp_key';
2514
+				} else {
2515
+					if ($curBlock === 'root') {
2516
+						$output = '$this->scope["'.$key.'"]';
2517
+					} else {
2518
+						$output = '(isset($this->scope["'.$key.'"]) ? $this->scope["'.$key.'"] : null)';
2519
+					}
2520
+				}
2521
+			} else {
2522
+				preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+|(\\\?[\'"])[^\3]*?\3)\]?#i', $key, $m);
2523
+
2524
+				$i = $m[2][0];
2525
+				if ($i === '_parent' || $i === '_') {
2526
+					$parentCnt = 0;
2527
+
2528
+					while (true) {
2529
+						++$parentCnt;
2530
+						array_shift($m[2]);
2531
+						array_shift($m[1]);
2532
+						if (current($m[2]) === '_parent') {
2533
+							continue;
2534
+						}
2535
+						break;
2536
+					}
2537
+
2538
+					$output = '$this->readParentVar('.$parentCnt.')';
2539
+				} else {
2540
+					if ($i === 'dwoo') {
2541
+						$output = '$this->globals';
2542
+						array_shift($m[2]);
2543
+						array_shift($m[1]);
2544
+					} elseif ($i === '_root' || $i === '__') {
2545
+						$output = '$this->data';
2546
+						array_shift($m[2]);
2547
+						array_shift($m[1]);
2548
+					} elseif ($i === '_key') {
2549
+						$output = '$tmp_key';
2550
+					} else {
2551
+						$output = '$this->scope';
2552
+					}
2553
+
2554
+					while (count($m[1]) && $m[1][0] !== '->') {
2555
+						$m[2][0] = preg_replace('/(^\\\([\'"])|\\\([\'"])$)/x', '$2$3', $m[2][0]);
2556
+						if (substr($m[2][0], 0, 1) == '"' || substr($m[2][0], 0, 1) == "'") {
2557
+							$output .= '['.$m[2][0].']';
2558
+						} else {
2559
+							$output .= '["'.$m[2][0].'"]';
2560
+						}
2561
+						array_shift($m[2]);
2562
+						array_shift($m[1]);
2563
+					}
2564
+
2565
+					if ($curBlock !== 'root') {
2566
+						$output = '(isset('.$output.') ? '.$output.':null)';
2567
+					}
2568
+				}
2569
+
2570
+				if (count($m[2])) {
2571
+					unset($m[0]);
2572
+					$output = '$this->readVarInto('.str_replace("\n", '', var_export($m, true)).', '.$output.', '.($curBlock == 'root' ? 'false' : 'true').')';
2573
+				}
2574
+			}
2575
+		} else {
2576
+			preg_match_all('#(\[|->|\.)?((?:[a-z0-9_]|-(?!>))+)\]?#i', $key, $m);
2577
+			unset($m[0]);
2578
+			$output = '$this->readVar('.str_replace("\n", '', var_export($m, true)).')';
2579
+		}
2580
+
2581
+		return $output;
2582
+	}
2583
+
2584
+	/**
2585
+	 * flattens a variable tree, this helps in parsing very complex variables such as $var.foo[$foo.bar->baz].baz,
2586
+	 * it computes the contents of the brackets first and works out from there.
2587
+	 *
2588
+	 * @param array $tree     the variable tree parsed by he parseVar() method that must be flattened
2589
+	 * @param bool  $recursed leave that to false by default, it is only for internal use
2590
+	 *
2591
+	 * @return string flattened tree
2592
+	 */
2593
+	protected function flattenVarTree(array $tree, $recursed = false)
2594
+	{
2595
+		$out = $recursed ? '".$this->readVarInto(' : '';
2596
+		foreach ($tree as $bit) {
2597
+			if (is_array($bit)) {
2598
+				$out .= '.'.$this->flattenVarTree($bit, false);
2599
+			} else {
2600
+				$key = str_replace('"', '\\"', $bit);
2601
+
2602
+				if (substr($key, 0, 1) === '$') {
2603
+					$out .= '".'.$this->parseVar($key, 0, strlen($key), false, 'variable').'."';
2604
+				} else {
2605
+					$cnt = substr_count($key, '$');
2606
+
2607
+					if ($this->debug) {
2608
+						echo 'PARSING SUBVARS IN : '.$key."\n";
2609
+					}
2610
+					if ($cnt > 0) {
2611
+						while (--$cnt >= 0) {
2612
+							if (isset($last)) {
2613
+								$last = strrpos($key, '$', -(strlen($key) - $last + 1));
2614
+							} else {
2615
+								$last = strrpos($key, '$');
2616
+							}
2617
+							preg_match('#\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*'.
2618
+									  '((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i', substr($key, $last), $submatch);
2619
+
2620
+							$len = strlen($submatch[0]);
2621
+							$key = substr_replace(
2622
+								$key,
2623
+								preg_replace_callback(
2624
+									'#(\$[a-z0-9_]+((?:(?:\.|->)(?:[a-z0-9_]+|(?R))|\[(?:[a-z0-9_]+|(?R))\]))*)'.
2625
+									'((?:(?:[+/*%-])(?:\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|[0-9.,]*))*)#i',
2626
+									array($this, 'replaceVarKeyHelper'), substr($key, $last, $len)
2627
+								),
2628
+								$last,
2629
+								$len
2630
+							);
2631
+							if ($this->debug) {
2632
+								echo 'RECURSIVE VAR REPLACEMENT DONE : '.$key."\n";
2633
+							}
2634
+						}
2635
+						unset($last);
2636
+
2637
+						$out .= $key;
2638
+					} else {
2639
+						$out .= $key;
2640
+					}
2641
+				}
2642
+			}
2643
+		}
2644
+		$out .= $recursed ? ', true)."' : '';
2645
+
2646
+		return $out;
2647
+	}
2648
+
2649
+	/**
2650
+	 * helper function that parses a variable.
2651
+	 *
2652
+	 * @param array $match the matched variable, array(1=>"string match")
2653
+	 *
2654
+	 * @return string parsed variable
2655
+	 */
2656
+	protected function replaceVarKeyHelper($match)
2657
+	{
2658
+		return '".'.$this->parseVar($match[0], 0, strlen($match[0]), false, 'variable').'."';
2659
+	}
2660
+
2661
+	/**
2662
+	 * parses various constants, operators or non-quoted strings.
2663
+	 *
2664
+	 * @param string $in            the string within which we must parse something
2665
+	 * @param int    $from          the starting offset of the parsed area
2666
+	 * @param int    $to            the ending offset of the parsed area
2667
+	 * @param mixed  $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
2668
+	 * @param string $curBlock      the current parser-block being processed
2669
+	 * @param mixed  $pointer       a reference to a pointer that will be increased by the amount of characters parsed, or null by default
2670
+	 *
2671
+	 * @return string parsed values
2672
+	 *
2673
+	 * @throws Exception
2674
+	 */
2675
+	protected function parseOthers($in, $from, $to, $parsingParams = false, $curBlock = '', &$pointer = null)
2676
+	{
2677
+		$first = $in[$from];
2678
+		$substr = substr($in, $from, $to - $from);
2679
+
2680
+		$end = strlen($substr);
2681
+
2682
+		if ($curBlock === 'condition') {
2683
+			$breakChars = array('(', ')', ' ', '||', '&&', '|', '&', '>=', '<=', '===', '==', '=', '!==', '!=', '<<', '<', '>>', '>', '^', '~', ',', '+', '-', '*', '/', '%', '!', '?', ':', $this->rd, ';');
2684
+		} elseif ($curBlock === 'modifier') {
2685
+			$breakChars = array(' ', ',', ')', ':', '|', "\r", "\n", "\t", ';', $this->rd);
2686
+		} elseif ($curBlock === 'expression') {
2687
+			$breakChars = array('/', '%', '+', '-', '*', ' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2688
+		} else {
2689
+			$breakChars = array(' ', ',', ')', "\r", "\n", "\t", ';', $this->rd);
2690
+		}
2691
+
2692
+		$breaker = false;
2693
+		while (list($k, $char) = each($breakChars)) {
2694
+			$test = strpos($substr, $char);
2695
+			if ($test !== false && $test < $end) {
2696
+				$end = $test;
2697
+				$breaker = $k;
2698
+			}
2699
+		}
2700
+
2701
+		if ($curBlock === 'condition') {
2702
+			if ($end === 0 && $breaker !== false) {
2703
+				$end = strlen($breakChars[$breaker]);
2704
+			}
2705
+		}
2706
+
2707
+		if ($end !== false) {
2708
+			$substr = substr($substr, 0, $end);
2709
+		}
2710
+
2711
+		if ($pointer !== null) {
2712
+			$pointer += strlen($substr);
2713
+		}
2714
+
2715
+		$src = $substr;
2716
+		$substr = trim($substr);
2717
+
2718
+		if (strtolower($substr) === 'false' || strtolower($substr) === 'no' || strtolower($substr) === 'off') {
2719
+			if ($this->debug) {
2720
+				echo 'BOOLEAN(FALSE) PARSED'."\n";
2721
+			}
2722
+			$substr = 'false';
2723
+			$type = self::T_BOOL;
2724
+		} elseif (strtolower($substr) === 'true' || strtolower($substr) === 'yes' || strtolower($substr) === 'on') {
2725
+			if ($this->debug) {
2726
+				echo 'BOOLEAN(TRUE) PARSED'."\n";
2727
+			}
2728
+			$substr = 'true';
2729
+			$type = self::T_BOOL;
2730
+		} elseif ($substr === 'null' || $substr === 'NULL') {
2731
+			if ($this->debug) {
2732
+				echo 'NULL PARSED'."\n";
2733
+			}
2734
+			$substr = 'null';
2735
+			$type = self::T_NULL;
2736
+		} elseif (is_numeric($substr)) {
2737
+			$substr = (float) $substr;
2738
+			if ((int) $substr == $substr) {
2739
+				$substr = (int) $substr;
2740
+			}
2741
+			$type = self::T_NUMERIC;
2742
+			if ($this->debug) {
2743
+				echo 'NUMBER ('.$substr.') PARSED'."\n";
2744
+			}
2745
+		} elseif (preg_match('{^-?(\d+|\d*(\.\d+))\s*([/*%+-]\s*-?(\d+|\d*(\.\d+)))+$}', $substr)) {
2746
+			if ($this->debug) {
2747
+				echo 'SIMPLE MATH PARSED . "\n"';
2748
+			}
2749
+			$type = self::T_MATH;
2750
+			$substr = '('.$substr.')';
2751
+		} elseif ($curBlock === 'condition' && array_search($substr, $breakChars, true) !== false) {
2752
+			if ($this->debug) {
2753
+				echo 'BREAKCHAR ('.$substr.') PARSED'."\n";
2754
+			}
2755
+			$type = self::T_BREAKCHAR;
2756
+			//$substr = '"'.$substr.'"';
2757
+		} else {
2758
+			$substr = $this->replaceStringVars('\''.str_replace('\'', '\\\'', $substr).'\'', '\'', $curBlock);
2759
+			$type = self::T_UNQUOTED_STRING;
2760
+			if ($this->debug) {
2761
+				echo 'BLABBER ('.$substr.') CASTED AS STRING'."\n";
2762
+			}
2763
+		}
2764
+
2765
+		if (is_array($parsingParams)) {
2766
+			$parsingParams[] = array($substr, $src, $type);
2767
+
2768
+			return $parsingParams;
2769
+		} elseif ($curBlock === 'namedparam') {
2770
+			return array($substr, $src, $type);
2771
+		} elseif ($curBlock === 'expression') {
2772
+			return $substr;
2773
+		} else {
2774
+			throw new Exception('Something went wrong');
2775
+		}
2776
+	}
2777
+
2778
+	/**
2779
+	 * replaces variables within a parsed string.
2780
+	 *
2781
+	 * @param string $string   the parsed string
2782
+	 * @param string $first    the first character parsed in the string, which is the string delimiter (' or ")
2783
+	 * @param string $curBlock the current parser-block being processed
2784
+	 *
2785
+	 * @return string the original string with variables replaced
2786
+	 */
2787
+	protected function replaceStringVars($string, $first, $curBlock = '')
2788
+	{
2789
+		$pos = 0;
2790
+		if ($this->debug) {
2791
+			echo 'STRING VAR REPLACEMENT : '.$string."\n";
2792
+		}
2793
+		// replace vars
2794
+		while (($pos = strpos($string, '$', $pos)) !== false) {
2795
+			$prev = substr($string, $pos - 1, 1);
2796
+			if ($prev === '\\') {
2797
+				++$pos;
2798
+				continue;
2799
+			}
2800
+
2801
+			$var = $this->parse($string, $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2802
+			$len = $var[0];
2803
+			$var = $this->parse(str_replace('\\'.$first, $first, $string), $pos, null, false, ($curBlock === 'modifier' ? 'modifier' : ($prev === '`' ? 'delimited_string' : 'string')));
2804
+
2805
+			if ($prev === '`' && substr($string, $pos + $len, 1) === '`') {
2806
+				$string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos - 1, $len + 2);
2807
+			} else {
2808
+				$string = substr_replace($string, $first.'.'.$var[1].'.'.$first, $pos, $len);
2809
+			}
2810
+			$pos += strlen($var[1]) + 2;
2811
+			if ($this->debug) {
2812
+				echo 'STRING VAR REPLACEMENT DONE : '.$string."\n";
2813
+			}
2814
+		}
2815
+
2816
+		// handle modifiers
2817
+		// TODO Obsolete?
2818
+		$string = preg_replace_callback('#("|\')\.(.+?)\.\1((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\4|:[^`]*))*))+)#i', array($this, 'replaceModifiers'), $string);
2819
+
2820
+		// replace escaped dollar operators by unescaped ones if required
2821
+		if ($first === "'") {
2822
+			$string = str_replace('\\$', '$', $string);
2823
+		}
2824
+
2825
+		return $string;
2826
+	}
2827
+
2828
+	/**
2829
+	 * replaces the modifiers applied to a string or a variable.
2830
+	 *
2831
+	 * @param array  $m        the regex matches that must be array(1=>"double or single quotes enclosing a string, when applicable", 2=>"the string or var", 3=>"the modifiers matched")
2832
+	 * @param string $curBlock the current parser-block being processed
2833
+	 * @param null   $pointer
2834
+	 *
2835
+	 * @return string the input enclosed with various function calls according to the modifiers found
2836
+	 *
2837
+	 * @throws Dwoo_Compilation_Exception
2838
+	 * @throws Dwoo_Exception
2839
+	 */
2840
+	protected function replaceModifiers(array $m, $curBlock = null, &$pointer = null)
2841
+	{
2842
+		if ($this->debug) {
2843
+			echo 'PARSING MODIFIERS : '.$m[3]."\n";
2844
+		}
2845
+
2846
+		if ($pointer !== null) {
2847
+			$pointer += strlen($m[3]);
2848
+		}
2849
+		// remove first pipe
2850
+		$cmdstrsrc = substr($m[3], 1);
2851
+		// remove last quote if present
2852
+		if (substr($cmdstrsrc, -1, 1) === $m[1]) {
2853
+			$cmdstrsrc = substr($cmdstrsrc, 0, -1);
2854
+			$add = $m[1];
2855
+		}
2856
+
2857
+		$output = $m[2];
2858
+
2859
+		$continue = true;
2860
+		while (strlen($cmdstrsrc) > 0 && $continue) {
2861
+			if ($cmdstrsrc[0] === '|') {
2862
+				$cmdstrsrc = substr($cmdstrsrc, 1);
2863
+				continue;
2864
+			}
2865
+			if ($cmdstrsrc[0] === ' ' || $cmdstrsrc[0] === ';' || substr($cmdstrsrc, 0, strlen($this->rd)) === $this->rd) {
2866
+				if ($this->debug) {
2867
+					echo 'MODIFIER PARSING ENDED, RIGHT DELIMITER or ";" FOUND'."\n";
2868
+				}
2869
+				$continue = false;
2870
+				if ($pointer !== null) {
2871
+					$pointer -= strlen($cmdstrsrc);
2872
+				}
2873
+				break;
2874
+			}
2875
+			$cmdstr = $cmdstrsrc;
2876
+			$paramsep = ':';
2877
+			if (!preg_match('/^(@{0,2}[a-z_][a-z0-9_]*)(:)?/i', $cmdstr, $match)) {
2878
+				throw new Dwoo_Compilation_Exception($this, 'Invalid modifier name, started with : '.substr($cmdstr, 0, 10));
2879
+			}
2880
+			$paramspos = !empty($match[2]) ? strlen($match[1]) : false;
2881
+			$func = $match[1];
2882
+
2883
+			$state = 0;
2884
+			if ($paramspos === false) {
2885
+				$cmdstrsrc = substr($cmdstrsrc, strlen($func));
2886
+				$params = array();
2887
+				if ($this->debug) {
2888
+					echo 'MODIFIER ('.$func.') CALLED WITH NO PARAMS'."\n";
2889
+				}
2890
+			} else {
2891
+				$paramstr = substr($cmdstr, $paramspos + 1);
2892
+				if (substr($paramstr, -1, 1) === $paramsep) {
2893
+					$paramstr = substr($paramstr, 0, -1);
2894
+				}
2895
+
2896
+				$ptr = 0;
2897
+				$params = array();
2898
+				while ($ptr < strlen($paramstr)) {
2899
+					if ($this->debug) {
2900
+						echo 'MODIFIER ('.$func.') START PARAM PARSING WITH POINTER AT '.$ptr."\n";
2901
+					}
2902
+					if ($this->debug) {
2903
+						echo $paramstr.'--'.$ptr.'--'.strlen($paramstr).'--modifier'."\n";
2904
+					}
2905
+					$params = $this->parse($paramstr, $ptr, strlen($paramstr), $params, 'modifier', $ptr);
2906
+					if ($this->debug) {
2907
+						echo 'PARAM PARSED, POINTER AT '.$ptr."\n";
2908
+					}
2909
+
2910
+					if ($ptr >= strlen($paramstr)) {
2911
+						if ($this->debug) {
2912
+							echo 'PARAM PARSING ENDED, PARAM STRING CONSUMED'."\n";
2913
+						}
2914
+						break;
2915
+					}
2916
+
2917
+					if ($paramstr[$ptr] === ' ' || $paramstr[$ptr] === '|' || $paramstr[$ptr] === ';' || substr($paramstr, $ptr, strlen($this->rd)) === $this->rd) {
2918
+						if ($this->debug) {
2919
+							echo 'PARAM PARSING ENDED, " ", "|", RIGHT DELIMITER or ";" FOUND, POINTER AT '.$ptr."\n";
2920
+						}
2921
+						if ($paramstr[$ptr] !== '|') {
2922
+							$continue = false;
2923
+							if ($pointer !== null) {
2924
+								$pointer -= strlen($paramstr) - $ptr;
2925
+							}
2926
+						}
2927
+						++$ptr;
2928
+						break;
2929
+					}
2930
+					if ($ptr < strlen($paramstr) && $paramstr[$ptr] === ':') {
2931
+						++$ptr;
2932
+					}
2933
+				}
2934
+				$cmdstrsrc = substr($cmdstrsrc, strlen($func) + 1 + $ptr);
2935
+				$paramstr = substr($paramstr, 0, $ptr);
2936
+				foreach ($params as $k => $p) {
2937
+					if (is_array($p) && is_array($p[1])) {
2938
+						$state |= 2;
2939
+					} else {
2940
+						if (($state & 2) && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m)) {
2941
+							$params[$k] = array($m[2], array('true', 'true'));
2942
+						} else {
2943
+							if ($state & 2) {
2944
+								throw new Dwoo_Compilation_Exception($this, 'You can not use an unnamed parameter after a named one');
2945
+							}
2946
+							$state |= 1;
2947
+						}
2948
+					}
2949
+				}
2950
+			}
2951
+
2952
+			// check if we must use array_map with this plugin or not
2953
+			$mapped = false;
2954
+			if (substr($func, 0, 1) === '@') {
2955
+				$func = substr($func, 1);
2956
+				$mapped = true;
2957
+			}
2958
+
2959
+			$pluginType = $this->getPluginType($func);
2960
+
2961
+			if ($state & 2) {
2962
+				array_unshift($params, array('value', is_array($output) ? $output : array($output, $output)));
2963
+			} else {
2964
+				array_unshift($params, is_array($output) ? $output : array($output, $output));
2965
+			}
2966
+
2967
+			if ($pluginType & Dwoo_Core::NATIVE_PLUGIN) {
2968
+				$params = $this->mapParams($params, null, $state);
2969
+
2970
+				$params = $params['*'][0];
2971
+
2972
+				$params = self::implode_r($params);
2973
+
2974
+				if ($mapped) {
2975
+					$output = '$this->arrayMap(\''.$func.'\', array('.$params.'))';
2976
+				} else {
2977
+					$output = $func.'('.$params.')';
2978
+				}
2979
+			} elseif ($pluginType & Dwoo_Core::PROXY_PLUGIN) {
2980
+				$params = $this->mapParams($params, $this->getDwoo()->getPluginProxy()->getCallback($func), $state);
2981
+				foreach ($params as &$p) {
2982
+					$p = $p[0];
2983
+				}
2984
+				$output = call_user_func(array($this->dwoo->getPluginProxy(), 'getCode'), $func, $params);
2985
+			} elseif ($pluginType & Dwoo_Core::SMARTY_MODIFIER) {
2986
+				$params = $this->mapParams($params, null, $state);
2987
+				$params = $params['*'][0];
2988
+
2989
+				$params = self::implode_r($params);
2990
+
2991
+				if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
2992
+					$callback = $this->customPlugins[$func]['callback'];
2993
+					if (is_array($callback)) {
2994
+						if (is_object($callback[0])) {
2995
+							$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
2996
+						} else {
2997
+							$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
2998
+						}
2999
+					} elseif ($mapped) {
3000
+						$output = '$this->arrayMap(\''.$callback.'\', array('.$params.'))';
3001
+					} else {
3002
+						$output = $callback.'('.$params.')';
3003
+					}
3004
+				} elseif ($mapped) {
3005
+					$output = '$this->arrayMap(\'smarty_modifier_'.$func.'\', array('.$params.'))';
3006
+				} else {
3007
+					$output = 'smarty_modifier_'.$func.'('.$params.')';
3008
+				}
3009
+			} else {
3010
+				if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3011
+					$callback = $this->customPlugins[$func]['callback'];
3012
+					$pluginName = $callback;
3013
+				} else {
3014
+					$pluginName = 'Dwoo_Plugin_'.$func;
3015
+
3016
+					if ($pluginType & Dwoo_Core::CLASS_PLUGIN) {
3017
+						$callback = array($pluginName, ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? 'compile' : 'process');
3018
+					} else {
3019
+						$callback = $pluginName.(($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) ? '_compile' : '');
3020
+					}
3021
+				}
3022
+
3023
+				$params = $this->mapParams($params, $callback, $state);
3024
+
3025
+				foreach ($params as &$p) {
3026
+					$p = $p[0];
3027
+				}
3028
+
3029
+				if ($pluginType & Dwoo_Core::FUNC_PLUGIN) {
3030
+					if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
3031
+						if ($mapped) {
3032
+							throw new Dwoo_Compilation_Exception($this, 'The @ operator can not be used on compiled plugins.');
3033
+						}
3034
+						if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3035
+							$funcCompiler = $this->customPlugins[$func]['callback'];
3036
+						} else {
3037
+							$funcCompiler = 'Dwoo_Plugin_'.$func.'_compile';
3038
+						}
3039
+						array_unshift($params, $this);
3040
+						$output = call_user_func_array($funcCompiler, $params);
3041
+					} else {
3042
+						array_unshift($params, '$this');
3043
+
3044
+						$params = self::implode_r($params);
3045
+						if ($mapped) {
3046
+							$output = '$this->arrayMap(\''.$pluginName.'\', array('.$params.'))';
3047
+						} else {
3048
+							$output = $pluginName.'('.$params.')';
3049
+						}
3050
+					}
3051
+				} else {
3052
+					if ($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) {
3053
+						if ($mapped) {
3054
+							throw new Dwoo_Compilation_Exception($this, 'The @ operator can not be used on compiled plugins.');
3055
+						}
3056
+						if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3057
+							$callback = $this->customPlugins[$func]['callback'];
3058
+							if (!is_array($callback)) {
3059
+								if (!method_exists($callback, 'compile')) {
3060
+									throw new Dwoo_Exception('Custom plugin '.$func.' must implement the "compile" method to be compilable, or you should provide a full callback to the method to use');
3061
+								}
3062
+								if (($ref = new ReflectionMethod($callback, 'compile')) && $ref->isStatic()) {
3063
+									$funcCompiler = array($callback, 'compile');
3064
+								} else {
3065
+									$funcCompiler = array(new $callback(), 'compile');
3066
+								}
3067
+							} else {
3068
+								$funcCompiler = $callback;
3069
+							}
3070
+						} else {
3071
+							$funcCompiler = array('Dwoo_Plugin_'.$func, 'compile');
3072
+							array_unshift($params, $this);
3073
+						}
3074
+						$output = call_user_func_array($funcCompiler, $params);
3075
+					} else {
3076
+						$params = self::implode_r($params);
3077
+
3078
+						if ($pluginType & Dwoo_Core::CUSTOM_PLUGIN) {
3079
+							if (is_object($callback[0])) {
3080
+								$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
3081
+							} else {
3082
+								$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
3083
+							}
3084
+						} elseif ($mapped) {
3085
+							$output = '$this->arrayMap(array($this->getObjectPlugin(\'Dwoo_Plugin_'.$func.'\'), \'process\'), array('.$params.'))';
3086
+						} else {
3087
+							$output = '$this->classCall(\''.$func.'\', array('.$params.'))';
3088
+						}
3089
+					}
3090
+				}
3091
+			}
3092
+		}
3093
+
3094
+		if ($curBlock === 'namedparam') {
3095
+			return array($output, $output);
3096
+		} elseif ($curBlock === 'var' || $m[1] === null) {
3097
+			return $output;
3098
+		} elseif ($curBlock === 'string' || $curBlock === 'root') {
3099
+			return $m[1].'.'.$output.'.'.$m[1].(isset($add) ? $add : null);
3100
+		}
3101
+
3102
+		return '';
3103
+	}
3104
+
3105
+	/**
3106
+	 * recursively implodes an array in a similar manner as var_export() does but with some tweaks
3107
+	 * to handle pre-compiled values and the fact that we do not need to enclose everything with
3108
+	 * "array" and do not require top-level keys to be displayed.
3109
+	 *
3110
+	 * @param array $params        the array to implode
3111
+	 * @param bool  $recursiveCall if set to true, the function outputs key names for the top level
3112
+	 *
3113
+	 * @return string the imploded array
3114
+	 */
3115
+	public static function implode_r(array $params, $recursiveCall = false)
3116
+	{
3117
+		$out = '';
3118
+		foreach ($params as $k => $p) {
3119
+			if (is_array($p)) {
3120
+				$out2 = 'array(';
3121
+				foreach ($p as $k2 => $v) {
3122
+					$out2 .= var_export($k2, true).' => '.(is_array($v) ? 'array('.self::implode_r($v, true).')' : $v).', ';
3123
+				}
3124
+				$p = rtrim($out2, ', ').')';
3125
+			}
3126
+			if ($recursiveCall) {
3127
+				$out .= var_export($k, true).' => '.$p.', ';
3128
+			} else {
3129
+				$out .= $p.', ';
3130
+			}
3131
+		}
3132
+
3133
+		return rtrim($out, ', ');
3134
+	}
3135
+
3136
+	/**
3137
+	 * returns the plugin type of a plugin and adds it to the used plugins array if required.
3138
+	 *
3139
+	 * @param string $name plugin name, as found in the template
3140
+	 *
3141
+	 * @return int type as a multi bit flag composed of the Dwoo plugin types constants
3142
+	 *
3143
+	 * @throws Dwoo_Exception
3144
+	 * @throws Dwoo_Security_Exception
3145
+	 * @throws Exception
3146
+	 */
3147
+	protected function getPluginType($name)
3148
+	{
3149
+		$pluginType = -1;
3150
+
3151
+		if (($this->securityPolicy === null && (function_exists($name) || strtolower($name) === 'isset' || strtolower($name) === 'empty')) ||
3152
+			($this->securityPolicy !== null && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) !== false)) {
3153
+			$phpFunc = true;
3154
+		} elseif ($this->securityPolicy !== null && function_exists($name) && array_key_exists(strtolower($name), $this->securityPolicy->getAllowedPhpFunctions()) === false) {
3155
+			throw new Dwoo_Security_Exception('Call to a disallowed php function : '.$name);
3156
+		}
3157
+
3158
+		while ($pluginType <= 0) {
3159
+			if (isset($this->templatePlugins[$name])) {
3160
+				$pluginType = Dwoo_Core::TEMPLATE_PLUGIN | Dwoo_Core::COMPILABLE_PLUGIN;
3161
+			} elseif (isset($this->customPlugins[$name])) {
3162
+				$pluginType = $this->customPlugins[$name]['type'] | Dwoo_Core::CUSTOM_PLUGIN;
3163
+			} elseif (class_exists('Dwoo_Plugin_'.$name) !== false) {
3164
+				if (is_subclass_of('Dwoo_Plugin_'.$name, 'Dwoo_Block_Plugin')) {
3165
+					$pluginType = Dwoo_Core::BLOCK_PLUGIN;
3166
+				} else {
3167
+					$pluginType = Dwoo_Core::CLASS_PLUGIN;
3168
+				}
3169
+				$interfaces = class_implements('Dwoo_Plugin_'.$name);
3170
+				if (in_array('Dwoo_ICompilable', $interfaces) !== false || in_array('Dwoo_ICompilable_Block', $interfaces) !== false) {
3171
+					$pluginType |= Dwoo_Core::COMPILABLE_PLUGIN;
3172
+				}
3173
+			} elseif (function_exists('Dwoo_Plugin_'.$name) !== false) {
3174
+				$pluginType = Dwoo_Core::FUNC_PLUGIN;
3175
+			} elseif (function_exists('Dwoo_Plugin_'.$name.'_compile')) {
3176
+				$pluginType = Dwoo_Core::FUNC_PLUGIN | Dwoo_Core::COMPILABLE_PLUGIN;
3177
+			} elseif (function_exists('smarty_modifier_'.$name) !== false) {
3178
+				$pluginType = Dwoo_Core::SMARTY_MODIFIER;
3179
+			} elseif (function_exists('smarty_function_'.$name) !== false) {
3180
+				$pluginType = Dwoo_Core::SMARTY_FUNCTION;
3181
+			} elseif (function_exists('smarty_block_'.$name) !== false) {
3182
+				$pluginType = Dwoo_Core::SMARTY_BLOCK;
3183
+			} else {
3184
+				if ($pluginType === -1) {
3185
+					try {
3186
+						$this->dwoo->getLoader()->loadPlugin($name, isset($phpFunc) === false);
3187
+					} catch (Exception $e) {
3188
+						if (isset($phpFunc)) {
3189
+							$pluginType = Dwoo_Core::NATIVE_PLUGIN;
3190
+						} elseif (is_object($this->dwoo->getPluginProxy()) && $this->dwoo->getPluginProxy()->handles($name)) {
3191
+							$pluginType = Dwoo_Core::PROXY_PLUGIN;
3192
+							break;
3193
+						} else {
3194
+							throw $e;
3195
+						}
3196
+					}
3197
+				} else {
3198
+					throw new Dwoo_Exception('Plugin "'.$name.'" could not be found');
3199
+				}
3200
+				++$pluginType;
3201
+			}
3202
+		}
3203
+
3204
+		if (($pluginType & Dwoo_Core::COMPILABLE_PLUGIN) === 0 && ($pluginType & Dwoo_Core::NATIVE_PLUGIN) === 0 && ($pluginType & Dwoo_Core::PROXY_PLUGIN) === 0) {
3205
+			$this->addUsedPlugin($name, $pluginType);
3206
+		}
3207
+
3208
+		return $pluginType;
3209
+	}
3210
+
3211
+	/**
3212
+	 * allows a plugin to load another one at compile time, this will also mark
3213
+	 * it as used by this template so it will be loaded at runtime (which can be
3214
+	 * useful for compiled plugins that rely on another plugin when their compiled
3215
+	 * code runs).
3216
+	 *
3217
+	 * @param string $name the plugin name
3218
+	 */
3219
+	public function loadPlugin($name)
3220
+	{
3221
+		$this->getPluginType($name);
3222
+	}
3223
+
3224
+	/**
3225
+	 * runs htmlentities over the matched <?php ?> blocks when the security policy enforces that.
3226
+	 *
3227
+	 * @param array $match matched php block
3228
+	 *
3229
+	 * @return string the htmlentities-converted string
3230
+	 */
3231
+	protected function phpTagEncodingHelper($match)
3232
+	{
3233
+		return htmlspecialchars($match[0]);
3234
+	}
3235
+
3236
+	/**
3237
+	 * maps the parameters received from the template onto the parameters required by the given callback.
3238
+	 *
3239
+	 * @param array    $params   the array of parameters
3240
+	 * @param callback $callback the function or method to reflect on to find out the required parameters
3241
+	 * @param int      $callType the type of call in the template, 0 = no params, 1 = php-style call, 2 = named parameters call
3242
+	 * @param array    $map      the parameter map to use, if not provided it will be built from the callback
3243
+	 *
3244
+	 * @return array parameters sorted in the correct order with missing optional parameters filled
3245
+	 *
3246
+	 * @throws Dwoo_Compilation_Exception
3247
+	 */
3248
+	protected function mapParams(array $params, $callback, $callType = 2, $map = null)
3249
+	{
3250
+		if (!$map) {
3251
+			$map = $this->getParamMap($callback);
3252
+		}
3253
+
3254
+		$paramlist = array();
3255
+
3256
+		// transforms the parameter array from (x=>array('paramname'=>array(values))) to (paramname=>array(values))
3257
+		$ps = array();
3258
+		foreach ($params as $p) {
3259
+			if (is_array($p[1])) {
3260
+				$ps[$p[0]] = $p[1];
3261
+			} else {
3262
+				$ps[] = $p;
3263
+			}
3264
+		}
3265
+
3266
+		// loops over the param map and assigns values from the template or default value for unset optional params
3267
+		while (list($k, $v) = each($map)) {
3268
+			if ($v[0] === '*') {
3269
+				// "rest" array parameter, fill every remaining params in it and then break
3270
+				if (count($ps) === 0) {
3271
+					if ($v[1] === false) {
3272
+						throw new Dwoo_Compilation_Exception($this, 'Rest argument missing for '.str_replace(array('Dwoo_Plugin_', '_compile'), '', (is_array($callback) ? $callback[0] : $callback)));
3273
+					} else {
3274
+						break;
3275
+					}
3276
+				}
3277
+				$tmp = array();
3278
+				$tmp2 = array();
3279
+				$tmp3 = array();
3280
+				foreach ($ps as $i => $p) {
3281
+					$tmp[$i] = $p[0];
3282
+					$tmp2[$i] = $p[1];
3283
+					$tmp3[$i] = isset($p[2]) ? $p[2] : 0;
3284
+					unset($ps[$i]);
3285
+				}
3286
+				$paramlist[$v[0]] = array($tmp, $tmp2, $tmp3);
3287
+				unset($tmp, $tmp2, $i, $p);
3288
+				break;
3289
+			} elseif (isset($ps[$v[0]])) {
3290
+				// parameter is defined as named param
3291
+				$paramlist[$v[0]] = $ps[$v[0]];
3292
+				unset($ps[$v[0]]);
3293
+			} elseif (isset($ps[$k])) {
3294
+				// parameter is defined as ordered param
3295
+				$paramlist[$v[0]] = $ps[$k];
3296
+				unset($ps[$k]);
3297
+			} elseif ($v[1] === false) {
3298
+				// parameter is not defined and not optional, throw error
3299
+				if (is_array($callback)) {
3300
+					if (is_object($callback[0])) {
3301
+						$name = get_class($callback[0]).'::'.$callback[1];
3302
+					} else {
3303
+						$name = $callback[0];
3304
+					}
3305
+				} else {
3306
+					$name = $callback;
3307
+				}
3308
+
3309
+				throw new Dwoo_Compilation_Exception($this, 'Argument '.$k.'/'.$v[0].' missing for '.str_replace(array('Dwoo_Plugin_', '_compile'), '', $name));
3310
+			} elseif ($v[2] === null) {
3311
+				// enforce lowercased null if default value is null (php outputs NULL with var export)
3312
+				$paramlist[$v[0]] = array('null', null, self::T_NULL);
3313
+			} else {
3314
+				// outputs default value with var_export
3315
+				$paramlist[$v[0]] = array(var_export($v[2], true), $v[2]);
3316
+			}
3317
+		}
3318
+
3319
+		if (count($ps)) {
3320
+			foreach ($ps as $i => $p) {
3321
+				array_push($paramlist, $p);
3322
+			}
3323
+		}
3324
+
3325
+		return $paramlist;
3326
+	}
3327
+
3328
+	/**
3329
+	 * returns the parameter map of the given callback, it filters out entries typed as Dwoo and Dwoo_Compiler and turns the rest parameter into a "*".
3330
+	 *
3331
+	 * @param callback $callback the function/method to reflect on
3332
+	 *
3333
+	 * @return array processed parameter map
3334
+	 */
3335
+	protected function getParamMap($callback)
3336
+	{
3337
+		if (is_null($callback)) {
3338
+			return array(array('*', true));
3339
+		}
3340
+		if (is_array($callback)) {
3341
+			$ref = new ReflectionMethod($callback[0], $callback[1]);
3342
+		} else {
3343
+			$ref = new ReflectionFunction($callback);
3344
+		}
3345
+
3346
+		$out = array();
3347
+		foreach ($ref->getParameters() as $param) {
3348
+			if (($class = $param->getClass()) !== null && ($class->name === 'Dwoo' || $class->name === 'Dwoo_Core')) {
3349
+				continue;
3350
+			}
3351
+			if (($class = $param->getClass()) !== null && $class->name === 'Dwoo_Compiler') {
3352
+				continue;
3353
+			}
3354
+			if ($param->getName() === 'rest' && $param->isArray() === true) {
3355
+				$out[] = array('*', $param->isOptional(), null);
3356
+				continue;
3357
+			}
3358
+			$out[] = array($param->getName(), $param->isOptional(), $param->isOptional() ? $param->getDefaultValue() : null);
3359
+		}
3360
+
3361
+		return $out;
3362
+	}
3363
+
3364
+	/**
3365
+	 * returns a default instance of this compiler, used by default by all Dwoo templates that do not have a
3366
+	 * specific compiler assigned and when you do not override the default compiler factory function.
3367
+	 *
3368
+	 * @see Dwoo_Core::setDefaultCompilerFactory()
3369
+	 *
3370
+	 * @return Dwoo_Compiler
3371
+	 */
3372
+	public static function compilerFactory()
3373
+	{
3374
+		if (self::$instance === null) {
3375
+			new self();
3376
+		}
3377
+
3378
+		return self::$instance;
3379
+	}
3380 3380
 }
Please login to merge, or discard this patch.