<?php
/*
# @category: 分享工作室;
# @copyright: 分享在线传媒公社;
# @var; PHPnew.class ;
# @version: PHPnew 7.1 Professional;
*/
defined('IN_SYSTEM') === false && exit('PHPnew Blog.');
define('PHPNEW_STATIC_TPL',true);
class PHPnew {
	public $templates_dir = './Static/Default/'; //模板路径;
	public $templates_cache = './Data/cache_tpl/'; //缓存模板路径;
	public $templates_default = './Static/Default/'; //默认模板路径;
	public $templates_new = false; //设置当次更新, 系统更新可强制配置为true;
	
	public $templates_postfix = '.tpl.php'; //模板后缀;
	public $templates_auto = true; //自动更新模板;
	public $templates_caching = '.php'; //缓存后缀;
	public $templates_space = false; //清除无意义字符
	public $templates_php =''; //为每个缓存头部增加PHP码;
	
    //结果集;
	public $templates_file = array(); //模板文件
	public $templates_cache_file = array(); //缓存文件;
	public $templates_name = null; //标识名
	public $templates_message = null; //html内容;
	public $templates_update = 0; //更新次数
	public $templates_assign = array(); //用户用smarty模式;
    public $templates_debug = array(); //错误信息;
	public $PHPnew = 'PHPnew 7.2 CACHE_TPL';
    public $temp_var = array();
    
	public $templates_replace = array(); //用于智能更新,可以将模板中的内容直接替换;

	//解析开始;
	public function display($PHPnew_file_name){
        $temp_var = $this->fun_parse_path($PHPnew_file_name);
        # 变量释放
        $this->templates_name = $PHPnew_file_name;
        $this->templates_cache_file[$this->templates_name] = $temp_var['cache'];
        $this->templates_file[$this->templates_name] = $temp_var['tpl'];
        $this->templates_debug[$this->templates_name] = array();
        # 判断是否需要更新.
        $true_check = $this->fun_file_check($temp_var);
        unset($temp_var , $PHPnew_file_name);
        
        $this->fun_parse_var();
        
        if($true_check === true){
            return $this->fun_view($this->templates_cache_file[$this->templates_name]);
        }else{
            #以下过程将处理一次模板解析.
            $this->templates_message = $this->fun_parse_html(file_get_contents($this->templates_file[$this->templates_name], LOCK_EX));
    		$this->fun_view();
        }
	}
    
	private function fun_view($PHPnew_path = false){
	   if($PHPnew_path === false){
            $PHPnew_path = $this->templates_cache_file[$this->templates_name];
            file_put_contents($PHPnew_path, $this->templates_message, LOCK_EX);
            $this->templates_message = null;
            $this->templates_update += 1;
       }
    
       extract($this->templates_assign);
	   include_once($PHPnew_path);
	}
    
    private function fun_file_check($html_array){
        if($this->templates_new === true)
            return false;
        if(is_file($html_array['cache']) === false)
            return false;
        if(is_file($html_array['tpl']) === false)
            exit('File does not exist: '. $html_array['tpl']);
        
        return true;
    }
    
	//路径处理
	private function fun_parse_path($htmlfile){
		    if(is_file($htmlfile) === false){
                if(is_file($this->templates_dir . $htmlfile . $this->templates_postfix) === false){
                    $htmlfile = $this->templates_default . $htmlfile . $this->templates_postfix;
                }else{
                    $htmlfile = $this->templates_dir . $htmlfile . $this->templates_postfix;
                }
            }
           $md5 = $this->templates_auto === true? md5_file($htmlfile):md5($htmlfile);
           return array('tpl'=>$htmlfile,'cache'=>$this->templates_cache . $md5 . '_cache' . $this->templates_caching);
	}

