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 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
<?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')
&& function_exists('ini_get')
&& ((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 ]);
}
}
|