<?php
/**
 * 解析标签类
 * @author e启学chen
 *
 */
class ParseTagModel {
	private $left = "<";
	private $right = ">";
	private $sgin = "";
	/**
	 * 输入的内容
	 * @var string
	 */
	private $content;
	
	private $replace = true;
	
	private $scope = false;
	
	/**
	 * 解析出来的Tags
	 * @var array
	 */
	private static $tags = array ();
	private $fileObject = null;
	
	/**
	 +----------------------------------------------------------
	 * 架构函数
	 +----------------------------------------------------------
	 * @author melec制作
	 * @access public
	 +----------------------------------------------------------
	 */
	public function __construct() {
		//TODO 扫描目录
	
	
		$icopath = ADDON_PATH . DIRECTORY_SEPARATOR . "diywidget" . DIRECTORY_SEPARATOR . "Tags";
		if (! is_dir ( $icopath )) {
			return $this;
		}
		if (empty ( self::$tags )) {
			self::$tags = self::traversalDir ( $icopath );
		}
	}
	/**
	 * 解析并得到替换后的内容
	 * 解析整个字符串中的标签
	 * 用于预览功能
	 * @param $content string
	 */
	public function parse($content, $replace = true, $scope = false) {
		$this->replace = $replace;
		$this->scope = $scope;
		foreach ( self::$tags as $tagName => $path ) {
			$content = $this->pregReplaceTag ( $tagName, $path, $content, $replace );
		}
		return $content;
	}
	/**
	 * 解析已有的模块
	 * @param unknown_type $content
	 * @param unknown_type $cacheOpen
	 * @return mixed
	 */
	public function parseId($content, $cacheOpen = true) {
		$preg = "/\[widget:(\w+)\]/siU";
		preg_match_all ( $preg, $content, $pluginIds );
		$pluginIds = array_merge ( array_filter ( $pluginIds ) );
		$pluginIds = array_combine ( $pluginIds [0], $pluginIds [1] );
		$data = model ( 'DiyWidget' )->getTagInofs ( $pluginIds );
		foreach ( $pluginIds as $key => $value ) {
			$widgetKey = $value;
			$tagInfo = $data [$value];
			if (isset ( $tagInfo ['attr'] ['cache_timeout'] )) {
				$cacheTime = $tagInfo ['attr'] ['cache_timeout'];
			} else {
				$cacheTime = $cacheOpen;
			}
			if ($cacheOpen && $cacheTime != 0 && C('MEMCACHED_ON')) {
				$cache = service ( 'Cache', array ("type" => "memcache" ) );
				if (! $value = $cache->getWidget($widgetKey)) {
					$attrSet = $tagInfo ['attr'];
					$tagName = $tagInfo ['tagName'];
					$value = $tagInfo ['content'];
					$path = self::$tags [strtolower ( $tagName )];
					list ( $dir, $file ) = explode ( ':', $tagName );
					$file = ucfirst ( $file );
					require_once $path;
					$fileObjct = new $file ();
					if ($fileObjct->getTagStatus () || ! empty ( $value )) {
						$value = $fileObjct->replaceTag ( $attrSet, $value, $tagInfo );
					} else {
						$value = $fileObjct->replaceTag ( $attrSet, '', $tagInfo );
					}
					$cache->setWidget($widgetKey,$value,$cacheTime);
				}
			} else {
				$attrSet = $tagInfo ['attr'];
				$tagName = $tagInfo ['tagName'];
				$value = $tagInfo ['content'];
				if(strpos($tagInfo['attr']['style'],'custom') != 0 && empty($value)) continue;
				$path = self::$tags [strtolower ( $tagName )];
				list ( $dir, $file ) = explode ( ':', $tagName );
				$file = ucfirst ( $file );
				if(!is_file($path)) continue;
				require_once $path;
				$fileObjct = new $file ();
				if ($fileObjct->getTagStatus () || ! empty ( $value )) {
					$value = $fileObjct->replaceTag ( $attrSet, $value, $tagInfo );
				} else {
					$value = $fileObjct->replaceTag ( $attrSet, '', $tagInfo );
				}
			}
				
			$content = str_replace ( $key, $value, $content );
		}
		return $content;
	}
	/**
	 * 查找模块在数据库中是否存在
	 * @param unknown_type $sign
	 */
	public function getTagInfo($sign) {
		return model ( 'DiyWidget' )->getTagInfo ( $sign );
	}
	
	public function setContent($content, $sign) {
		$save ['content'] = $content;
		$map ['pluginId'] = $sign;
		return model ( 'DiyWidget' )->where ( $map )->save ( $save );
	}
	
	public function getTplContent($tpl, $tagName, $sign) {
		if (strpos ( $tpl, 'custom' ) !== false) {
			return model ( 'DiyWidget' )->getTemplateByPluginId ( $sign );
		} else {
			list ( $dir, $file ) = explode ( ':', $tagName );
			$file = ucfirst ( $file );
				
			require_once self::$tags [strtolower ( $tagName )];
			$this->fileObject = new $file ();
			ob_start ();
			ob_implicit_flush ( 0 );
			include $this->fileObject->getTemplateFile ( $tpl );
			$content = ob_get_clean ();
			return $content;
		}
	
	}
	
	/**
	 * 直接解析某一个标签
	 */
	public function pregReplace($tag, $replace = true) {
		//取出tagName
		$this->replace = $replace;
		$tagName = substr ( $tag, 1, strpos ( $tag, ' ' ) - 1 );
		if (isset ( self::$tags [$tagName] )) {
			$path = self::$tags [$tagName];
			$content = $this->pregReplaceTag ( $tagName, $path, $tag, $replace );
		}
	}
	/**
	 * 匹配内容并 编译返回HTMl内容
	 * @param unknown_type $tagName
	 * @param unknown_type $path
	 * @param unknown_type $content
	 * @param unknown_type $replace
	 * @return mixed
	 */
	private function pregReplaceTag($tagName, $path, $content, $replace = true) {
		list ( $dir, $file ) = explode ( ':', $tagName );
		$file = ucfirst ( $file );
		include_once $path;
		$this->fileObject = new $file ();
		$fileObjcet = $this->fileObject;
		//先对封闭式的标签进行过滤:<w:blog a="1" b="2" c="3" />这样的形式
		//		if( !$this->scope && !$fileObjct->getTagStatus()) 杨德升修改
		if (! $this->scope && ! $this->fileObject->getTagStatus ()) {
			$preg = "/([\n\r\t\s]*)" . $this->left . $tagName . "\s+(.*)\/" . $this->right . "([\n\r\t\s]*)/siU";
		} else {
			$preg = "/([\n\r\t\s]*)" . $this->left . $tagName . "\s+(.*)" . $this->right . "(.*)" . $this->left . "\/" . $tagName . $this->right . "([\n\r\t\s]*)/siU";
		}
		if ($replace) {
			$content = preg_replace_callback ( $preg, array ($this, 'parseTagContent' ), $content );
		} else {
			preg_replace_callback ( $preg, array ($this, 'parseTagContent' ), $content );
		}
		return $content;
	}
	/**
	 * 编译并返回内容
	 * @param unknown_type $source
	 */
	private function parseTagContent($source) {
		//去掉所有空数组成员
		foreach ( $source as &$value ) {
			$value = preg_replace ( "/^\s*\n/siU", "", $value );
			$value = rtrim ( $value );
		}
		$source = array_merge ( array_filter ( $source ) );
		$tagName = substr ( $source [0], 1, strpos ( $source [0], ' ' ) - 1 );
		//第一个是原始数据无需处理
	
		$tagInfo ['tagLib'] = sprintf ( '<%s %s/>', $tagName, $source [1] );
		//取出tagName
		if ($this->scope) {
			$source [0] = $this->left . $tagName . " " . $source [1] . "/" . $this->right;
		}
		//第二个是参数成员,需做数组处理
		$temp = simplexml_load_string ( $source [0] );
		$temp = (( array ) $temp);
		$attrSet = $this->parseTagAttr ( $temp ['@attributes'] );
		//第三个是内容集
		$source = isset ( $source [2] ) ? $source [2] : null;
		$source = str_replace ( '[@]', '&', $source );
	
		$tagInfo ['tagInfo'] ['name'] = $tagName;
		$tagInfo ['tagInfo'] ['path'] = self::$tags [$tagName];
		//parseTag 检查数据库是否有该模块的记录，如果没有就添加
		$this->sign [$tagName] = $this->fileObject->parseTag ( $attrSet, $source, $tagInfo );
		if (isset ( $_POST ['customContent'] )) {
			$_POST ['customContent'] = str_replace ( '[@]', '&', $_POST ['customContent'] );
			$this->setContent ( $_POST ['customContent'], $this->sign [$tagName] );
		}
		if ($this->replace) {
			//replaceTag 返回编译后的内容
			return $this->fileObject->replaceTag ( $attrSet, $source, $tagInfo );
		}
		return $this->sign [$tagName];
	}
	
	public function getSign($tagName) {
		if (isset ( $this->sign [$tagName] )) {
			return $this->sign [$tagName];
		} else {
			return false;
		}
	}
	private function parseTagAttr($attr) {
		$result = array ();
		foreach ( $attr as $key => $value ) {
			$temp = json_decode ( $value );
			$result [$key] = $temp ? $temp : $value;
		}
		return $result;
	}
	
	private static function traversalDir($path) {
		$result = array ();
		$file = new RecursiveIteratorIterator ( new RecursiveDirectoryIterator ( ($path) ) );
		$i = 0;
		foreach ( $file as $key => $value ) {
			if (! strpos ( $value->getPathname (), ".svn" ) && strpos ( $value->getFilename (), ".php" )) {
				$path = explode ( DIRECTORY_SEPARATOR, $value->getPath () );
				$temp_key = strtolower ( array_pop ( $path ) );
				list ( $temp_value ) = explode ( '.', $value->getFilename () );
				$result [$temp_key . ":" . strtolower ( $temp_value )] = $value->getPathname ();
			}
		}
		return $result;
	}
	//服务初始化
	public function init() {
	
	}
	
	//运行服务，系统服务自动运行
	public function run() {
	
	}
}
?>