	//假如用户用强制性;
	public function assign($phpnew_var, $phpnew_value = null){
		if(!$phpnew_var) return false;
		if(is_array($phpnew_var) === true){
		  $this->assign($php_val);
			foreach ($phpnew_var as $php_key => $php_val){
				$this->assign($php_key,$php_val);
            }
		} else{
            if(is_string($phpnew_value) === true || is_array($phpnew_value) === true || (is_object($phpnew_value) === false && is_resource($phpnew_value) === false)){
                $this->templates_assign[$phpnew_var] = $phpnew_value;
            }else{
                unset($phpnew_value);
            }
		}
	}
    
	private function fun_parse_var(){
		if(empty($this->templates_update) === true){
            $allvar = array_diff_key($GLOBALS, array ('GLOBALS'=>0,'_ENV'=>0,'HTTP_ENV_VARS'=>0,'ALLUSERSPROFILE'=>0,'CommonProgramFiles'=>0,'COMPUTERNAME'=>0,'ComSpec'=>0,'FP_NO_HOST_CHECK'=>0,'NUMBER_OF_PROCESSORS'=>0,'OS'=>0,'Path'=>0,'PATHEXT'=>0,'PROCESSOR_ARCHITECTURE'=>0,'PROCESSOR_IDENTIFIER'=>0,'PROCESSOR_LEVEL'=>0,'PROCESSOR_REVISION'=>0,'ProgramFiles'=>0,'SystemDrive'=>0,'SystemRoot'=>0,'TEMP'=>0,'TMP'=>0,'USERPROFILE'=>0,'VBOX_INSTALL_PATH'=>0,'windir'=>0,'AP_PARENT_PID'=>0,'uchome_loginuser'=>0,'supe_cookietime'=>0,'supe_auth'=>0,'Mwp6_lastvisit'=>0,'Mwp6_home_readfeed'=>0,'Mwp6_smile'=>0,'Mwp6_onlineindex'=>0,'Mwp6_sid'=>0,'Mwp6_lastact'=>0,'PHPSESSID'=>0,'HTTP_ACCEPT'=>0,'HTTP_REFERER'=>0,'HTTP_ACCEPT_LANGUAGE'=>0,'HTTP_USER_AGENT'=>0,'HTTP_ACCEPT_ENCODING'=>0,'HTTP_HOST'=>0,'HTTP_CONNECTION'=>0,'HTTP_COOKIE'=>0,'PATH'=>0,'COMSPEC'=>0,'WINDIR'=>0,'SERVER_SIGNATURE'=>0,'SERVER_SOFTWARE'=>0,'SERVER_NAME'=>0,'SERVER_ADDR'=>0,'SERVER_PORT'=>0,'REMOTE_ADDR'=>0,'DOCUMENT_ROOT'=>0,'SERVER_ADMIN'=>0,'SCRIPT_FILENAME'=>0,'REMOTE_PORT'=>0,'GATEWAY_INTERFACE'=>0,'SERVER_PROTOCOL'=>0,'REQUEST_METHOD'=>0,'QUERY_STRING'=>0,'REQUEST_URI'=>0,'SCRIPT_NAME'=>0,'PHP_SELF'=>0,'REQUEST_TIME'=>0,'argv'=>0,'argc'=>0,'_POST'=>0,'HTTP_POST_VARS'=>0,'_GET'=>0,'HTTP_GET_VARS'=>0,'_COOKIE'=>0,'HTTP_COOKIE_VARS'=>0,'_SERVER'=>0,'HTTP_SERVER_VARS'=>0,'_FILES'=>0,'HTTP_POST_FILES'=>0,'_REQUEST'=>0));
			foreach($allvar as $key => $val){
                $this->assign($key, $val);
			}
            unset($allvar);
		}
	}
    
