1: <?php
2: /**
3: * Smarty Internal Plugin Config File Compiler
4: * This is the config file compiler class. It calls the lexer and parser to
5: * perform the compiling.
6: *
7: * @package Smarty
8: * @subpackage Config
9: * @author Uwe Tews
10: */
11:
12: /**
13: * Main config file compiler class
14: *
15: * @package Smarty
16: * @subpackage Config
17: */
18: class Smarty_Internal_Config_File_Compiler
19: {
20: /**
21: * Lexer class name
22: *
23: * @var string
24: */
25: public $lexer_class;
26:
27: /**
28: * Parser class name
29: *
30: * @var string
31: */
32: public $parser_class;
33:
34: /**
35: * Lexer object
36: *
37: * @var object
38: */
39: public $lex;
40:
41: /**
42: * Parser object
43: *
44: * @var object
45: */
46: public $parser;
47:
48: /**
49: * Smarty object
50: *
51: * @var Smarty object
52: */
53: public $smarty;
54:
55: /**
56: * Smarty object
57: *
58: * @var Smarty_Internal_Template object
59: */
60: public $template;
61:
62: /**
63: * Compiled config data sections and variables
64: *
65: * @var array
66: */
67: public $config_data = array();
68:
69: /**
70: * compiled config data must always be written
71: *
72: * @var bool
73: */
74: public $write_compiled_code = true;
75:
76: /**
77: * Initialize compiler
78: *
79: * @param string $lexer_class class name
80: * @param string $parser_class class name
81: * @param Smarty $smarty global instance
82: */
83: public function __construct($lexer_class, $parser_class, Smarty $smarty)
84: {
85: $this->smarty = $smarty;
86: // get required plugins
87: $this->lexer_class = $lexer_class;
88: $this->parser_class = $parser_class;
89: $this->smarty = $smarty;
90: $this->config_data[ 'sections' ] = array();
91: $this->config_data[ 'vars' ] = array();
92: }
93:
94: /**
95: * Method to compile Smarty config source.
96: *
97: * @param Smarty_Internal_Template $template
98: *
99: * @return bool true if compiling succeeded, false if it failed
100: * @throws \SmartyException
101: */
102: public function compileTemplate(Smarty_Internal_Template $template)
103: {
104: $this->template = $template;
105: $this->template->compiled->file_dependency[ $this->template->source->uid ] =
106: array(
107: $this->template->source->filepath,
108: $this->template->source->getTimeStamp(),
109: $this->template->source->type
110: );
111: if ($this->smarty->debugging) {
112: if (!isset($this->smarty->_debug)) {
113: $this->smarty->_debug = new Smarty_Internal_Debug();
114: }
115: $this->smarty->_debug->start_compile($this->template);
116: }
117: // init the lexer/parser to compile the config file
118: /* @var Smarty_Internal_ConfigFileLexer $this->lex */
119: $this->lex = new $this->lexer_class(
120: str_replace(
121: array(
122: "\r\n",
123: "\r"
124: ),
125: "\n",
126: $template->source->getContent()
127: ) . "\n",
128: $this
129: );
130: /* @var Smarty_Internal_ConfigFileParser $this->parser */
131: $this->parser = new $this->parser_class($this->lex, $this);
132: if (function_exists('mb_internal_encoding')
133: && function_exists('ini_get')
134: && ((int)ini_get('mbstring.func_overload')) & 2
135: ) {
136: $mbEncoding = mb_internal_encoding();
137: mb_internal_encoding('ASCII');
138: } else {
139: $mbEncoding = null;
140: }
141: if ($this->smarty->_parserdebug) {
142: $this->parser->PrintTrace();
143: }
144: // get tokens from lexer and parse them
145: while ($this->lex->yylex()) {
146: if ($this->smarty->_parserdebug) {
147: echo "<br>Parsing {$this->parser->yyTokenName[$this->lex->token]} Token {$this->lex->value} Line {$this->lex->line} \n";
148: }
149: $this->parser->doParse($this->lex->token, $this->lex->value);
150: }
151: // finish parsing process
152: $this->parser->doParse(0, 0);
153: if ($mbEncoding) {
154: mb_internal_encoding($mbEncoding);
155: }
156: if ($this->smarty->debugging) {
157: $this->smarty->_debug->end_compile($this->template);
158: }
159: // template header code
160: $template_header = sprintf(
161: "<?php /* Smarty version %s, created on %s\n compiled from '%s' */ ?>\n",
162: Smarty::SMARTY_VERSION,
163: date("Y-m-d H:i:s"),
164: str_replace('*/', '* /' , $this->template->source->filepath)
165: );
166: $code = '<?php $_smarty_tpl->smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' .
167: var_export($this->config_data, true) . '); ?>';
168: return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code);
169: }
170:
171: /**
172: * display compiler error messages without dying
173: * If parameter $args is empty it is a parser detected syntax error.
174: * In this case the parser is called to obtain information about expected tokens.
175: * If parameter $args contains a string this is used as error message
176: *
177: * @param string $args individual error message or null
178: *
179: * @throws SmartyCompilerException
180: */
181: public function trigger_config_file_error($args = null)
182: {
183: // get config source line which has error
184: $line = $this->lex->line;
185: if (isset($args)) {
186: // $line--;
187: }
188: $match = preg_split("/\n/", $this->lex->data);
189: $error_text =
190: "Syntax error in config file '{$this->template->source->filepath}' on line {$line} '{$match[$line - 1]}' ";
191: if (isset($args)) {
192: // individual error message
193: $error_text .= $args;
194: } else {
195: // expected token from parser
196: foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) {
197: $exp_token = $this->parser->yyTokenName[ $token ];
198: if (isset($this->lex->smarty_token_names[ $exp_token ])) {
199: // token type from lexer
200: $expect[] = '"' . $this->lex->smarty_token_names[ $exp_token ] . '"';
201: } else {
202: // otherwise internal token name
203: $expect[] = $this->parser->yyTokenName[ $token ];
204: }
205: }
206: // output parser error message
207: $error_text .= ' - Unexpected "' . $this->lex->value . '", expected one of: ' . implode(' , ', $expect);
208: }
209: throw new SmartyCompilerException($error_text);
210: }
211: }
212: