|
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: