<?php
abstract class Tag{

	 //标签左符号
	 public $left;

	 //标签右符号
	 public $right;
	
	 /**
     * 构造函数
     */
    public function __construct(){
        //左侧标签
        $this->left = C("TPL_TAG_LEFT");
        //右侧标签
        $this->right = C("TPL_TAG_RIGHT");
        if (method_exists($this, '__init')) {
            $this->__init();
        }
    }

	/**
     * 解析标签
     * @param array   $tag         标签
     * @param content $ViewContent 模板解析内容
     * @return mixed
     */
	public function parseTag($tag,$tplName, &$ViewContent, &$View,$method = false,$taglist = false){
		 
        if ($this->Tag[$tag]['block']==1) {
         //块标签解析
         $preg = '#' . $this->left . '(?:' . $tag . '|' . $tag . '\s+(.*))'
                . $this->right . '(.*)' .
                  $this->left[0] . '/' . substr($this->left, 1) . $tag
                . $this->right . '#isU';
		
		}elseif($this->Tag[$tag]['block']==2){
			//行标签处理
           $preg = '#' . $this->left . '(?:' . $tag . '|' . $tag . '\s+(.*))'
                   . $this->right . "#isU"; //独立正则
        }else{
           //行标签处理
           $preg = '#' . $this->left . '(?:' . $tag . '|' . $tag . '\s+(.*))/'
                   . $this->right . "#isU"; //独立正则
			
        }

        /**
         * 找到所有当前标签名的内容区域
         * 变量info说明
         * 0) 全部匹配内容
         * 1) 属性部分
         * 2) 内容部分
         */
        $status = preg_match_all($preg, $ViewContent, $info, PREG_SET_ORDER);
		
        if ($status) {
            foreach ($info as $i=>$k) {

                //属性解析
                if (empty($k[1])) {
                    $attr = array();
                }elseif($method){
						
					$attr = $this->parseTagAttr($k[1]);
					$attr['tpl']=$tplName;
				
				}else{
				    $attr = $k[1];
                }
                 //标签内容
                $k[2]        = isset($k[2]) ? $k['2'] : '';
				$tagcont[$i]['name']   = $tag;
				$tagcont[$i]['attr']   = $attr;
				$tagcont[$i]['content']= $k[2];
				$content     = call_user_func_array(array($this, '_' . $tag), array($attr, $k[2], &$View));
				$ViewContent = str_replace($k[0], $content, $ViewContent);
			
            }
			if ($taglist){
				 return $tagcont;
			}else{
				 return true;
			}
        } else {
            return false;
        }
    }

	 /**
     * 解析标签属性
     * @param string $attrStr 标签字符串
     * @return array 标签名如foreach
     */
    protected function parseTagAttr($attrStr){
			
        $pregAttr = '#' . '([a-z_]+)=(["\'])(.*)\2#iU'; //属性正则
        /**
         * $info说明
         * 0 完整内容
         * 1 引号
         * 3 属性值
         */
        $status = preg_match_all($pregAttr, $attrStr, $info, PREG_SET_ORDER);
	
        if ($status) {
            $attr = array();
            foreach ($info as $k) {
                //解析属性值
                $attr[$k[1]] = $this->parseAttrValue($k[3]);
            }

            return $attr;
        } else {
            return array();
        }
    }

    /**
     * 解析属性值
     * @param $attrValue 属性值
     * @return mixed
     */
    protected function parseAttrValue($attrValue){
		
        //替换常量值
        $const = get_defined_constants(true);
        foreach ($const['user'] as $name => $value) {
            //替换以__开始的常量
            if (substr($name, 0, 2) == '__') {
                $attrValue = str_ireplace($name, $value, $attrValue);
            }
        }

        //解析变量为PHP可识别状态
        $preg   = '@\$([\w\.]+)@i';
        $status = preg_match_all($preg, $attrValue, $info, PREG_SET_ORDER);
		
        if ($status) {
            foreach ($info as $i => $d) {
                $var  = '';
                $data = explode('.', $d[1]);
			
                foreach ($data as $n => $m) {
                    if ($n == 0) {
                        $var .= $m;
                    } else {
                        $var .= "['$m']";
                    }
                }	
                $attrValue = str_replace($d[1], $var, $attrValue);
				
            }
            return $attrValue;
        } else {
		
            return $attrValue;
        }
    }
	
	/**
     * 解析数组属性
     * @param $attrValue 属性值
     * @return 返回可写入的数组
     */
	protected function parseAttrArr($attr=array()){	

        $preg   = '@\$([\w\.]+)@i';

		if (empty($attr)) {
			return ;
		}
		foreach($attr as $k=>$v){
			//解析变量为PHP可识别状态
			if(preg_match_all($preg, $v, $info, PREG_SET_ORDER)){
				$attr_arr[$k] .= "'".$k."'=>".$v;
			}else{
				$attr_arr[$k] .= "'".$k."'=>'".$v."'";
			}
		}

		$attr_arr = 'array('.implode(',',$attr_arr).')';
		
		return $attr_arr;
	}

}
?>