1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** * ************************************************ |
4
|
|
|
* Image CMS Template Engine (Mabilis TPL) |
5
|
|
|
* |
6
|
|
|
* Simple template engine for Image CMS based on regular expressions search and replace. |
7
|
|
|
* |
8
|
|
|
* @author <[email protected]> |
9
|
|
|
* @version 0.3 PHP5 |
10
|
|
|
* ************************************************ */ |
11
|
|
|
class Mabilis_Compiler extends Mabilis |
12
|
|
|
{ |
13
|
|
|
|
14
|
|
|
public $config = NULL; |
15
|
|
|
|
16
|
|
|
// Array with functions that are in ./functions/ folder |
17
|
|
|
// Each of this function will be renamed as tpl_$func |
18
|
|
|
private $func_prefix = 'func_'; |
19
|
|
|
|
20
|
|
|
private $func_array = [ |
21
|
|
|
'counter', |
22
|
|
|
'truncate', |
23
|
|
|
]; |
24
|
|
|
|
25
|
|
|
// Constructor |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @param Mabilis_Config $config_obj |
29
|
|
|
*/ |
30
|
|
|
public function __construct(&$config_obj) { |
31
|
|
|
$this->config = &$config_obj; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Compile template file to php code |
36
|
|
|
* |
37
|
|
|
* @access public |
38
|
|
|
* @param string $file filename |
39
|
|
|
* @return bool |
40
|
|
|
*/ |
41
|
|
|
public function compile($file) { |
42
|
|
|
// Read template data |
43
|
|
|
$tpl_data = $this->read_tpl_file($file); |
44
|
|
|
|
45
|
|
|
if ($tpl_data === FALSE) { |
46
|
|
|
$this->error('File ' . $file . ' not found;'); |
47
|
|
|
return FALSE; |
48
|
|
|
} else { |
49
|
|
|
|
50
|
|
|
$curFilePath = dirname(realpath($file)); |
51
|
|
|
|
52
|
|
|
$include_functions = []; |
53
|
|
|
|
54
|
|
|
// Replace all {$variable} as echo $variable |
55
|
|
|
//$tpl_data = preg_replace('/({\s*)\s*(\$\w*?)\s*(\s*\})/', '$1 echo $2;$3', $tpl_data); |
56
|
|
|
$tpl_data = preg_replace('/\{(\$\w*?)\}/', '{ echo $1; }', $tpl_data); |
57
|
|
|
|
58
|
|
|
// For arrays like $arr['1']['2'] |
59
|
|
|
$tpl_data = preg_replace('/\{(\$.*?\[.*?\])\}/', '{ echo $1; }', $tpl_data); |
60
|
|
|
|
61
|
|
|
// Replace $arr.key to $arr['key'] |
62
|
|
|
$tpl_data = preg_replace('/\{(\$\w*)?\.(\w*)?\.(\w*)\}/', '{ echo $1[\'$2\'][\'$3\']; }', $tpl_data); |
63
|
|
|
$tpl_data = preg_replace('/\{(\$\w*)?\.(\w*)\}/', '{ echo $1[\'$2\']; }', $tpl_data); |
64
|
|
|
|
65
|
|
|
$tpl_data = preg_replace('/\{(.*?)(\$\w*)\.(\w*)\.(\w*)(.*?)\s*\}/', '{ $1 $2[\'$3\'][\'$4\'] $5 }', $tpl_data); |
66
|
|
|
|
67
|
|
|
for ($i = 0; $i < 3; $i++) { |
68
|
|
|
$tpl_data = preg_replace('/\{(.*?)(\$\w*)\.(\w*)(.*?)\}/', '{ $1 $2[\'$3\'] $4 }', $tpl_data); //mother of god |
69
|
|
|
} |
70
|
|
|
// Find end replace template functions |
71
|
|
|
foreach ($this->func_array as $func) { |
72
|
|
|
// Replace { function(params) } as { echo functon(params); } |
73
|
|
View Code Duplication |
if (preg_match_all('/\{\s*(' . $func . ')\s*(\(.*?\))\s*\}/', $tpl_data, $_match) > 0) { |
74
|
|
|
// Function found |
75
|
|
|
$tpl_data = preg_replace('/\{\s*(' . $func . ')\s*(\(.*?\))\s*\}/', '{ echo ' . $this->func_prefix . '$1 $2; }', $tpl_data); |
76
|
|
|
|
77
|
|
|
// Include function |
78
|
|
|
$include_functions[$func] = TRUE; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
// If we want to assign function result to variable |
82
|
|
|
// tpl code { $var = function(params) } |
83
|
|
View Code Duplication |
if (preg_match_all('/\{\s*\$.*?\=\s*(' . $func . ')\s*(\(.*?\))\s*\}/', $tpl_data, $_match) > 0) { |
84
|
|
|
// Function found |
85
|
|
|
$tpl_data = preg_replace('/\{\s*(\$.*?)\=\s*(' . $func . ')\s*(\(.*?\))\s*\}/', '{ $1 = ' . $this->func_prefix . '$2 $3; }', $tpl_data); |
86
|
|
|
|
87
|
|
|
// Include function |
88
|
|
|
$include_functions[$func] = TRUE; |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
// PHP functions |
93
|
|
|
$tpl_data = preg_replace('/\{\s*(\w*)\s*(\(.*?\))\s*\}/', '{ echo $1 $2; }', $tpl_data); |
94
|
|
|
|
95
|
|
|
// Replace PHP tags |
96
|
|
|
$tpl_data = preg_replace('/<\?php(.*?)\?>/si', '<!user_php$1user_php!>', $tpl_data); |
97
|
|
|
|
98
|
|
|
// Replace literal tags |
99
|
|
|
$tpl_data = preg_replace('/\{\s*literal\s*\}(.*?)\{\s*\/literal\}/si', '<!user_literal$1user_literal!>', $tpl_data); |
100
|
|
|
|
101
|
|
|
// Replace delimiters to php tags |
102
|
|
|
$tpl_data = preg_replace('/(\s*)\{(\s*)/', '$1<?php$2', $tpl_data); |
103
|
|
|
$tpl_data = preg_replace('/(\s*)\}(\s*)/', '$1?>$2', $tpl_data); |
104
|
|
|
|
105
|
|
|
/* * **************************************** |
106
|
|
|
* Functions |
107
|
|
|
* Replace all between php tags to php code |
108
|
|
|
* **************************************** */ |
109
|
|
|
|
110
|
|
|
// If |
111
|
|
|
$tpl_data = preg_replace('/<\?php\s*\/if\s*\?>/', '<?php endif; ?>', $tpl_data); |
112
|
|
|
$tpl_data = preg_replace('/<\?php.*elseif (.*).*\?>/', '<?php elseif ($1): ?>', $tpl_data); |
113
|
|
|
$tpl_data = preg_replace('/<\?php\s*?(if)\s*(.*?)\s*(\?>)/', '<?php $1($2): ?>', $tpl_data); |
114
|
|
|
|
115
|
|
|
// Foreach |
116
|
|
|
$tpl_data = preg_replace('/<\?php\s*\/foreach\s*\?>/', '<?php }} ?>', $tpl_data); |
117
|
|
|
$tpl_data = preg_replace('/<\?php\s*(foreach)\s*(\$.*?)\s*as\s*(\$.*?)\s*\?>/', '<?php if(is_true_array($2)){ $1 ($2 as $3){ ?>', $tpl_data); |
118
|
|
|
$tpl_data = preg_replace('/<\?php\s*(foreach)\s*(.*?)\s*as\s*(\$.*?)\s*\?>/', "<?php \$result = $2; \n if(is_true_array(\$result)){ $1 (\$result as $3){ ?>", $tpl_data); |
119
|
|
|
|
120
|
|
|
// For |
121
|
|
|
$tpl_data = preg_replace('/<\?php\s*\/for\s*\?>/', '<?php } ?>', $tpl_data); |
122
|
|
|
$tpl_data = preg_replace('/<\?php\s*(for) (.*?)\s*\?>/', '<?php $1($2){?>', $tpl_data); |
123
|
|
|
|
124
|
|
|
// Switch |
125
|
|
|
$tpl_data = preg_replace('/<\?php\s*\/switch\s*\?>/', '<?php } ?>', $tpl_data); |
126
|
|
|
$tpl_data = preg_replace('/<\?php\s*(switch)(.*)\?>/', '<?php $1($2){ default: break; ?>', $tpl_data); |
127
|
|
|
|
128
|
|
|
// While |
129
|
|
|
$tpl_data = preg_replace('/<\?php.*\/while\s*?>/', '<?php } ?>', $tpl_data); |
130
|
|
|
$tpl_data = preg_replace('/<\?php.*while(.*).*\?>/', '<?php while ($1){ ?>', $tpl_data); |
131
|
|
|
|
132
|
|
|
// Include_tpl |
133
|
|
|
$tpl_data = preg_replace_callback( |
134
|
|
|
'/<\?php.*include\_tpl.*\((.*)\).*\?>/', |
135
|
|
|
function ($arr) use ($curFilePath) { |
136
|
|
|
return '<?php $this->include_tpl(' . $arr[1] . ', \'' . $curFilePath . '\'); ?>'; |
137
|
|
|
}, |
138
|
|
|
$tpl_data |
139
|
|
|
); |
140
|
|
|
|
141
|
|
|
$tpl_data = preg_replace_callback( |
142
|
|
|
'/<\?php.*include\_shop\_tpl.*\((.*)\).*\?>/', |
143
|
|
|
function ($arr) use ($curFilePath) { |
144
|
|
|
return '<?php $this->include_shop_tpl(' . $arr[1] . ', \'' . $curFilePath . '\'); ?>'; |
145
|
|
|
}, |
146
|
|
|
$tpl_data |
147
|
|
|
); |
148
|
|
|
|
149
|
|
|
preg_match_all('/<\!user_php(.*)\s*user_php\!>/', $tpl_data, $_match); |
150
|
|
|
|
151
|
|
|
$php_patterns = [ |
152
|
|
|
'/<\?php/', |
153
|
|
|
'/\?>/', |
154
|
|
|
]; |
155
|
|
|
|
156
|
|
View Code Duplication |
foreach ($_match[0] as $k => $v) { |
157
|
|
|
$text = preg_replace($php_patterns, $this->config->delimiters, $v); |
158
|
|
|
$tpl_data = str_replace($v, $text, $tpl_data); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
$tpl_data = preg_replace('/\s*<\!user_php/', '<?php', $tpl_data); |
162
|
|
|
$tpl_data = preg_replace('/user_php!>/', '?>', $tpl_data); |
163
|
|
|
|
164
|
|
|
// Replace php tags to { } between literal tags |
165
|
|
|
preg_match_all('/<\!user_literal(.*?)user_literal\!>/si', $tpl_data, $_match); |
166
|
|
|
|
167
|
|
|
$php_patterns = [ |
168
|
|
|
'/<\?php/', |
169
|
|
|
'/\?>/', |
170
|
|
|
]; |
171
|
|
|
|
172
|
|
View Code Duplication |
foreach ($_match[0] as $k => $v) { |
173
|
|
|
$text = preg_replace($php_patterns, $this->config->delimiters, $v); |
174
|
|
|
$tpl_data = str_replace($v, $text, $tpl_data); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
$tpl_data = preg_replace('/\s*<\!user_literal/', '', $tpl_data); |
178
|
|
|
$tpl_data = preg_replace('/user_literal!>/', '', $tpl_data); |
179
|
|
|
|
180
|
|
|
// Replace all 'echo $var' to if(isset($var)) { echo $var } |
181
|
|
|
$tpl_data = preg_replace('/(<\?php)\s*(echo)\s*(\$\w*?);\s*(\?>)/', '$1 if(isset($3)){ $2 $3; } $4', $tpl_data); |
182
|
|
|
|
183
|
|
|
$add_data = ''; |
184
|
|
|
|
185
|
|
|
if (count($include_functions) > 0) { |
186
|
|
|
foreach ($include_functions as $k => $v) { |
187
|
|
|
$add_data .= 'include (\'' . $this->config->function_path . 'func.' . $k . $this->config->function_ext . '\'); '; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
$add_data = '<?php ' . $add_data . ' ?>'; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
$del_time = time() + $this->config->compiled_ttl; |
194
|
|
|
$modifi_time = ''; |
195
|
|
|
|
196
|
|
|
if ($this->config->use_filemtime == TRUE) { |
197
|
|
|
$modifi_time = '$mabilis_last_modified=' . filemtime($file) . ';'; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
// Delete repeating spaces after php open tag |
201
|
|
|
$tpl_data = preg_replace('/(\s*)\<\?php\s*/', '$1<?php ', $tpl_data); |
202
|
|
|
|
203
|
|
|
$ttl_string = '<?php $mabilis_ttl=' . $del_time . '; ' . $modifi_time . ' //' . $file . ' ?>'; |
204
|
|
|
|
205
|
|
|
$this->write_compiled_file($file, $add_data . $tpl_data . $ttl_string); |
206
|
|
|
|
207
|
|
|
return TRUE; |
208
|
|
|
} |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Read template file |
213
|
|
|
* |
214
|
|
|
* @param string $file |
215
|
|
|
* @return string|false |
216
|
|
|
*/ |
217
|
|
|
public function read_tpl_file($file) { |
218
|
|
|
if (file_exists($file)) { |
219
|
|
|
return file_get_contents($file); |
220
|
|
|
} else { |
221
|
|
|
// File no found |
222
|
|
|
return FALSE; |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Write compiled template file |
228
|
|
|
* |
229
|
|
|
* @param string $file |
230
|
|
|
* @param string $data |
231
|
|
|
* @return boolean |
232
|
|
|
*/ |
233
|
|
|
private function write_compiled_file($file, $data) { |
234
|
|
|
if (!$fp = fopen($this->config->compile_path . md5($file) . $this->config->compiled_ext, 'w')) { |
235
|
|
|
return FALSE; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
flock($fp, LOCK_EX); |
239
|
|
|
fwrite($fp, $data); |
240
|
|
|
flock($fp, LOCK_UN); |
241
|
|
|
fclose($fp); |
242
|
|
|
|
243
|
|
|
@chmod($this->config->compile_path . md5($file) . $this->config->compiled_ext, 0777); |
|
|
|
|
244
|
|
|
|
245
|
|
|
return TRUE; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* @param string $text |
250
|
|
|
*/ |
251
|
|
|
private function error($text) { |
252
|
|
|
echo '<p>Error: ' . $text . '</p>'; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/* End of Mabilis.compiler.php */ |
If you suppress an error, we recommend checking for the error condition explicitly: