<?php
/*
 * framework-spider
 * spider/tags/TagBase.class.php
 * 
 * CopyRight(C)Framework-Spider Developer Team. 2010. All Right Reserved. 
 * URL         : http://sourceforge.jp/projects/frameworkspider/
 * Mail        : frameworkspider-dev@lists.sourceforge.jp
 * Auther      : Masanori Nakashima
 * Modifier    : Masanori Nakashima
 * Last Updated: 2010.06.23
 * 
 */
require_once(dirname(dirname(dirname(__FILE__)))
	.DIRECTORY_SEPARATOR.'util'
	.DIRECTORY_SEPARATOR.'CharUtility.class.php');
/**
 * HTML用変換タグの基礎クラス
 * 
 * @package spider spiderのコアパッケージ
 * @version 1.2.00
 * @copyright Copyright &copy; 2008, <m_nakashima@users.sourceforge.jp> http://sourceforge.jp/projects/shopformer/
 * @author  m.nakashima <m_nakashima@users.sourceforge.jp>
 * @since PHP 4.3
 */
class spider_tags_TagBase {
	/** 変換実行優先度	*/
	var $priority	= 50;
	/** タグ文字列名称	*/
	var $tag_name	= '';
	/**
	 * コンストラクタ
	 */
	function spider_tags_TagBase() {
		$this->priority	= 50;
		$this->tag_name	= '';
	}
	/**
	 * コンバートメソッド
	 */
	function convert( &$result_strings, &$build_information ){
		// デフォルト動作は設定済みタグ名称でのシングルタグ全変換
		$this->convertSingleTagAll( $result_strings, $build_information );
	}
	/**
	 * 要素のみのシングルタグ変換を実行します
	 */
	function convertSingleTagAll( &$result_strings, &$build_information, $tag_name=null ) {
		// タグ名称が渡された場合のみ設定
		if( !is_null($tag_name) && strlen($tag_name) > 0 ) {
			$this->tag_name	= $tag_name;
		}
		// タグ名称が設定されていないなら処理をしない
		if( is_null($this->tag_name) || strlen($this->tag_name) == 0 ) {
			return;
		}
		$tag_regx			= util_CharUtility::escape_regx_str('{'.$this->tag_name);
		$tag_search_regx	= $tag_regx.'[^\\}]*?\\}';
		$tag_strings_array		= array();
		$valiable_counter	= 0;
		while( preg_match_all( '/'.$tag_search_regx.'/'
			, $result_strings
			, $tag_strings_array
			, PREG_PATTERN_ORDER ) > 0 ) {
			foreach ( $tag_strings_array as $target_tag_array ) {
				foreach ( $target_tag_array as $target_tag ) {
					$options_string	= preg_replace( '/'.$tag_regx.'/','', $target_tag );
					$options_string	= preg_replace( '/\\}$/','', $options_string );
					if( strlen(trim($options_string)) == 0 ) {
						// タグが終了しているようならオプション無で処理
						$option_array		= array();
						$converted_strings	= $this->getConvertedStrings( $result_strings, $build_information, $option_array, $valiable_counter );
						$result_strings 	= str_replace( $target_tag, $converted_strings, $result_strings );
					} else if( preg_match('/^\\:/', $options_string) > 0 ) {
						// :で始まっているならオプション文字列なのでオプションを取り出して処理
						$options_string	= preg_replace('/^\\:/','',$options_string);
						$param_array	= $this->splitOptionBySpace( $options_string );
						$option_array	= array();
						foreach( $param_array as $param ) {
							$param	= trim($param);
							if( strlen( $param ) > 0 ) {
								array_push( $option_array, $param );
							}
						}
						$converted_strings	= $this->getConvertedStrings( $result_strings, $build_information, $option_array, $valiable_counter );
						// 空行にならないよう前後が改行も削除
						if( strlen($converted_strings) == 0 ) {
							$result_strings 	= str_replace( "\n".$target_tag."\n", $converted_strings, $result_strings );
						}
						$result_strings 	= str_replace( $target_tag, $converted_strings, $result_strings );
					} else {
						// 終了でも:でもないなら違うタグなので処理しない
					}
					$valiable_counter++;
				}
			}
		}
		return;
	}
	/**
	 * 個々のタグ文字列の変換後文字列を取得します
	 * 必要に応じて拡張したタグクラスで実装してください。
	 */
	function getConvertedStrings( &$result_strings, &$build_information, $option_array=array(), $valiable_counter=0 ) {
		return '';
	}
	//
	// タグ解析全般で利用するユーティリティメソッド
	//
	/**
	 * オプション文字列をオプション配列にします。
	 */
	function splitOptionBySpace( $string ) {
		// 最終的なオプション文字列配列
		$option_array	= array();
		$string			= trim($string);
		if( strpos($string,' ') !== false ) {
			// 分割
			$column_array	= explode(' ', $string);
			// クォートを維持してオプション文字列配列にいれる
			$data			= '';
			foreach( $column_array as $column ) {
				$data		.= $column;
				if( preg_match('/^\\\'/',$data) > 0 && substr_count( $data, "'" ) % 2 == 1 ) {
					// 'から始まって'の数が奇数個なら次のカラムとつなげる
					$data		.= ' ';
					continue;
				} else if( strlen($data) > 0 ) {
					// そうでない場合はカラムがデータとして完結しているので配列に追加
					array_push( $option_array, $data );
					// 次のデータに備えてデータを空文字で新しく設定
					$data	= '';
				}
			}
			if( strlen($data) > 0 ) {
				array_push( $option_array, $data );
				$data	= '';
			}
		} else {
			array_push( $option_array, $string );
		}
		return $option_array;
	}
	/**
	 * タグコードをPHPコードに変換します
	 */
	function tagCode2NativeCode( $strings, & $attribute_name_array ) {
		// 演算時の正規表現
		$signiture_regx	= '\\+\\-\\/\\*\\%\\=\\<\\>\\&\\|\\(\\)\\!\\,\\[\\]';
		// 変換後文字列
		$converted_strings	= '';
		$element_array		= preg_split('/([\\s'.$signiture_regx.'])/', $strings, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE );
		$element_data		= '';
		$prev_data			= '';
		foreach( $element_array as $key => $element ) {
			$element_data		.= $element;
			if( preg_match('/^\\\'/',$element_data) > 0 && substr_count( $element_data, "'" ) % 2 == 1 ) {
				// 'から始まって'の数が偶数個なら次のカラムとつなげる
				continue;
			} else if( preg_match('/^\\\'/',$element_data) > 0 && substr_count( $element_data, "'" ) % 2 == 1 ) {
				// 'から始まって'の数が偶数個なら次のカラムとつなげる
				continue;
			} else {
				if( preg_match('/([\\s'.$signiture_regx.'])/',$element_data) == 0 ) {
					// 演算子でない場合のみ処理
					if( preg_match('/^\\$/',$element_data ) > 0 ) {
						// $から始まるなら変換しないでそのまま追加
						$converted_strings	.= $element_data;
					} else if( preg_match('/^\'/',$element_data ) > 0 && preg_match('/\'$/',$element_data ) > 0 ) {
						// クォートされているなら文字列
						if( $key > 2 && $element_array[$key-1] == '>' &&  $element_array[$key-2] == '-'){
							// 前の要素が->オブジェクトメンバ指定子の場合クォートを除去して追加
							$converted_strings	.= preg_replace('/(^\'|\'$)/','',$element_data);
						} else {
							// ただの文字列の場合はそのまま追加
							$converted_strings	.= $element_data;
						}
					} else if( preg_match('/^"/',$element_data ) > 0 && preg_match('/"$/',$element_data ) > 0 ) {
						// クォートされているなら文字列
						if( $key > 2 && $element_array[$key-1] == '>' &&  $element_array[$key-2] == '-'){
							// 前の要素が->オブジェクトメンバ指定子の場合
							$converted_strings	.= preg_replace('/(^\\"|\\"$)/','',$element_data);
						} else {
							// ただの文字列の場合はそのまま追加
							$converted_strings	.= $element_data;
						}
					} else if( preg_match('/^[0-9]+$/',$element_data ) > 0 ) {
						// 数字だけならそのまま追加
						$converted_strings	.= $element_data;
					} else if( preg_match('/^(true|false)$/',$element_data ) > 0 ) {
						// true/falseならそのまま追加
						$converted_strings	.= $element_data;
					} else {
						// 次の演算子以外の要素が(なら関数なので次の空でない要素をチェック
						$is_method	= false;
						for( $i=$key+1;$i<count($element_array);$i++){
							$val	= trim($element_array[$i]);
							if( strlen($val) > 0 ) {
								if( $val == '(' ) {
									$is_method	= true;
								}
								break;
							}
						}
						if( $is_method ) {
							// 関数名・メソッド名の場合はそのまま追加
							$converted_strings	.= $element_data;
						} else if( $key > 2 && $element_array[$key-1] == '>' &&  $element_array[$key-2] == '-'){
							// メソッドでなくて前の要素が->の場合オブジェクトメンバも変換(要検討...)
							$converted_strings	.= '$GLOBALS[\''.$element_data.'\']';
							if( is_array($attribute_name_array) ) {
								array_push( $attribute_name_array, $element_data );
							}
						} else if( $element_data == '.' ) {
							// .のみ単体(前後がスペース)の場合はそのまま追加
							$converted_strings	.= ' . ';
						} else {
							// それ以外は$GLOBALSへ変換
							$converted_strings	.= '$GLOBALS[\''.$element_data.'\']';
							if( is_array($attribute_name_array) ) {
								array_push( $attribute_name_array, $element_data );
							}
						}
					}
				} else {
					// 演算子はそのまま追加
					$converted_strings	.= $element_data;
				}
				$prev_data			= $element_data;
				$element_data		= '';
			}
		}

		return $converted_strings;
	}
}
?>