|
@@ -41,7 +41,9 @@
|
|
|
'gettext_string'=>'/^([\'"])(.+)\1$/i',
|
|
|
'echo'=>'/\{=([^}]+)\}/i',
|
|
|
'eval'=>'/\{\?([\W\w\S\s]+)\?\}/i',
|
|
|
- 'include'=>'/{#include ([^}]+)}/i'
|
|
|
+ 'include'=>'/{#include ([^}]+)}/i',
|
|
|
+ 'define'=>'/\{#define ([^}]*)\}([\S\s]*)\{\/define \1\}/i',
|
|
|
+ 'widget'=>'/{#widget ([^}]+)}/i'
|
|
|
];
|
|
|
protected static $parsers;
|
|
|
private $template;
|
|
@@ -71,20 +73,31 @@
|
|
|
}, $output);
|
|
|
}
|
|
|
},
|
|
|
- 'each'=>[
|
|
|
- function(&$output, $data){
|
|
|
- $output = preg_replace_callback(static::$regex['each'], function($matches) use($data){
|
|
|
- $output = '';
|
|
|
- if(isset($data[$matches[1]])){
|
|
|
- foreach($data[$matches[1]] as $item){
|
|
|
- $output = static::parse($matches[2], $item);
|
|
|
- }
|
|
|
+ 'define'=>function(&$output, &$widgets){
|
|
|
+ while(preg_match(static::$regex['define'], $output)){
|
|
|
+ $output = preg_replace_callback(static::$regex['define'], function($matches) use(&$widgets){
|
|
|
+ $name = $matches[1];
|
|
|
+ if(isset($widgets[$name])){
|
|
|
+ throw new \Exception("Widget {$name} is already defined");
|
|
|
}
|
|
|
- return $output;
|
|
|
+ $widgets[$name] = $matches[2];
|
|
|
+ return '';
|
|
|
}, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['each'], function($matches){
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 'widget'=>function(&$output, $widgets){
|
|
|
+ while(preg_match(static::$regex['widget'], $output)){
|
|
|
+ $output = preg_replace_callback(static::$regex['widget'], function($matches) use(&$widgets){
|
|
|
+ $name = $matches[1];
|
|
|
+ if(!isset($widgets[$name])){
|
|
|
+ throw new \Exception("Widget {$name} is not defined");
|
|
|
+ }
|
|
|
+ return $widgets[$name];
|
|
|
+ }, $output);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 'each'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['each'], function($matches){
|
|
|
$output = "<?php if(isset(\$data[".var_export($matches[1], true)."])): ";
|
|
|
$output .= "foreach(\$data[".var_export($matches[1], true)."] as \$item): ";
|
|
|
$output .= "\$parent[] = \$data; \$data = \$item; ?>";
|
|
@@ -93,129 +106,62 @@
|
|
|
$output .= "endforeach;endif; ?>";
|
|
|
return $output;
|
|
|
}, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'existelse'=>[
|
|
|
- function(&$output, $data){
|
|
|
- $output = preg_replace_callback(static::$regex['existelse'], function($matches) use($data){
|
|
|
- if(isset($data[$matches[1]])){
|
|
|
- $output = static::parse($matches[2], $data);
|
|
|
- }else{
|
|
|
- $output = static::parse($matches[3], $data);
|
|
|
- }
|
|
|
- return $output;
|
|
|
- }, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['existelse'], function($matches){
|
|
|
- $output = "<?php if(isset(\$data[".var_export($matches[1], true)."])): ?>";
|
|
|
- $output .= static::compile($matches[2]);
|
|
|
- $output .= "<?php else: ?>";
|
|
|
- $output .= static::compile($matches[3]);
|
|
|
- $output .= "<?php endif; ?>";
|
|
|
- return $output;
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'exist'=>[
|
|
|
- function(&$output, $data){
|
|
|
- $output = preg_replace_callback(static::$regex['exist'], function($matches) use($data){
|
|
|
- if(isset($data[$matches[1]])){
|
|
|
- return static::parse($data[$matches[2]], $data);
|
|
|
- }
|
|
|
- return '';
|
|
|
- }, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['exist'], function($matches){
|
|
|
- $output = "<?php if(isset(\$data[".var_export($matches[1], true)."])): ?>";
|
|
|
- $output .= static::compile($matches[2]);
|
|
|
- $output .= "<?php endif; ?>";
|
|
|
- return $output;
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'gettext'=>[
|
|
|
- function(&$output, $data){
|
|
|
- $output = preg_replace_callback(static::$regex['gettext'], function($matches) use($data){
|
|
|
- $args = array_map(function($item) use($data){
|
|
|
+ },
|
|
|
+ 'existelse'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['existelse'], function($matches){
|
|
|
+ $output = "<?php if(isset(\$data[".var_export($matches[1], true)."])): ?>";
|
|
|
+ $output .= static::compile($matches[2]);
|
|
|
+ $output .= "<?php else: ?>";
|
|
|
+ $output .= static::compile($matches[3]);
|
|
|
+ $output .= "<?php endif; ?>";
|
|
|
+ return $output;
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
+ 'exist'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['exist'], function($matches){
|
|
|
+ $output = "<?php if(isset(\$data[".var_export($matches[1], true)."])): ?>";
|
|
|
+ $output .= static::compile($matches[2]);
|
|
|
+ $output .= "<?php endif; ?>";
|
|
|
+ return $output;
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
+ 'gettext'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['gettext'], function($matches){
|
|
|
+ if(count($matches) > 2){
|
|
|
+ $output = "<?=htmlentities(sprintf(_({$matches[1]})";
|
|
|
+ foreach(array_slice($matches, 2) as $item){
|
|
|
if(preg_match(static::$regex['gettext_string'], $item)){
|
|
|
- return preg_replace(static::$regex['gettext_string'], '\2', $item);
|
|
|
+ $output .= ", $item";
|
|
|
}else{
|
|
|
- return $data[$item] ?? '';
|
|
|
+ $output .= ", (\$data['{$item}'] ?? '')";
|
|
|
}
|
|
|
- }, array_slice($matches, 1));
|
|
|
- return htmlentities(_(sprintf(...$args)));
|
|
|
- }, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['gettext'], function($matches){
|
|
|
- if(count($matches) > 2){
|
|
|
- $output = "<?=htmlentities(sprintf(_({$matches[1]})";
|
|
|
- foreach(array_slice($matches, 2) as $item){
|
|
|
- if(preg_match(static::$regex['gettext_string'], $item)){
|
|
|
- $output .= ", $item";
|
|
|
- }else{
|
|
|
- $output .= ", (\$data['{$item}'] ?? '')";
|
|
|
- }
|
|
|
- }
|
|
|
- }else{
|
|
|
- $output = "<?=htmlentities(_({$matches[1]}";
|
|
|
}
|
|
|
- return "{$output})); ?>";
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'echo'=>[
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['echo'], function($matches){
|
|
|
- return eval("return {$matches[1]};");
|
|
|
- }, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['echo'], function($matches){
|
|
|
- return "<?= {$matches[1]}; ?>";
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'eval'=>[
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['eval'], function($matches){
|
|
|
- ob_start();
|
|
|
- eval($matches[1]);
|
|
|
- $output = ob_get_contents();
|
|
|
- ob_end_clean();
|
|
|
- return $output;
|
|
|
- }, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['eval'], function($matches){
|
|
|
- return "<?php {$matches[1]}; ?>";
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'match'=>[
|
|
|
- function(&$output, $data){
|
|
|
- $output = preg_replace_callback(static::$regex['match'], function($matches) use($data){
|
|
|
- return htmlentities($data[$matches[1]] ?? '');
|
|
|
- }, $output);
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['match'], function($matches){
|
|
|
- return "<?=htmlentities(\$data[".var_export($matches[1], true)."] ?? ''); ?>";
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
- 'parentmatch'=>[
|
|
|
- function(&$output, $data){
|
|
|
- throw new \Exception("Not supported in non-compiled templates");
|
|
|
- },
|
|
|
- function(&$output){
|
|
|
- $output = preg_replace_callback(static::$regex['parentmatch'], function($matches){
|
|
|
- return "<?=htmlentities(\$parent[count(\$parent)-1][".var_export($matches[1], true)."] ?? ''); ?>";
|
|
|
- }, $output);
|
|
|
- }
|
|
|
- ],
|
|
|
+ }else{
|
|
|
+ $output = "<?=htmlentities(_({$matches[1]}";
|
|
|
+ }
|
|
|
+ return "{$output})); ?>";
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
+ 'echo'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['echo'], function($matches){
|
|
|
+ return "<?= {$matches[1]}; ?>";
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
+ 'eval'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['eval'], function($matches){
|
|
|
+ return "<?php {$matches[1]}; ?>";
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
+ 'match'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['match'], function($matches){
|
|
|
+ return "<?=htmlentities(\$data[".var_export($matches[1], true)."] ?? ''); ?>";
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
+ 'parentmatch'=>function(&$output){
|
|
|
+ $output = preg_replace_callback(static::$regex['parentmatch'], function($matches){
|
|
|
+ return "<?=htmlentities(\$parent[count(\$parent)-1][".var_export($matches[1], true)."] ?? ''); ?>";
|
|
|
+ }, $output);
|
|
|
+ },
|
|
|
'ignored'=>function(&$output, $ignored){
|
|
|
$output = preg_replace_callback(static::$regex['ignored'], function($matches) use($ignored){
|
|
|
return htmlentities($ignored[(int)$matches[1]] ?? '');
|
|
@@ -234,6 +180,9 @@
|
|
|
$template = file_get_contents($path);
|
|
|
}
|
|
|
static::$parsers['include']($template);
|
|
|
+ $widgets = [];
|
|
|
+ static::$parsers['define']($template, $widgets);
|
|
|
+ static::$parsers['widget']($template, $widgets);
|
|
|
$this->template = $template;
|
|
|
$this->name = $name;
|
|
|
$this->path = static::$cachedir."/{$this->name}.".md5($this->template).'.php';
|
|
@@ -284,55 +233,31 @@
|
|
|
|
|
|
static::$parsers['include']($output, $ignored);
|
|
|
|
|
|
- static::$parsers['each'][1]($output);
|
|
|
+ static::$parsers['each']($output);
|
|
|
|
|
|
- static::$parsers['existelse'][1]($output);
|
|
|
+ static::$parsers['existelse']($output);
|
|
|
|
|
|
- static::$parsers['exist'][1]($output);
|
|
|
+ static::$parsers['exist']($output);
|
|
|
|
|
|
- static::$parsers['gettext'][1]($output);
|
|
|
+ static::$parsers['gettext']($output);
|
|
|
|
|
|
- static::$parsers['echo'][1]($output);
|
|
|
+ static::$parsers['echo']($output);
|
|
|
|
|
|
- static::$parsers['eval'][1]($output);
|
|
|
+ static::$parsers['eval']($output);
|
|
|
|
|
|
- static::$parsers['parentmatch'][1]($output);
|
|
|
+ static::$parsers['parentmatch']($output);
|
|
|
|
|
|
- static::$parsers['match'][1]($output);
|
|
|
+ static::$parsers['match']($output);
|
|
|
|
|
|
static::$parsers['ignored']($output, $ignored);
|
|
|
return $output;
|
|
|
}
|
|
|
public static function parse(string $template, $data) : string{
|
|
|
- if(is_null(static::$parsers)){
|
|
|
-
|
|
|
- new Template(uuid(), $template);
|
|
|
+ $id = md5($template);
|
|
|
+ if(!isset(static::$templates[$id])){
|
|
|
+ new Template($id, $template);
|
|
|
}
|
|
|
- $ignored = [];
|
|
|
- $output = $template;
|
|
|
-
|
|
|
- static::$parsers['ignore']($output, $ignored);
|
|
|
-
|
|
|
- static::$parsers['include']($output, $ignored);
|
|
|
-
|
|
|
- static::$parsers['each'][0]($output, $data);
|
|
|
-
|
|
|
- static::$parsers['existelse'][0]($output, $data);
|
|
|
-
|
|
|
- static::$parsers['exist'][0]($output, $data);
|
|
|
-
|
|
|
- static::$parsers['gettext'][0]($output, $data);
|
|
|
-
|
|
|
- static::$parsers['echo'][0]($output);
|
|
|
-
|
|
|
- static::$parsers['eval'][0]($output);
|
|
|
-
|
|
|
- static::$parsers['parentmatch'][1]($output, $data);
|
|
|
-
|
|
|
- static::$parsers['match'][0]($output, $data);
|
|
|
-
|
|
|
- static::$parsers['ignored']($output, $ignored);
|
|
|
- return $output;
|
|
|
+ return static::$templates[$id]->run($data);
|
|
|
}
|
|
|
public static function execute(string $path, $data) : string{
|
|
|
ob_start();
|