	//替换函数;
	protected function fun_parse_html($template){
	    if(empty($template) === true)
            return $template;
     
		$template = preg_replace_callback("/[\n\r\t]*\{templatesub\s+(.+)\}[\n\r\t]*/sU", array($this,'get_contents'), $template);
		$template = preg_replace_callback('/[\n\r\t]*\<\?php.*\\?\>[\n\r\t]*/sU', create_function('$math',' return "[php]".base64_encode($math[0])."[/php]";'), $template);
        //替换语言包变量
        $template = preg_replace_callback("/[\n\r\t]*\{lang (.+)\}[\n\r\t]*/isU", array($this,'get_language'), $template);
        
		$template = preg_replace_callback("/[\n\r\t]*\{html\s+(.+)\}[\n\r\t]*/sU",array($this,'get_var'), $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);
		$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_callback("/$varRegexp/s", array($this,'addquote'), $template);
		$template = preg_replace_callback("/\<\?\=\<\?\=$varRegexp\?\>\?\>/is",array($this,'addquote'), $template);
  
		//替换特定函数
        $template = preg_replace_callback("/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/is",array($this,'stripvtags'), $template);
		$template = preg_replace_callback("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/is", array($this,'stripvtags'), $template);
        
        if(stripos($template, '{else') !== false){
    		$template = preg_replace_callback("/([\n\r\t]*)\{el[se ]*if\s+(.+?)\}([\n\r\t]*)/is", create_function('$math','
            $expr = "{$math[1]}<? }else if({$math[2]}){ ?>{$math[3]}";
            $expr = str_replace("\\\\\"", "\"", preg_replace("/\<\?\=(\\\\\$.+?)\?\>/s", "$1", $expr));
            return $expr;
            '), $template);
    		$template = preg_replace("/([\n\r\t]*)\{else\}([\n\r\t]*)/is", "\\1<? }else{ ?>$2", $template);
        }
        
		//主要是递归循环及判断.
        $loopa = "/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r]*(.+?)[\n\r]*\{\/loop\}[\n\r\t]*/is";
        $loopb = "/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*(.+?)[\n\r\t]*\{\/loop\}[\n\r\t]*/is";
        if(stripos($template, '{/loop}') !== false){
    		while(true){
                $template = preg_replace_callback($loopa, create_function('$math','
                 $expr = "<? if(is_array({$math[1]})===true){foreach({$math[1]} AS {$math[2]}){ ?>";
                $expr = str_replace("\\\\\"", "\"", preg_replace("/\<\?\=(\\\\\$.+?)\?\>/s", "$1", $expr));
                $statement = str_replace("\\\\\"", "\"", "{$math[3]}<? }} ?>");
                return $expr.$statement;'), $template);
                
                $template = preg_replace_callback($loopb, create_function('$math','
                $expr = "<? if(is_array({$math[1]})===true){foreach({$math[1]} AS {$math[2]} => {$math[3]}){ ?>";
                $expr = str_replace("\\\\\"", "\"", preg_replace("/\<\?\=(\\\\\$.+?)\?\>/s", "$1", $expr));
                $statement = str_replace("\\\\\"", "\"", "{$math[4]}<? }} ?>");
                return $expr.$statement;'), $template);
                
                if(stripos($template, '{/loop}') !== false){
                    preg_match($loopa, $template, $rega);
                    preg_match($loopb, $template, $regb);
                    if(!$rega && !$regb){
                        unset($loopa,$loopb, $rega, $regb);
                        break;
                    }
                }else{
                    unset($loopa,$loopb);
                    break;
                }
            }
        }
        
        $loopa = "/([\n\r\t]*)\{if\s+(.+?)\}([\n\r]*)(.+?)([\n\r]*)\{\/if\}([\n\r\t]*)/is";
        if(stripos($template, '{/if}') !== false){
    		while(true){
                $template = preg_replace_callback($loopa, create_function('$math','
                    $expr = "{$math[1]}<? if({$math[2]}){ ?>{$math[3]}";
                    $expr = str_replace("\\\\\"", "\"", preg_replace("/\<\?\=(\\\\\$.+?)\?\>/s", "$1", $expr));
                    $statement = str_replace("\\\\\"", "\"", "{$math[4]}{$math[5]}<? } ?>{$math[6]}");
                    return $expr.$statement;
                    '), $template);
                
                if(stripos($template, '{/if}') !== false){
                    preg_match($loopa, $template, $rega);
                    if(!$rega){
                        unset($loopa,$rega);
                        break;
                    }
                }else{
                    unset($loopa);
                    break;
                }
		  }
       }
         
		//常量替换
		$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_callback("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/s", array($this, 'transamp'), $template);
		$template = preg_replace_callback("/\<script[^\>]*?src=\"(.+?)\".*?\>\s*\<\/script\>/is",array($this, 'stripscriptamp'), $template);
		$template = preg_replace_callback("/[\n\r\t]*\{block\s+([a-zA-Z0-9_]+)\}(.+?)\{\/block\}/is", array($this, 'stripblock'), $template);
        
		$template = preg_replace_callback('/[\n\r\t]*\[php\](.*)\[\/php\][\n\r\t]*/isU', create_function('$math','
        if($math[1])
        return base64_decode($math[1]);
        return \'\';
        '), $template);
		$template = preg_replace_callback('/<script.+script>/isU', create_function('$math','
        if($math[0])
        return "[script]". base64_encode($math[0])."[/script]";
        return \'\';
        '), $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_callback('/\[script\](.+)\[\/script\]/isU',create_function('$math','
        if($math[1])
        return base64_decode($math[1]);
        return \'\';
        '), $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'));
		$template = strtr($template, array('<?php' => '<?', '<?php echo' => '<?='));
        
		$template = strtr($template, array('<?' => '<?php', '<?=' => '<?php echo '));
        if($this->templates_replace)
		$template = strtr($template, $this->templates_replace);
		return $template;
	}
	//模板引擎需要的函数. 开始.
    protected function get_language($var){
        $var[1] = ltrim($var[1], '$');
        if($this->templates_lang[$var[1]])
            return $this->templates_lang[$var[1]];
        return '';
    }
    
	protected function get_contents($array){
        $filename = trim($array[1]);
        $html_array = $this->fun_parse_path($filename);
        $this->templates_name = $filename;
        $this->templates_cache_file[$this->templates_name] = $html_array['cache'];
        $this->templates_file[$this->templates_name] = $html_array['tpl'];
		if(is_file($this->templates_file[$this->templates_name]) === true){
			$files = file_get_contents($this->templates_file[$this->templates_name], LOCK_EX);
            if(strpos($files, '{templatesub') !== false)
		      $files = preg_replace_callback("/[\n\r\t]*\{templatesub\s+(.+)\}[\n\r\t]*/isU", array($this,'get_contents'),$files);
			return $files;
		}
		return '';
	}
	protected function get_var($array){
	    $phpnew_name = ltrim(trim($array[1]),'$');
		if(empty($this->templates_assign[$phpnew_name]) === false)
			return $this->templates_assign[$phpnew_name];
		return '';
	}
	protected function transamp($template){
	   $template = trim($template[0]);
		$template = str_replace('&', '&amp;', $template);
		$template = str_replace('&amp;amp;', '&amp;', $template);
		$template = str_replace('\"', '"', $template);
		return $template;
	}
	protected function stripvtags($expr, $statement = ''){
	    $expr = "<? {$expr[1]};?>";
		$expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", '$1', $expr));
		$statement = str_replace("\\\"", "\"", $statement);
		return $expr . $statement;
	}

	protected function addquote($var){
	    $var = "<?={$var[1]}?>" ;
		return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
	}

	protected function stripscriptamp($s){
	    $s = trim($s[1]);
		$s = str_replace('&amp;', '&', $s);
		return "<script src=\"$s\" type=\"text/javascript\"></script>";
	}

	protected function stripblock($array){
	    $var = trim($array[1]);
        $s   = trim($array[2]);
		$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\n" . $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);
    		}
        }else{
            if(is_file($path) === true)
                unlink($path);
        }
	}
}