<?php
/*
# @category: 分享工作室;
# @copyright: 分享在线传媒公社;
# @var; PHPnew.class ;
# @version: PHPnew 7.0 Professional;
*/
//模板引擎解析类;
class PHPnew
{
const PHP = 5; //PHP限制版本;
public $templates_dir = 'Templates/default/'; //模板路径;
public $templates_cache = 'Data/cache_tpl/'; //缓存模板路径;
public $templates_default = 'Templates/default/'; //默认模板路径;
public $templates_new = true; //设置当次更新;
public $templates_time = 360; //过期时间,分钟计算;
//以下的默认设置
public $templates_charset = 'utf-8';
public $templates_postfix = '.html'; //模板后缀;
public $templates_auto = true; //自动更新模板;
public $templates_caching = '.php'; //缓存后缀;
public $templates_debug = array(); //错误信息;
public $templates_lonlabel = true; //长标签;
public $templates_space = false; //清除无意义字符
public $templates_php = false; //为每个缓存头部增加PHP码;
//结果集;
public $templates_file = array(); //模板文件
public $templates_cache_file = null; //缓存文件;
public $templates_name = null; //标识名
public $templates_message = null; //html内容;
public $templates_update = 0; //更新次数
public $templates_assign = array(); //用户用smarty模式;
public $PHPnew = 'PHPnew 7.0 Professional';
//缓存控制;
public $templates_menu = array(); //用于记录每个模板信息;
public $templates_replace = array(); //用于智能更新,可以将模板中的内容直接替换;
//构造函数
public function __construct()
{
// 确认php版本,低过设置的, 就提供一下debug出去。但不终止。
if((int) phpversion() < self::PHP)
$this->templates_debug[] = 'PHP version is too low ' .self::PHP;
//为属性作初级判断;
$this->templates_auto = (boolean) $this->templates_auto;
$this->templates_lonlabel = (boolean) $this->templates_lonlabel;
$this->templates_space = (boolean) $this->templates_space;
$this->templates_new = (boolean) $this->templates_new;
//禁止默认模板目录不存在
is_dir($this->templates_default) === false && exit('error templates_default');
//为控制设置流程,先引入配置文件, 里面记录着所有缓存文件的时间。
if(is_file($this->templates_cache.'templates_caceh.php') && $this->templates_auto===true)
$this->templates_menu = include($this->templates_cache.'templates_caceh.php');
}
//解析开始;
public function display($file_name){
// 初始化先设置变量信息
$var_list = $this->parse_var();
//取得路径;
$this->templates_file[$file_name] = $this->get_path($file_name);
//取得文件名字;
$this->templates_name = $file_name;
//取得缓存路径;
$this->templates_cache_file[$file_name] = $this->get_path();
// 如果不自动更新,就直接调用缓存。
if($this->templates_auto===false){
return $this->view($this->templates_cache_file[$file_name]);
}
//如果设置了当次更新,就将配置数组清空.
if($this->templates_new===true){
$this->templates_menu = array();
}
//判断一下文件是否存在。 是否已经过期,然后生成并且显示。
if($this->check($this->templates_name)===true){
return $this->view($this->templates_cache_file[$file_name]);
}
$this->templates_message = null;
if(is_file($this->templates_file[$this->templates_name]) == true)
$this->templates_message = $this->replace_html(file_get_contents($this->templates_file[$this->templates_name],LOCK_EX));
$this->templates();
return $this->view($this->fileplus());
}
//显示出来;
private function view($path_php){
//释放数组内容。
if(empty($this->templates_assign) === false)
extract($this->templates_assign,EXTR_OVERWRITE);
if(is_file($path_php) === true){
include($path_php);
}else {
print $path_php.' Does not exist<br>';
}
return true;
}
private function parse_var(){
static $var_list;
if(empty($var_list) === true){
$list = array();
foreach ($GLOBALS as $key => $val)
{
$list[$key] = $val;
}
$var_list = $list;
foreach ($var_list as $phpnew_key =>$phpnew_value){
$this->assign($phpnew_key,$phpnew_value);
}
}
return $this->templates_assign;
}
//生成缓存
private function fileplus()
{
file_put_contents($this->templates_cache_file[$this->templates_name],$this->templates_message,LOCK_EX);
$this->templates_message = array();
return $this->templates_cache_file[$this->templates_name];
}
//控制配置
private function templates(){
if(empty($this->templates_menu[$this->templates_name]) === false)
unset($this->templates_menu[$this->templates_name]);
if(is_array($this->templates_menu)===false)
$this->templates_menu = array();
if(is_file($this->templates_file[$this->templates_name]) == true)
$this->templates_menu[$this->templates_name] = md5_file($this->templates_file[$this->templates_name]);
if(($php = null) && empty($this->templates_php) === false)
$php = $this->templates_php."\r\n";
file_put_contents($this->templates_cache.'templates_caceh.php',
sprintf($php."<?php \r\n return %s;",var_export($this->templates_menu,true)),LOCK_EX);
}
//路径处理
private function get_path($file_name=null){
//为默认路径做完整路径抓取;
$this->path();
if($file_name!==null){
$file_all = $this->templates_dir.$file_name.$this->templates_postfix;
if($this->templates_dir===null || is_file($file_all)===false){
$file_all = realpath($this->templates_default).DIRECTORY_SEPARATOR.$file_name.$this->templates_postfix;
}
if(is_file($file_all)===false){
return false;
$this->templates_debug[] = 'Template file does not exist or an error';
}
return (string) $file_all;
}else {
$file = $this->templates_file[$this->templates_name];
$file_arr = pathinfo($file);
$postfix = basename(dirname($file));
return $this->templates_cache.$postfix.'_'.$this->templates_name.'_cache'.$this->templates_caching;
}
return false;
}
// 路径规范处理;
private function path(){
$this->templates_dir = realpath(strtr($this->templates_dir,array('./'=>'','//'=>'/','\\\\'=>'\\'))).DIRECTORY_SEPARATOR;
$this->templates_cache = realpath(strtr($this->templates_cache,array('./'=>'','//'=>'/','\\\\'=>'\\'))).DIRECTORY_SEPARATOR;
// 不能判断目录是否存在, 因为还有默认目录功能。
if(strlen($this->templates_dir)<=2)
exit('Catalog Error');
if(strlen($this->templates_cache)<=2)
exit('Catalog Error');
}
//控制判断
private function check($name){
//对文件及目录判断
if(strlen($this->templates_name)===0){
$this->templates_name = 'index';
}
// 检查默认模板目录是否存在
if(is_dir($this->templates_dir)===false){
exit('Templates directory does not exist');
}
// 检查缓存模板目录是否存在
if(is_dir($this->templates_cache)===false){
exit('Template cache directory does not exist');
}
// 判断缓存文件是否存在,不存在就报错.
if(is_file($this->templates_file[$name])===false){
exit('Template does not exist: '.$name);
}
// true 让判断成真,即返回缓存文件 // false 将执行编译;
if(empty($this->templates_menu)===true)
return false;
if(time() - fileatime($this->templates_cache.'templates_caceh.php')>=$this->templates_time*60){
if(is_file($this->templates_cache.'templates_caceh.php') === true)
unlink($this->templates_cache.'templates_caceh.php');
return false;
}
if(empty($this->templates_menu[$name]) === false && md5_file($this->templates_file[$name])===$this->templates_menu[$name]){
return true;
}
return false;
}
//假如用户用强制性;
public function assign($phpnew_var,$phpnewvalue=null){
$php_key = $php_val = null;
if($phpnew_var=='')
return false;
if(is_array($phpnew_var)===true){
foreach ($phpnew_var as $php_key => $php_val){
if(is_array($php_val)===true){
$this->assign($php_val);
}
if(is_numeric($php_key)===false || $php_key{0}!='_')
$this->templates_assign[$php_key] = $php_val;
}
}else {
if(is_numeric($phpnew_var)===false || $phpnew_var{0}!='_')
$this->templates_assign[$phpnew_var] = $phpnew_value;
}
}
//替换函数;
protected function replace_html($template){
//替换
$template = preg_replace(
"/[\n\r\t]*\{templatesub\s+(.+)\}[\n\r\t]*/iseU",
"\$this->get_contents('$1')",
$template
);
//直接输出php
$template = preg_replace('/[\n\r\t]*\<\?php.*\\?\>[\n\r\t]*/iseU',
'\'[php]\'.base64_encode(\'$0\').\'[/php]\'',
$template
);
//静态替换
$template = preg_replace(
"/[\n\r\t]*\{html\s+(.+?)\}[\n\r\t]*/ise",
"\$this->get_var('$1')",
$template
);
//替换模板载入命令
$template = preg_replace(
"/[\n\r\t]*\{template\s+\\$(.+)\}[\n\r\t]*/isU",
'<? include display(-%-$1); ?>',
$template
);
$template = preg_replace(
"/[\n\r\t]*\{template\s+(.+)\}[\n\r\t]*/isU",
"<? include display('$1'); ?>",
$template
);
//过滤 <!--{}-->
$template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
//替换 PHP 换行符
$template = str_replace("{LF}", "<?=\"\\n\"?>", $template);
//替换直接变量输出
$varRegexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)"
. "(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
$template = preg_replace("/\{(\\\$[a-zA-Z0-9_\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
$template = preg_replace("/$varRegexp/es", "\$this->addquote('<?=\\1?>')", $template);
$template = preg_replace("/\<\?\=\<\?\=$varRegexp\?\>\?\>/es", "\$this->addquote('<?=\\1?>')", $template);
//替换语言包变量
$template = preg_replace("/\{lang\s+(.+?)\}/is", "<?=\$language['\\1']?>", $template);
//替换特定函数
$template = preg_replace(
"/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/ies",
"\$this->stripvtags('<? \\1; ?>','')",
$template
);
$template = preg_replace(
"/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies",
"\$this->stripvtags('<? \\1; ?>','')",
$template
);
$template = preg_replace(
"/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/ies",
"\$this->stripvtags('\\1<? } elseif(\\2) { ?>\\3','')",
$template
);
$template = preg_replace(
"/([\n\r\t]*)\{else\}([\n\r\t]*)/is",
"\\1<? } else { ?>\\2",
$template
);
//替换循环函数及条件判断语句
for ($i = 0; $i < 6; $i++) {
$template = preg_replace(
"/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r]*(.+?)[\n\r]*\{\/loop\}[\n\r\t]*/ies",
"\$this->stripvtags('<? if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\\3<? } } ?>')",
$template
);
$template = preg_replace(
"/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*(.+?)[\n\r\t]*\{\/loop\}[\n\r\t]*/ies",
"\$this->stripvtags('<? if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\\4<? } } ?>')",
$template
);
$template = preg_replace(
"/([\n\r\t]*)\{if\s+(.+?)\}([\n\r]*)(.+?)([\n\r]*)\{\/if\}([\n\r\t]*)/ies",
"\$this->stripvtags('\\1<? if(\\2) { ?>\\3','\\4\\5<? } ?>\\6')",
$template
);
}
//常量替换
$template = preg_replace(
"/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/s",
"<?=\\1?>",
$template
);
//删除 PHP 代码断间多余的空格及换行
$template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
//其他替换
$template = preg_replace(
"/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/e",
"\$this->transamp('\\0')",
$template
);
$template = preg_replace(
"/\<script[^\>]*?src=\"(.+?)\".*?\>\s*\<\/script\>/ise",
"\$this->stripscriptamp('\\1')",
$template
);
$template = preg_replace(
"/[\n\r\t]*\{block\s+([a-zA-Z0-9_]+)\}(.+?)\{\/block\}/ies",
"\$this->stripblock('\\1', '\\2')",
$template
);
$template = preg_replace('/[\n\r\t]*\[php\](.*)\[\/php\][\n\r\t]*/iseU','base64_decode(\'\\1\')',$template);
$template = preg_replace('/<script.+script>/iseU','\'[script]\'.base64_encode(\'$0\').\'[/script]\'',$template);
if ($this->templates_space===true) {
$template = preg_replace(
array('/\r\n/isU','/<<<EOF/isU'),array('',"\r\n<<<EOF\r\n"),$template);
}
$template = preg_replace('/[\n\r\t]*\[script\](.+)\[\/script\][\n\r\t]*/iseU','base64_decode(\'$1\')',$template);
$template = strtr($template,array('-%-'=>'$','\"'=>'"','<style>'=>'<style type="text/css">','<script>'=>'<script type="text/javascript">'));
if(empty($this->templates_php) === false)
$template = $this->templates_php."\r\n".$template;
$template = strtr($template,array('include display'=>'$this->display'));
if($this->templates_lonlabel===true){
$template = strtr($template,
array('<?php'=>'<?','<?php echo'=>'<?='));
$template = strtr($template,
array('<?'=>'<?php ','<?='=>'<?php echo '));
}
$template = strtr($template,$this->templates_replace);
$this->templates_update +=1;
return (string) $template;
}
//模板引擎需要的函数. 开始.
protected function get_contents($filename){
$this->templates_file[$filename] = $this->get_path($filename);
if(is_file($this->get_path($filename)) === true){
$files = file_get_contents($this->templates_file[$filename],LOCK_EX);
//替换
$files = preg_replace(
"/[\n\r\t]*\{templatesub\s+(.+)\}[\n\r\t]*/iseU",
"\$this->get_contents('$1')",
$files
);
return $files;
}
return false;
}
protected function get_var($phpnew_name){
if(empty($this->templates_assign[$phpnew_name]) === false)
return $this->templates_assign[$phpnew_name];
return 'Static variable is not defined';
}
protected function transamp($template) {
$template = str_replace('&', '&', $template);
$template = str_replace('&amp;', '&', $template);
$template = str_replace('\"', '"', $template);
return $template;
}
protected function stripvtags($expr, $statement) {
$expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
$statement = str_replace("\\\"", "\"", $statement);
return $expr . $statement;
}
protected function addquote($var) {
return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
}
protected function stripscriptamp($s) {
$s = str_replace('&', '&', $s);
return "<script src=\"$s\" type=\"text/javascript\"></script>";
}
protected function stripblock($var, $s) {
$s = str_replace('\\"', '"', $s);
$s = preg_replace("/<\?=\\\$(.+?)\?>/", "{\$\\1}", $s);
preg_match_all("/<\?=(.+?)\?>/e", $s, $constary);
$constadd = '';
$constary[1] = array_unique($constary[1]);
foreach($constary[1] as $const) {
$constadd .= '$__' . $const .' = ' . $const . ';';
}
$s = preg_replace("/<\?=(.+?)\?>/", "{\$__\\1}", $s);
$s = str_replace('?>', "\n\$$var .= <<<EOF\n", $s);
$s = str_replace('<?', "\nEOF;\n", $s);
return "<?php\n$constadd\$$var = <<<EOF" . $s . "\nEOF;\n?>";
}
//删除缓存;
public function cache_dele($path = null){
if($path===null){
$path = $this->templates_cache;
}
$file_arr = scandir($path);
foreach ($file_arr as $val){
if($val === '.' || $val === '..'){
continue;
}
if(is_dir($path.$val)===true)
$this->cache_dele($path.$val.'/');
if(is_file($path.$val)===true && $val!=='index.html')
unlink($path.$val);
}
}
public function __destruct(){}
}