1 | <?php |
---|
2 | |
---|
3 | if (!defined('DIR_SEP')) { |
---|
4 | define('DIR_SEP', DIRECTORY_SEPARATOR); |
---|
5 | } |
---|
6 | |
---|
7 | if (!defined('SMARTY_PHP_PASSTHRU')) { |
---|
8 | define('SMARTY_PHP_PASSTHRU', 0); |
---|
9 | define('SMARTY_PHP_QUOTE', 1); |
---|
10 | define('SMARTY_PHP_REMOVE', 2); |
---|
11 | define('SMARTY_PHP_ALLOW', 3); |
---|
12 | } |
---|
13 | |
---|
14 | if (class_exists('Dwoo_Compiler', false) === false) { |
---|
15 | require dirname(dirname(__FILE__)) . '/Compiler.php'; |
---|
16 | } |
---|
17 | |
---|
18 | /** |
---|
19 | * a Smarty compatibility layer for Dwoo |
---|
20 | * |
---|
21 | * This software is provided 'as-is', without any express or implied warranty. |
---|
22 | * In no event will the authors be held liable for any damages arising from the use of this software. |
---|
23 | * |
---|
24 | * @author Jordi Boggiano <j.boggiano@seld.be> |
---|
25 | * @copyright Copyright (c) 2008, Jordi Boggiano |
---|
26 | * @license http://dwoo.org/LICENSE Modified BSD License |
---|
27 | * @link http://dwoo.org/ |
---|
28 | * @version 1.1.0 |
---|
29 | * @date 2009-07-18 |
---|
30 | * @package Dwoo |
---|
31 | */ |
---|
32 | class Dwoo_Smarty__Adapter extends Dwoo_Core |
---|
33 | { |
---|
34 | // magic get/set/call functions that handle unsupported features |
---|
35 | public function __set($p, $v) |
---|
36 | { |
---|
37 | if ($p==='scope') { |
---|
38 | $this->scope = $v; |
---|
39 | return; |
---|
40 | } |
---|
41 | if ($p==='data') { |
---|
42 | $this->data = $v; |
---|
43 | return; |
---|
44 | } |
---|
45 | if (array_key_exists($p, $this->compat['properties']) !== false) { |
---|
46 | if ($this->show_compat_errors) { |
---|
47 | $this->triggerError('Property '.$p.' is not available in the Dwoo_Smarty_Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE); |
---|
48 | } |
---|
49 | $this->compat['properties'][$p] = $v; |
---|
50 | } else { |
---|
51 | if ($this->show_compat_errors) { |
---|
52 | $this->triggerError('Property '.$p.' is not available in the Dwoo_Smarty_Adapter, but it is not listed as such, so you might want to tell me about it at j.boggiano@seld.be', E_USER_NOTICE); |
---|
53 | } |
---|
54 | } |
---|
55 | } |
---|
56 | |
---|
57 | public function __get($p) |
---|
58 | { |
---|
59 | if (array_key_exists($p, $this->compat['properties']) !== false) { |
---|
60 | if ($this->show_compat_errors) { |
---|
61 | $this->triggerError('Property '.$p.' is not available in the Dwoo_Smarty_Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE); |
---|
62 | } |
---|
63 | return $this->compat['properties'][$p]; |
---|
64 | } else { |
---|
65 | if ($this->show_compat_errors) { |
---|
66 | $this->triggerError('Property '.$p.' is not available in the Dwoo_Smarty_Adapter, but it is not listed as such, so you might want to tell me about it at j.boggiano@seld.be', E_USER_NOTICE); |
---|
67 | } |
---|
68 | } |
---|
69 | } |
---|
70 | |
---|
71 | public function __call($m, $a) |
---|
72 | { |
---|
73 | if (method_exists($this->dataProvider, $m)) { |
---|
74 | call_user_func_array(array($this->dataProvider, $m), $a); |
---|
75 | } elseif ($this->show_compat_errors) { |
---|
76 | if (array_search($m, $this->compat['methods']) !== false) { |
---|
77 | $this->triggerError('Method '.$m.' is not available in the Dwoo_Smarty_Adapter, however it might be implemented in the future, check out http://wiki.dwoo.org/index.php/SmartySupport for more details.', E_USER_NOTICE); |
---|
78 | } else { |
---|
79 | $this->triggerError('Method '.$m.' is not available in the Dwoo_Smarty_Adapter, but it is not listed as such, so you might want to tell me about it at j.boggiano@seld.be', E_USER_NOTICE); |
---|
80 | } |
---|
81 | } |
---|
82 | } |
---|
83 | |
---|
84 | // list of unsupported properties and methods |
---|
85 | protected $compat = array |
---|
86 | ( |
---|
87 | 'methods' => array |
---|
88 | ( |
---|
89 | 'register_resource', 'unregister_resource', 'load_filter', 'clear_compiled_tpl', |
---|
90 | 'clear_config', 'get_config_vars', 'config_load' |
---|
91 | ), |
---|
92 | 'properties' => array |
---|
93 | ( |
---|
94 | 'cache_handler_func' => null, |
---|
95 | 'debugging' => false, |
---|
96 | 'error_reporting' => null, |
---|
97 | 'debugging_ctrl' => 'NONE', |
---|
98 | 'request_vars_order' => 'EGPCS', |
---|
99 | 'request_use_auto_globals' => true, |
---|
100 | 'use_sub_dirs' => false, |
---|
101 | 'autoload_filters' => array(), |
---|
102 | 'default_template_handler_func' => '', |
---|
103 | 'debug_tpl' => '', |
---|
104 | 'cache_modified_check' => false, |
---|
105 | 'default_modifiers' => array(), |
---|
106 | 'default_resource_type' => 'file', |
---|
107 | 'config_overwrite' => true, |
---|
108 | 'config_booleanize' => true, |
---|
109 | 'config_read_hidden' => false, |
---|
110 | 'config_fix_newlines' => true, |
---|
111 | 'config_class' => 'Config_File', |
---|
112 | ), |
---|
113 | ); |
---|
114 | |
---|
115 | // security vars |
---|
116 | public $security = false; |
---|
117 | public $trusted_dir = array(); |
---|
118 | public $secure_dir = array(); |
---|
119 | public $php_handling = SMARTY_PHP_PASSTHRU; |
---|
120 | public $security_settings = array |
---|
121 | ( |
---|
122 | 'PHP_HANDLING' => false, |
---|
123 | 'IF_FUNCS' => array |
---|
124 | ( |
---|
125 | 'list', 'empty', 'count', 'sizeof', |
---|
126 | 'in_array', 'is_array', |
---|
127 | ), |
---|
128 | 'INCLUDE_ANY' => false, |
---|
129 | 'PHP_TAGS' => false, |
---|
130 | 'MODIFIER_FUNCS' => array(), |
---|
131 | 'ALLOW_CONSTANTS' => false |
---|
132 | ); |
---|
133 | |
---|
134 | // paths |
---|
135 | public $template_dir = 'templates'; |
---|
136 | public $compile_dir = 'templates_c'; |
---|
137 | public $config_dir = 'configs'; |
---|
138 | public $cache_dir = 'cache'; |
---|
139 | public $plugins_dir = array(); |
---|
140 | |
---|
141 | // misc options |
---|
142 | public $left_delimiter = '{'; |
---|
143 | public $right_delimiter = '}'; |
---|
144 | public $compile_check = true; |
---|
145 | public $force_compile = false; |
---|
146 | public $caching = 0; |
---|
147 | public $cache_lifetime = 3600; |
---|
148 | public $compile_id = null; |
---|
149 | public $compiler_file = null; |
---|
150 | public $compiler_class = null; |
---|
151 | |
---|
152 | // dwoo/smarty compat layer |
---|
153 | public $show_compat_errors = false; |
---|
154 | protected $dataProvider; |
---|
155 | protected $_filters = array('pre'=>array(), 'post'=>array(), 'output'=>array()); |
---|
156 | protected static $tplCache = array(); |
---|
157 | protected $compiler = null; |
---|
158 | |
---|
159 | public function __construct() |
---|
160 | { |
---|
161 | parent::__construct(); |
---|
162 | $this->charset = 'iso-8859-1'; |
---|
163 | $this->dataProvider = new Dwoo_Data(); |
---|
164 | $this->compiler = new Dwoo_Compiler(); |
---|
165 | } |
---|
166 | |
---|
167 | public function display($filename, $cacheId=null, $compileId=null) |
---|
168 | { |
---|
169 | $this->fetch($filename, $cacheId, $compileId, true); |
---|
170 | } |
---|
171 | |
---|
172 | public function fetch($filename, $cacheId=null, $compileId=null, $display=false) |
---|
173 | { |
---|
174 | $this->setCacheDir($this->cache_dir); |
---|
175 | $this->setCompileDir($this->compile_dir); |
---|
176 | |
---|
177 | if ($this->security) { |
---|
178 | $policy = new Dwoo_Security_Policy(); |
---|
179 | $policy->addPhpFunction(array_merge($this->security_settings['IF_FUNCS'], $this->security_settings['MODIFIER_FUNCS'])); |
---|
180 | |
---|
181 | $phpTags = $this->security_settings['PHP_HANDLING'] ? SMARTY_PHP_ALLOW : $this->php_handling; |
---|
182 | if ($this->security_settings['PHP_TAGS']) { |
---|
183 | $phpTags = SMARTY_PHP_ALLOW; |
---|
184 | } |
---|
185 | switch($phpTags) { |
---|
186 | case SMARTY_PHP_ALLOW: |
---|
187 | case SMARTY_PHP_PASSTHRU: |
---|
188 | $phpTags = Dwoo_Security_Policy::PHP_ALLOW; |
---|
189 | break; |
---|
190 | case SMARTY_PHP_QUOTE: |
---|
191 | $phpTags = Dwoo_Security_Policy::PHP_ENCODE; |
---|
192 | break; |
---|
193 | case SMARTY_PHP_REMOVE: |
---|
194 | default: |
---|
195 | $phpTags = Dwoo_Security_Policy::PHP_REMOVE; |
---|
196 | break; |
---|
197 | } |
---|
198 | $policy->setPhpHandling($phpTags); |
---|
199 | |
---|
200 | $policy->setConstantHandling($this->security_settings['ALLOW_CONSTANTS']); |
---|
201 | |
---|
202 | if ($this->security_settings['INCLUDE_ANY']) { |
---|
203 | $policy->allowDirectory(preg_replace('{^((?:[a-z]:)?[\\\\/]).*}i', '$1', __FILE__)); |
---|
204 | } else { |
---|
205 | $policy->allowDirectory($this->secure_dir); |
---|
206 | } |
---|
207 | |
---|
208 | $this->setSecurityPolicy($policy); |
---|
209 | } |
---|
210 | |
---|
211 | if (!empty($this->plugins_dir)) { |
---|
212 | foreach ($this->plugins_dir as $dir) { |
---|
213 | $this->getLoader()->addDirectory(rtrim($dir, '\\/')); |
---|
214 | } |
---|
215 | } |
---|
216 | |
---|
217 | $tpl = $this->makeTemplate($filename, $cacheId, $compileId); |
---|
218 | if ($this->force_compile) { |
---|
219 | $tpl->forceCompilation(); |
---|
220 | } |
---|
221 | |
---|
222 | if ($this->caching > 0) { |
---|
223 | $this->cacheTime = $this->cache_lifetime; |
---|
224 | } else { |
---|
225 | $this->cacheTime = 0; |
---|
226 | } |
---|
227 | |
---|
228 | if ($this->compiler_class !== null) { |
---|
229 | if ($this->compiler_file !== null && !class_exists($this->compiler_class, false)) { |
---|
230 | include $this->compiler_file; |
---|
231 | } |
---|
232 | $this->compiler = new $this->compiler_class; |
---|
233 | } else { |
---|
234 | $this->compiler->addPreProcessor('smarty_compat', true); |
---|
235 | $this->compiler->setLooseOpeningHandling(true); |
---|
236 | } |
---|
237 | |
---|
238 | $this->compiler->setDelimiters($this->left_delimiter, $this->right_delimiter); |
---|
239 | |
---|
240 | return $this->get($tpl, $this->dataProvider, $this->compiler, $display===true); |
---|
241 | } |
---|
242 | |
---|
243 | public function get($_tpl, $data = array(), $_compiler = null, $_output = false) |
---|
244 | { |
---|
245 | if ($_compiler === null) { |
---|
246 | $_compiler = $this->compiler; |
---|
247 | } |
---|
248 | return parent::get($_tpl, $data, $_compiler, $_output); |
---|
249 | } |
---|
250 | |
---|
251 | public function register_function($name, $callback, $cacheable=true, $cache_attrs=null) |
---|
252 | { |
---|
253 | if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_FUNCTION) { |
---|
254 | throw new Dwoo_Exception('Multiple plugins of different types can not share the same name'); |
---|
255 | } |
---|
256 | $this->plugins[$name] = array('type'=>self::SMARTY_FUNCTION, 'callback'=>$callback); |
---|
257 | } |
---|
258 | |
---|
259 | public function unregister_function($name) |
---|
260 | { |
---|
261 | unset($this->plugins[$name]); |
---|
262 | } |
---|
263 | |
---|
264 | public function register_block($name, $callback, $cacheable=true, $cache_attrs=null) |
---|
265 | { |
---|
266 | if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_BLOCK) { |
---|
267 | throw new Dwoo_Exception('Multiple plugins of different types can not share the same name'); |
---|
268 | } |
---|
269 | $this->plugins[$name] = array('type'=>self::SMARTY_BLOCK, 'callback'=>$callback); |
---|
270 | } |
---|
271 | |
---|
272 | public function unregister_block($name) |
---|
273 | { |
---|
274 | unset($this->plugins[$name]); |
---|
275 | } |
---|
276 | |
---|
277 | public function register_modifier($name, $callback) |
---|
278 | { |
---|
279 | if (isset($this->plugins[$name]) && $this->plugins[$name][0] !== self::SMARTY_MODIFIER) { |
---|
280 | throw new Dwoo_Exception('Multiple plugins of different types can not share the same name'); |
---|
281 | } |
---|
282 | $this->plugins[$name] = array('type'=>self::SMARTY_MODIFIER, 'callback'=>$callback); |
---|
283 | } |
---|
284 | |
---|
285 | public function unregister_modifier($name) |
---|
286 | { |
---|
287 | unset($this->plugins[$name]); |
---|
288 | } |
---|
289 | |
---|
290 | public function register_prefilter($callback) |
---|
291 | { |
---|
292 | $processor = new Dwoo_SmartyProcessorAdapter($this->compiler); |
---|
293 | $processor->registerCallback($callback); |
---|
294 | $this->_filters['pre'][] = $processor; |
---|
295 | $this->compiler->addPreProcessor($processor); |
---|
296 | } |
---|
297 | |
---|
298 | public function unregister_prefilter($callback) |
---|
299 | { |
---|
300 | foreach ($this->_filters['pre'] as $index => $processor) |
---|
301 | if ($processor->callback === $callback) { |
---|
302 | $this->compiler->removePostProcessor($processor); |
---|
303 | unset($this->_filters['pre'][$index]); |
---|
304 | } |
---|
305 | } |
---|
306 | |
---|
307 | public function register_postfilter($callback) |
---|
308 | { |
---|
309 | $processor = new Dwoo_SmartyProcessorAdapter($this->compiler); |
---|
310 | $processor->registerCallback($callback); |
---|
311 | $this->_filters['post'][] = $processor; |
---|
312 | $this->compiler->addPostProcessor($processor); |
---|
313 | } |
---|
314 | |
---|
315 | public function unregister_postfilter($callback) |
---|
316 | { |
---|
317 | foreach ($this->_filters['post'] as $index => $processor) |
---|
318 | if ($processor->callback === $callback) { |
---|
319 | $this->compiler->removePostProcessor($processor); |
---|
320 | unset($this->_filters['post'][$index]); |
---|
321 | } |
---|
322 | } |
---|
323 | |
---|
324 | public function register_outputfilter($callback) |
---|
325 | { |
---|
326 | $filter = new Dwoo_SmartyFilterAdapter($this); |
---|
327 | $filter->registerCallback($callback); |
---|
328 | $this->_filters['output'][] = $filter; |
---|
329 | $this->addFilter($filter); |
---|
330 | } |
---|
331 | |
---|
332 | public function unregister_outputfilter($callback) |
---|
333 | { |
---|
334 | foreach ($this->_filters['output'] as $index => $filter) |
---|
335 | if ($filter->callback === $callback) { |
---|
336 | $this->removeOutputFilter($filter); |
---|
337 | unset($this->_filters['output'][$index]); |
---|
338 | } |
---|
339 | } |
---|
340 | |
---|
341 | function register_object($object, $object_impl, $allowed = array(), $smarty_args = false, $block_methods = array()) |
---|
342 | { |
---|
343 | settype($allowed, 'array'); |
---|
344 | settype($block_methods, 'array'); |
---|
345 | settype($smarty_args, 'boolean'); |
---|
346 | |
---|
347 | if (!empty($allowed) && $this->show_compat_errors) { |
---|
348 | $this->triggerError('You can register objects but can not restrict the method/properties used, this is PHP5, you have proper OOP access restrictions so use them.', E_USER_NOTICE); |
---|
349 | } |
---|
350 | |
---|
351 | if ($smarty_args) { |
---|
352 | $this->triggerError('You can register objects but methods will be called using method($arg1, $arg2, $arg3), not as an argument array like smarty did.', E_USER_NOTICE); |
---|
353 | } |
---|
354 | |
---|
355 | if (!empty($block_methods)) { |
---|
356 | $this->triggerError('You can register objects but can not use methods as being block methods, you have to build a plugin for that.', E_USER_NOTICE); |
---|
357 | } |
---|
358 | |
---|
359 | $this->dataProvider->assign($object, $object_impl); |
---|
360 | } |
---|
361 | |
---|
362 | function unregister_object($object) |
---|
363 | { |
---|
364 | $this->dataProvider->clear($object); |
---|
365 | } |
---|
366 | |
---|
367 | function get_registered_object($name) { |
---|
368 | $data = $this->dataProvider->getData(); |
---|
369 | if (isset($data[$name]) && is_object($data[$name])) { |
---|
370 | return $data[$name]; |
---|
371 | } else { |
---|
372 | trigger_error('Dwoo_Compiler: object "'.$name.'" was not registered or is not an object', E_USER_ERROR); |
---|
373 | } |
---|
374 | } |
---|
375 | |
---|
376 | public function template_exists($filename) |
---|
377 | { |
---|
378 | if (!is_array($this->template_dir)) { |
---|
379 | return file_exists($this->template_dir.DIRECTORY_SEPARATOR.$filename); |
---|
380 | } else { |
---|
381 | foreach ($this->template_dir as $tpl_dir) { |
---|
382 | if (file_exists($tpl_dir.DIRECTORY_SEPARATOR.$filename)) { |
---|
383 | return true; |
---|
384 | } |
---|
385 | } |
---|
386 | return false; |
---|
387 | } |
---|
388 | } |
---|
389 | |
---|
390 | public function is_cached($tpl, $cacheId = null, $compileId = null) |
---|
391 | { |
---|
392 | return $this->isCached($this->makeTemplate($tpl, $cacheId, $compileId)); |
---|
393 | } |
---|
394 | |
---|
395 | public function append_by_ref($var, &$value, $merge=false) |
---|
396 | { |
---|
397 | $this->dataProvider->appendByRef($var, $value, $merge); |
---|
398 | } |
---|
399 | |
---|
400 | public function assign_by_ref($name, &$val) |
---|
401 | { |
---|
402 | $this->dataProvider->assignByRef($name, $val); |
---|
403 | } |
---|
404 | |
---|
405 | public function clear_assign($var) |
---|
406 | { |
---|
407 | $this->dataProvider->clear($var); |
---|
408 | } |
---|
409 | |
---|
410 | public function clear_all_assign() |
---|
411 | { |
---|
412 | $this->dataProvider->clear(); |
---|
413 | } |
---|
414 | |
---|
415 | public function get_template_vars($name=null) |
---|
416 | { |
---|
417 | if ($this->show_compat_errors) { |
---|
418 | trigger_error('get_template_vars does not return values by reference, if you try to modify the data that way you should modify your code.', E_USER_NOTICE); |
---|
419 | } |
---|
420 | |
---|
421 | $data = $this->dataProvider->getData(); |
---|
422 | if ($name === null) |
---|
423 | return $data; |
---|
424 | elseif (isset($data[$name])) |
---|
425 | return $data[$name]; |
---|
426 | return null; |
---|
427 | } |
---|
428 | |
---|
429 | public function clear_all_cache($olderThan = 0) |
---|
430 | { |
---|
431 | $this->clearCache($olderThan); |
---|
432 | } |
---|
433 | |
---|
434 | public function clear_cache($template, $cacheId = null, $compileId = null, $olderThan = 0) |
---|
435 | { |
---|
436 | $this->makeTemplate($template, $cacheId, $compileId)->clearCache($olderThan); |
---|
437 | } |
---|
438 | |
---|
439 | public function trigger_error($error_msg, $error_type = E_USER_WARNING) |
---|
440 | { |
---|
441 | $this->triggerError($error_msg, $error_type); |
---|
442 | } |
---|
443 | |
---|
444 | protected function initGlobals() |
---|
445 | { |
---|
446 | parent::initGlobals(); |
---|
447 | $this->globals['ldelim'] = '{'; |
---|
448 | $this->globals['rdelim'] = '}'; |
---|
449 | } |
---|
450 | |
---|
451 | protected function makeTemplate($file, $cacheId, $compileId) |
---|
452 | { |
---|
453 | if ($compileId === null) |
---|
454 | $compileId = $this->compile_id; |
---|
455 | |
---|
456 | $hash = bin2hex(md5($file.$cacheId.$compileId, true)); |
---|
457 | if (!isset(self::$tplCache[$hash])) { |
---|
458 | // abs path |
---|
459 | if (substr($file, 0, 1) === '/' || substr($file, 1, 1) === ':') { |
---|
460 | self::$tplCache[$hash] = new Dwoo_Template_File($file, null, $cacheId, $compileId); |
---|
461 | } elseif (is_string($this->template_dir) || is_array($this->template_dir)) { |
---|
462 | self::$tplCache[$hash] = new Dwoo_Template_File($file, null, $cacheId, $compileId, $this->template_dir); |
---|
463 | } else { |
---|
464 | throw new Exception('Unable to load "'.$file.'", check the template_dir'); |
---|
465 | } |
---|
466 | } |
---|
467 | return self::$tplCache[$hash]; |
---|
468 | } |
---|
469 | |
---|
470 | public function triggerError($message, $level=E_USER_NOTICE) |
---|
471 | { |
---|
472 | if (is_object($this->template)) { |
---|
473 | return parent::triggerError($message, $level); |
---|
474 | } |
---|
475 | trigger_error('Dwoo error : '.$message, $level); |
---|
476 | } |
---|
477 | } |
---|
478 | |
---|
479 | class Dwoo_Smarty_Filter_Adapter extends Dwoo_Filter |
---|
480 | { |
---|
481 | public $callback; |
---|
482 | |
---|
483 | public function process($input) |
---|
484 | { |
---|
485 | return call_user_func($this->callback, $input); |
---|
486 | } |
---|
487 | |
---|
488 | public function registerCallback($callback) |
---|
489 | { |
---|
490 | $this->callback = $callback; |
---|
491 | } |
---|
492 | } |
---|
493 | |
---|
494 | class Dwoo_Smarty_Processor_Adapter extends Dwoo_Processor |
---|
495 | { |
---|
496 | public $callback; |
---|
497 | |
---|
498 | public function process($input) |
---|
499 | { |
---|
500 | return call_user_func($this->callback, $input); |
---|
501 | } |
---|
502 | |
---|
503 | public function registerCallback($callback) |
---|
504 | { |
---|
505 | $this->callback = $callback; |
---|
506 | } |
---|
507 | } |
---|
508 | |
---|
509 | // cloaks the adapter if possible with the smarty name to fool type-hinted plugins |
---|
510 | if (class_exists('Smarty', false) === false) |
---|
511 | { |
---|
512 | interface Smarty {} |
---|
513 | class Dwoo_Smarty_Adapter extends Dwoo_Smarty__Adapter implements Smarty {} |
---|
514 | } |
---|
515 | else |
---|
516 | { |
---|
517 | class Dwoo_Smarty_Adapter extends Dwoo_Smarty__Adapter {} |
---|
518 | } |
---|