<?php
class ESPCMS_Templates_Parser {
private $template_content;
private $list_hash = '6623ef97c6f6ccf2fb032e800d2edda9';
private $link_hash = '885BA145EFC8431D34F5CC06D142F143';
private $get_hash = '214adb21252b0af7b03s214s9';
private $get_table_hash = '60af7b03s21fs';
private $find_hash = '4adb4912cd04e6fd3';
private $pack_hash = 'E843B7A28BF9F9FC6D55A5A8EAE72F36';
private $code_spc = false;
public function compile($fetch_filename, $templates_path_dir, $templates_themss_dirname, $html_compile_dir, $left_delimiter, $right_delimiter) {
$this->fetch_filename = $fetch_filename;
$this->templates_themss_dirname = $templates_themss_dirname;
$this->left_delimiter = preg_quote($left_delimiter);
$this->right_delimiter = preg_quote($right_delimiter);
$templates_filename = $templates_path_dir . $fetch_filename;
$parsed_file = $html_compile_dir . md5($templates_filename) . '.php';
if (!file_exists($templates_filename)) {
espcms_message_err('public_pack-espcms_templates_filename_err', array($fetch_filename));
}
$fp = fopen($templates_filename, 'r');
if (!$fp) {
espcms_message_err('public_pack-espcms_templates_filename_fp_err', array($fetch_filename));
}
if (filesize($templates_filename)) {
$this->template_content = fread($fp, filesize($templates_filename));
} else {
espcms_message_err('public_pack-espcms_templates_filename_size_err', array($fetch_filename));
}
fclose($fp);
$this->_parse_common();
$this->_parse_var();
$this->_parse_for();
$this->_parse_if();
$this->_parse_fun();
$this->_parse_link();
$this->_parse_pack();
$this->_parse_find();
$this->_parse_class();
$this->_parse_get();
$this->_parse_list();
$this->_parse_echo();
if ($this->code_spc) {
$this->template_content = $this->str_space($this->template_content);
}
$fp = fopen($parsed_file, 'w');
fwrite($fp, $this->template_content);
fclose($fp);
}
private function str_space($str) {
if (!$str) {
return false;
}
$str = preg_replace("/[\t]+/is", '', $str);
$str = preg_replace("/([\s]{2,})/", '', $str);
return $str;
}
private function _parse_common() {
if (preg_match('/' . $this->left_delimiter . '\s*#\s*' . $this->right_delimiter . '/', $this->template_content)) {
$patten = '/' . $this->left_delimiter . '\s*#\s*' . $this->right_delimiter . '\s*([^' . $this->left_delimiter . ']*)\s*' . $this->left_delimiter . '\s*#\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($patten, '<?php ?>', $this->template_content);
}
return true;
}
private function _parse_var() {
if (preg_match('/' . $this->left_delimiter . '\s*\\$[a-zA-Z0-9_]{1,}|$[a-zA-Z0-9_]{1,}\s*\|\s*([a-zA-Z_]+)\[([^]]+)\]\s*' . $this->right_delimiter . '/', $this->template_content)) {
$patten = '/\$([A-Za-z]+[\w]+)/';
$this->template_content = preg_replace($patten, "\$this->_tpl_vars['$1']", $this->template_content);
$patten = '/(\$this->_tpl_vars\[\'[\w]+\'\])\.([\w]+)/';
$this->template_content = preg_replace($patten, "\$1['$2']", $this->template_content);
}
}
private function _parse_get() {
if (preg_match('/' . $this->left_delimiter . '\s*get\s*name\s*=\s*[0-9a-zA-Z_]+/', $this->template_content)) {
preg_match_all('/' . $this->left_delimiter . '\s*get[^\f]*?\/get' . $this->right_delimiter . '/', $this->template_content, $getarray);
foreach ($getarray[0] as $key => $variable) {
$bearkarray = array();
preg_match_all('/' . $this->left_delimiter . '\s*get\s*name\s*=\s*([0-9a-zA-Z_]+)\s*(iscache=\s*([0-9]{1})|)\s*(cachefile=\s*([^\s]+)|)\s*(class=\s*([^%]+)|)*\s*' . $this->right_delimiter . '/', $variable, $bearkarray);
$newbearkText = $this->_parse_array__get($bearkarray, $this->left_delimiter, $this->right_delimiter);
$getout = str_replace($bearkarray[0][0], $newbearkText, $variable);
$value_strget = '/' . $this->left_delimiter . '\s*get\s*name\s*=\s*([0-9a-zA-Z_]+)\s*(iscache=\s*([0-9]{1})|)\s*(cachefile=\s*([0-9a-zA-Z_,<\?\>\=\$\[\]\'\s-]+)|)\s*(class=\s*([^%]+)|)' . $this->right_delimiter . '/';
$value_endget = '/' . $this->left_delimiter . '\s*\/get\s*' . $this->right_delimiter . '/';
$getout = preg_replace($value_strget, $this->get_hash . '$1|$7|$3|$5|' . $this->get_table_hash, $getout);
$getout = preg_replace($value_endget, $this->get_hash, $getout);
$rec_book = '/' . preg_quote($bearkarray[0][0]) . '[^\f]*?' . $this->left_delimiter . '\s*\/get\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($rec_book, $getout, $this->template_content);
}
}
}
private function _parse_list() {
if (strrchr($this->fetch_filename, '.') == '.lbi') {
$this->template_content = preg_replace('/<meta\shttp-equiv=["|\']Content-Type["|\']\scontent=["|\']text\/html;\scharset=(?:.*?)["|\']>\r?\n?/i', '', $this->template_content);
}
if (preg_match('/' . $this->left_delimiter . '\s*list\s*name\s*=\s*[0-9a-zA-Z_]+/', $this->template_content)) {
preg_match_all('/' . $this->left_delimiter . '\s*list\s*name\s*=\s*([0-9a-zA-Z_]+)\s*(file=\s*([0-9a-zA-Z_,]+)|)\s*(iscache=\s*([0-9]{1})|)\s*(cachefile=\s*([^\s]+)|)\s*(libdir=\s*([0-9a-zA-Z_,]+)|)\s*(class=\s*([^%]+)|)' . $this->right_delimiter . '/', $this->template_content, $bearkarray);
foreach ($bearkarray[0] as $key => $variable) {
if (!empty($bearkarray[11][$key])) {
$textarray = array($bearkarray[0][$key], $bearkarray[1][$key], $bearkarray[2][$key], $bearkarray[3][$key], $bearkarray[4][$key], $bearkarray[5][$key], $bearkarray[6][$key], $bearkarray[7][$key], $bearkarray[8][$key], $bearkarray[9][$key], $bearkarray[10][$key], $bearkarray[11][$key]);
$newbearkText = $this->_parse_array__list($textarray, $this->left_delimiter, $this->right_delimiter);
$this->template_content = str_replace($variable, $newbearkText, $this->template_content);
}
}
$value_beark = '/' . $this->left_delimiter . '\s*list\s*name\s*=\s*([0-9a-zA-Z_]+)\s*(file=\s*([0-9a-zA-Z_,]+)|)\s*(iscache=\s*([0-9]{1})|)\s*(cachefile=\s*([^\s]+)|)\s*(libdir=\s*([0-9a-zA-Z_,]+)|)\s*(class=\s*([^%]+)|)' . $this->right_delimiter . '/';
$this->template_content = preg_replace($value_beark, $this->list_hash . '$1|$11|$3|$5|$7|$9|' . $this->list_hash, $this->template_content);
}
}
private function _parse_for() {
if (preg_match('/' . $this->left_delimiter . '\s*forlist[^\n]+' . $this->right_delimiter . '/', $this->template_content)) {
if (preg_match('/' . $this->left_delimiter . '\s*\/forlist\s*' . $this->right_delimiter . '/', $this->template_content)) {
preg_match_all('/\$this->_tpl_vars\[[\w\']+\]\[[\w]+\]\.[\w\[\]\.\\(\)\']+/', $this->template_content, $valueAt);
foreach ($valueAt[0] as $key => $variable) {
$arraylistNew = $this->_parse_value_preg($variable);
$this->template_content = preg_replace('/' . preg_quote($variable) . '/', $arraylistNew, $this->template_content, 1);
}
preg_match_all('/' . $this->left_delimiter . '\s*forlist\s*([$\w-\>\=.\s\[\]\']+)\s*' . $this->right_delimiter . '/', $this->template_content, $forlistarray);
for ($i = 0; $i < count($forlistarray[0]); $i++) {
$tag_args = $forlistarray[0][$i];
$attrs = $this->_parse_array_tag($tag_args);
if (empty($attrs['key']))
trigger_error('错误:FORLIST语句未设置key参数', E_USER_ERROR);
if (empty($attrs['from']))
trigger_error('错误:FORLIST语句未设置FROM参数', E_USER_ERROR);
$value_forlist = '/key=>([\w]*)/';
$this->template_content = preg_replace($value_forlist, "$$1+1", $this->template_content);
$value_forlist = '/list=>([\w]*)/';
$this->template_content = preg_replace($value_forlist, "$$1", $this->template_content);
$value_forlist = '/' . $this->left_delimiter . '\s*div=>([\w]+)=([\w]+)\s*' . $this->right_delimiter . '/';
if (preg_match($value_forlist, $this->template_content)) {
if (preg_match('/' . $this->left_delimiter . '\s*\/div=>([\w]+)\s*' . $this->right_delimiter . '/', $this->template_content)) {
$this->template_content = preg_replace($value_forlist, "<?php if(\$divid_$1==$2){ ?>", $this->template_content);
$value_forlist = '/' . $this->left_delimiter . '\s*\/div=>([\w]+)\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($value_forlist, "<?php \$divid_$1=0;}\$divid_$1++;?>", $this->template_content);
} else {
trigger_error('错误:div语句没有封闭', E_USER_ERROR);
}
}
$value_forlist = '/(\$this->_tpl_vars[^=]+)=>([\w]+)/';
$this->template_content = preg_replace($value_forlist, "$1[$$2]", $this->template_content);
$forlist_max = !empty($attrs['max']) ? $attrs['max'] : "count(" . $attrs['from'] . ")";
$patten_forlist = $attrs['from'];
$patten_forlist = '/' . $this->left_delimiter . '\s*forlist\s*' . preg_quote($forlistarray[1][$i]) . '\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($patten_forlist, "<?php if (count(" . $attrs['from'] . ")>0){\$divid_" . $attrs['key'] . "=1;for(\$" . $attrs['key'] . "=0;\$" . $attrs['key'] . "<" . $forlist_max . "; \$" . $attrs['key'] . "++){?>", $this->template_content);
}
$end_forlist = '/' . $this->left_delimiter . '\s*\/forlist\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($end_forlist, '<?php }} ?>', $this->template_content);
} else {
trigger_error('错误:语法错误,没有封闭FORLIST条件语句', E_USER_ERROR);
}
}
}
private function _parse_link() {
if (preg_match("/" . $this->left_delimiter . "\s*link\s*file=[\'|\"]([^%]+)[\'|\"]\s*" . $this->right_delimiter . "/", $this->template_content, $file)) {
if (trim($file[1]) == '')
exit('错误:包含文件不能为空');
$include_patten = '/' . $this->left_delimiter . '\s*link\s*file=[\'|\"]([^%]+)[\'|\"]\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($include_patten, $this->link_hash . $this->templates_themss_dirname . '$1|' . $this->link_hash, $this->template_content);
}
return true;
}
private function _parse_pack() {
if (preg_match('/' . $this->left_delimiter . '\s*pack:[0-9a-zA-Z_-]+\s*/', $this->template_content)) {
preg_match_all('/' . $this->left_delimiter . '\s*pack:[0-9a-zA-Z_-]+\s*(class=[^\s]+\s*|)' . $this->right_delimiter . '/', $this->template_content, $getarray);
foreach ($getarray[0] as $key => $variable) {
$packarray = array();
$pack_class_str = null;
preg_match_all('/' . $this->left_delimiter . '\s*pack:([0-9a-zA-Z_-]+)\s*(class=([^\s]+)\s*|)' . $this->right_delimiter . '/', $variable, $packarray);
if ($packarray[3][0]) {
$pack_class_str = $this->_parse_array_pack($packarray[3][0]);
}
$this->template_content = str_replace($packarray[0][0], $this->pack_hash . $packarray[1][0] . '|' . $pack_class_str . $this->pack_hash, $this->template_content);
}
}
}
private function _parse_array_pack($bearkarray) {
$classvar = explode(',', $bearkarray);
$newarray = array();
foreach ($classvar as $key => $variable) {
if (strstr($variable, '$this->_tpl_vars')) {
$echo_patten = '/(\$this->[^\,]+])/';
$newarray[$key] = preg_replace($echo_patten, "<?php echo $1 ?>", $variable);
} else {
$newarray[$key] = $variable;
}
}
if (is_array($newarray)) {
$newText = implode(',', $newarray);
} else {
$newText = false;
}
return $newText;
}
private function _parse_find() {
if (preg_match('/' . $this->left_delimiter . '\s*find:[0-9a-zA-Z_]+\s*class*=\s*/', $this->template_content)) {
preg_match_all('/' . $this->left_delimiter . '\s*find:[0-9a-zA-Z_]+\s*class=[^\s]+\s*out=[^%]+\s*' . $this->right_delimiter . '/', $this->template_content, $getarray);
foreach ($getarray[0] as $key => $variable) {
$bearkarray = array();
preg_match_all('/' . $this->left_delimiter . '\s*find:([0-9a-zA-Z_]+)\s*class=([^\s]+)\s*out=([^%]+)\s*' . $this->right_delimiter . '/', $variable, $bearkarray);
$this->_parse_array_find($bearkarray);
}
}
}
private function _parse_array_find($bearkarray) {
if (strstr($bearkarray[2][0], '$this->_tpl_vars')) {
$bearkarray[4][0] = str_replace($bearkarray[2][0], "<?php echo " . $bearkarray[2][0] . "?>", $bearkarray[2][0]);
} else {
$bearkarray[4][0] = $bearkarray[2][0];
}
$this->template_content = str_replace($bearkarray[0][0], $this->find_hash . $bearkarray[1][0] . '|' . $bearkarray[4][0] . '|' . $bearkarray[3][0] . $this->find_hash, $this->template_content);
}
private function _parse_class() {
if (preg_match('/' . $this->left_delimiter . '\s*class\s*=>\s*[^%]+\s*' . $this->right_delimiter . '/', $this->template_content)) {
$fun_patten = '/class\s*=>\s*([^\)]+\))/';
$this->template_content = preg_replace($fun_patten, "\$this->$1", $this->template_content);
}
return true;
}
private function _parse_if() {
if (preg_match('/' . $this->left_delimiter . '\s*if\s*[^%]+\s*' . $this->right_delimiter . '/', $this->template_content)) {
if (preg_match('/' . $this->left_delimiter . '\s*\/if\s*' . $this->right_delimiter . '/', $this->template_content)) {
$if_patten = '/' . $this->left_delimiter . '\s*if\s*([^%]+)\s*' . $this->right_delimiter . '/';
$elseif_patten = '/' . $this->left_delimiter . '\s*elseif\s*([^%]+)\s*' . $this->right_delimiter . '/';
preg_match_all($if_patten, $this->template_content, $forlistarray);
$else_patten = '/' . $this->left_delimiter . '\s*else\s*' . $this->right_delimiter . '/';
$ef_patten = '/' . $this->left_delimiter . '\s*\/if\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($if_patten, "<?php if($1){ ?>", $this->template_content);
$this->template_content = preg_replace($elseif_patten, "<?php } elseif($1){ ?>", $this->template_content);
$this->template_content = preg_replace($else_patten, '<?php }else{ ?>', $this->template_content);
$this->template_content = preg_replace($ef_patten, '<?php } ?>', $this->template_content);
} else {
exit('错误:语法错误,没有封闭IF条件语句');
}
}
return true;
}
private function _parse_fun() {
if (preg_match('/\$this->_tpl_vars[\'\w\$\[\]]*\|[^%]*/', $this->template_content)) {
$fun_patten = '/(\$this->_tpl_vars[\'\w\$\[\]]*)\|([\w]*)\(([^\)]*)\)/';
$this->template_content = preg_replace($fun_patten, "\$2($1,$3)", $this->template_content);
}
if (preg_match('/\$this->_tpl_vars[\'\w\$\[\]]*\|[^%]*/', $this->template_content)) {
$fun_patten = '/(\$this->_tpl_vars[\'\w\$\[\]]*)\|([\w]*)/';
$this->template_content = preg_replace($fun_patten, "$2($1)", $this->template_content);
}
if (preg_match('/("|\')\s*[^"\']+\s*("|\')\|[^%]*/', $this->template_content)) {
$fun_patten = '/(["|\']\s*[^"\']+\s*["|\'])\|([\w]*)\(([^\)]*)\)/';
$this->template_content = preg_replace($fun_patten, "\$2($1,$3)", $this->template_content);
}
if (preg_match('/(@this->[a-zA-z0-9]+)(\([^\)]*\))/', $this->template_content)) {
$fun_patten = '/@(this->[a-zA-z0-9]+)(\([^\)]*\))/';
$this->template_content = preg_replace($fun_patten, "$$1$2", $this->template_content);
}
}
private function _parse_echo() {
if (preg_match('/' . $this->left_delimiter . '\s*([^%]+)\s*' . $this->right_delimiter . '/', $this->template_content)) {
$echo_patten = '/' . $this->left_delimiter . '\s*([^%]+)\s*' . $this->right_delimiter . '/';
$this->template_content = preg_replace($echo_patten, "<?php echo $1 ?>", $this->template_content);
}
}
private function _parse_array__list($bearkarray, $left_delimiter, $right_delimiter) {
$classvar = explode(',', $bearkarray[11]);
$newarray = array();
foreach ($classvar as $key => $variable) {
if (strstr($variable, '$this->_tpl_vars')) {
$echo_patten = '/(\$this->[^\,]+]|[\w]+\(\$this->[^\,]+]\))/';
$newarray[$key] = preg_replace($echo_patten, "<?php echo $1 ?>", $variable);
} else {
$newarray[$key] = $variable;
}
}
if (strstr($bearkarray[7], '$this->_tpl_vars')) {
$bearkarray[7] = preg_replace('/(\$this->[^\,]+])/', "<?php echo $1 ?>", $bearkarray[7]);
}
$bearkarray[11] = implode(',', $newarray);
$left_delimiter = str_replace("\\", "", $left_delimiter);
$right_delimiter = str_replace("\\", "", $right_delimiter);
$iscachestr = !empty($bearkarray[5]) ? " iscache=" . $bearkarray[5] : '';
$cachefile = !empty($bearkarray[7]) ? " cachefile=" . $bearkarray[7] : '';
$libdir = !empty($bearkarray[9]) ? " libdir=" . $bearkarray[9] : '';
if ($bearkarray[11]) {
$newText = $left_delimiter . "list name=" . $bearkarray[1] . " " . $bearkarray[2] . $iscachestr . $cachefile . $libdir . " class=" . $bearkarray[11] . $right_delimiter;
} else {
$newText = $left_delimiter . "list name=" . $bearkarray[1] . " " . $bearkarray[2] . $iscachestr . $cachefile . $libdir . $right_delimiter;
}
return $newText;
}
private function _parse_array__get($bearkarray, $left_delimiter, $right_delimiter) {
$classvar = explode(',', $bearkarray[7][0]);
$newarray = array();
foreach ($classvar as $key => $variable) {
if (strstr($variable, '$this->_tpl_vars')) {
$echo_patten = '/(\$this->[^\,]+]|[\w]+\(\$this->[^\,]+]\))/';
$newarray[$key] = preg_replace($echo_patten, "<?php echo $1 ?>", $variable);
} else {
$newarray[$key] = $variable;
}
}
if (strstr($bearkarray[5][0], '$this->_tpl_vars')) {
$echo_patten = '/(\$this->[^\,]+])/';
$bearkarray[5][0] = preg_replace($echo_patten, "<?php echo $1 ?>", $bearkarray[5][0]);
}
$bearkarray[7][0] = implode(',', $newarray);
$left_delimiter = str_replace("\\", "", $left_delimiter);
$right_delimiter = str_replace("\\", "", $right_delimiter);
$iscachestr = !empty($bearkarray[3][0]) ? " iscache=" . $bearkarray[3][0] : '';
$cachefile = !empty($bearkarray[5][0]) ? " cachefile=" . $bearkarray[5][0] : '';
if ($bearkarray[7][0]) {
$newText = $left_delimiter . "get name=" . $bearkarray[1][0] . $iscachestr . $cachefile . " class=" . $bearkarray[7][0] . $right_delimiter;
} else {
$newText = $left_delimiter . "get name=" . $bearkarray[1][0] . $iscachestr . $cachefile . $right_delimiter;
}
return $newText;
}
private function _parse_array_tag($arraylist) {
preg_match_all('/\s*([\w]+)\s*=\s*([$\w->\[\]\'\"]+)\s*/', $arraylist, $arg_list);
for ($i = 0; $i < count($arg_list[1]); $i++) {
$attrs[$arg_list[1][$i]] = $arg_list[2][$i];
}
return $attrs;
}
private function _parse_value_preg($value) {
$arraylist = preg_split("/(\])\./", $value);
$arraycount = count($arraylist);
foreach ($arraylist as $key => $variable) {
if (($key + 1) != $arraycount) {
if ($key == 0) {
$variableFind = str_replace('[', '', strrchr($variable, '['));
$variableText = str_replace('[' . $variableFind, '', $variable);
$arraylistNew = $variableText . "[$$variableFind]";
} else {
$variableFind = str_replace('[', '', strrchr($variable, '['));
$variableText = str_replace('[' . $variableFind, '', $variable);
$arraylistNew .= "['$variableText'][$$variableFind]";
}
} else {
$variableFun = strrchr($variable, '|');
$variableText = str_replace($variableFun, '', $variable);
$arraylistNew .= "['$variableText']$variableFun";
}
}
return $arraylistNew;
}
}