1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
<?php
/**
* Smarty Internal Plugin Smarty Template Compiler Base
* This file contains the basic classes and methods for compiling Smarty templates with lexer/parser
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Class SmartyTemplateCompiler
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCompilerBase
{
/**
* Lexer class name
*
* @var string
*/
public $lexer_class;
/**
* Parser class name
*
* @var string
*/
public $parser_class;
/**
* array of vars which can be compiled in local scope
*
* @var array
*/
public $local_var = array();
/**
* array of callbacks called when the normal compile process of template is finished
*
* @var array
*/
public $postCompileCallbacks = array();
/**
* prefix code
*
* @var string
*/
public $prefixCompiledCode = '';
/**
* postfix code
*
* @var string
*/
public $postfixCompiledCode = '';
/**
* Initialize compiler
*
* @param string $lexer_class class name
* @param string $parser_class class name
* @param Smarty $smarty global instance
*/
public function __construct($lexer_class, $parser_class, Smarty $smarty)
{
parent::__construct($smarty);
// get required plugins
$this->lexer_class = $lexer_class;
$this->parser_class = $parser_class;
}
/**
* method to compile a Smarty template
*
* @param mixed $_content template source
* @param bool $isTemplateSource
*
* @return bool true if compiling succeeded, false if it failed
* @throws \SmartyCompilerException
*/
protected function doCompile($_content, $isTemplateSource = false)
{
/* here is where the compiling takes place. Smarty
tags in the templates are replaces with PHP code,
then written to compiled files. */
// init the lexer/parser to compile the template
$this->parser =
new $this->parser_class(new $this->lexer_class(str_replace(array("\r\n", "\r"), "\n", $_content), $this),
$this);
if ($isTemplateSource && $this->template->caching) {
$this->parser->insertPhpCode("<?php\n\$_smarty_tpl->compiled->nocache_hash = '{$this->nocache_hash}';\n?>\n");
}
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('ASCII');
} else {
$mbEncoding = null;
}
if ($this->smarty->_parserdebug) {
$this->parser->PrintTrace();
$this->parser->lex->PrintTrace();
}
// get tokens from lexer and parse them
while ($this->parser->lex->yylex()) {
if ($this->smarty->_parserdebug) {
echo "<pre>Line {$this->parser->lex->line} Parsing {$this->parser->yyTokenName[$this->parser->lex->token]} Token " .
htmlentities($this->parser->lex->value) . "</pre>";
}
$this->parser->doParse($this->parser->lex->token, $this->parser->lex->value);
}
// finish parsing process
$this->parser->doParse(0, 0);
if ($mbEncoding) {
mb_internal_encoding($mbEncoding);
}
// check for unclosed tags
if (count($this->_tag_stack) > 0) {
// get stacked info
list($openTag, $_data) = array_pop($this->_tag_stack);
$this->trigger_template_error("unclosed {$this->smarty->left_delimiter}" . $openTag .
"{$this->smarty->right_delimiter} tag");
}
// call post compile callbacks
foreach ($this->postCompileCallbacks as $cb) {
$parameter = $cb;
$parameter[ 0 ] = $this;
call_user_func_array($cb[ 0 ], $parameter);
}
// return compiled code
return $this->prefixCompiledCode . $this->parser->retvalue . $this->postfixCompiledCode;
}
/**
* Register a post compile callback
* - when the callback is called after template compiling the compiler object will be inserted as first parameter
*
* @param callback $callback
* @param array $parameter optional parameter array
* @param string $key optional key for callback
* @param bool $replace if true replace existing keyed callback
*
*/
public function registerPostCompileCallback($callback, $parameter = array(), $key = null, $replace = false)
{
array_unshift($parameter, $callback);
if (isset($key)) {
if ($replace || !isset($this->postCompileCallbacks[ $key ])) {
$this->postCompileCallbacks[ $key ] = $parameter;
}
} else {
$this->postCompileCallbacks[] = $parameter;
}
}
/**
* Remove a post compile callback
*
* @param string $key callback key
*/
public function unregisterPostCompileCallback($key)
{
unset($this->postCompileCallbacks[ $key ]);
}
}
|