<?php
/*
 * framework-spider
 * spider/tags/Charset.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(__FILE__).DIRECTORY_SEPARATOR.'TagBase.class.php');
/**
 * HTML用変換タグ:charsetタグクラス
 * 
 * {charset:[文字コード指定文字列]}で指定された文字コードでページを出力するよう変更します。
 * 
 * [文字コード指定文字列]にはPHPのmbstringによる文字コード指定方法を用いてください。
 * 例）Windows向けShift_JISの場合→SJIS-win
 * 
 * また出力時にHTMLタグ内の以下のメタタグ内の文字セットの書き換えも試みます。
 * <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
 * 
 * 記述例）
 * {charset:SJIS-win}
 * 
 * ※本タグはテンプレート・ウィジェット・ページ全てあわせて1つのみ指定できます。
 * 複数のタグが記述されている場合、出力文字列の一番最後に記述されているcharset指定が有効になります。
 * 
 * @package spider spiderのコアパッケージ
 * @subpackage tags 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_Charset extends spider_tags_TagBase {

	/**
	 * コンストラクタ
	 */
	function spider_tags_Charset() {
		$this->priority	= 30;
	}
	/**
	 * コンバートメソッド
	 */
	function convert( & $resultString, & $buildInformation ){
		// charsetタグ内文字列
		$charsetStrings	= '';
		if ( preg_match_all( '/\\{charset\\:([^\\}]*?)\\}/'
		,$resultString,$outputArray,PREG_PATTERN_ORDER ) > 0 ) {
			// charsetタグが明示的に指定されている場合、最後に書かれたものを適用
			$matchAllArray	= $outputArray[0];
			$matchCharArray	= $outputArray[1];
			$charsetStrings		= trim($matchCharArray[count($matchCharArray)-1]);
			foreach ( $matchAllArray as $target ){
				$resultString 	= str_replace( "\n".$target."\n", "", $resultString );
				$resultString 	= str_replace( $target."\n", "", $resultString );
				$resultString 	= str_replace( "\n".$target, "", $resultString );
				$resultString 	= str_replace( $target, "", $resultString );
			}
		} else {
			// charsetタグがない場合はユーザーエージェント指定の文字コードがあるなら適用
			if( isset($GLOBALS['SPIDER_USER_AGENT_CLASS_OUTPUT_CHARSET'])
				&& isset($GLOBALS['SPIDER_USER_AGENT_CLASS_OUTPUT_CHARSET'][$buildInformation->agent_class])
				&& strlen($GLOBALS['SPIDER_USER_AGENT_CLASS_OUTPUT_CHARSET'][$buildInformation->agent_class]) > 0 ) {
				// 対象ユーザーエージェント分類の文字コードが指定されているなら適用
				$charsetStrings	= $GLOBALS['SPIDER_USER_AGENT_CLASS_OUTPUT_CHARSET'][$buildInformation->agent_class];
			} else {
				// 定義がないなら常にUTF-8で出力する
				$charsetStrings	= 'UTF-8';
			}
		}
		$charsetArray	= explode(' ', $charsetStrings);
		// 最初の項は必ず文字コード
		$outputCharset		= trim(array_shift($charsetArray));
		$convertKana			= '';
		$internalCharset	= 'UTF-8';
		$outputHandler		= 'mb_output_handler';
		$detectOrder			= 'UTF-8,EUC-JP,SJIS,SJIS-win,JIS,UTF-7';
		$language					= 'ja';
		// 残りの項の解析
		foreach( $charsetArray as $str ) {
			if( strlen(trim($str)) > 0 ) {
				list( $key, $val )	= explode('=',trim($str));
				$key	= trim($key);
				$val	= trim($val);
				if( strlen($val) == 0 ) {
					// 単一項目ならconvert_kanaと判断する（下位互換）
					$convertKana	= $key;
				} else if( 'internal_charset' == $key ){
					$internalCharset	= $val;
				} else if( 'output_handler' == $key ) {
					$outputHandler		= $val;
				} else if( 'convert_kana' == $key ) {
					$convertKana		= $val;
				} else if( 'detect_order' == $key ) {
					$detectOrder		= $val;
				} else if( 'language' == $key ) {
					$language			= $val;
				}
			}
		}
		// buildInformationに設定
		$buildInformation->output_charset		= $outputCharset;
		$buildInformation->convert_kana			= $convertKana;
		$buildInformation->output_handler		= $outputHandler;
		$buildInformation->internal_charset	= $internalCharset;
		$buildInformation->detect_order			= $detectOrder;
		$buildInformation->output_language	= $language;

		// 出力HTML内の文字コード指定変換
		$htmlReplaceCode = $outputCharset;
		if( isset($GLOBALS['DEF_SPIDER_CHARSET_REPLACE_ENCODINGS'][$outputCharset]) ) {
			// 変換文字が定義されているなら変換文字を使う(SJIS等の場合Shift_JISにするなどの為)
			$htmlReplaceCode = $GLOBALS['DEF_SPIDER_CHARSET_REPLACE_ENCODINGS'][$outputCharset];
		}
		// メタタグのcharsetを変更
		$resultString	= preg_replace(
			'/(<[mM][eE][tT][aA][^>]*\\s[cC][oO][nN][tT][eE][nN][tT]\\=[\'"][^\'"]*[cC][hH][aA][rR][sS][eE][tT]\\=)([^\'"\\;]+)([^\'"]*[\'"][^>]*>)/',
			'$1'.$htmlReplaceCode.'$3',
			$resultString
		);
		// XML宣言もあれば変更
		$resultString	= preg_replace(
			'/(<\\?xml[^>]*\\s[eE][nN][cC][oO][dD][iI][nN][gG]\\=[\'"])([^\'"]*)([^\'"]*[\'"][^>]*>)/',
			'$1'.$htmlReplaceCode.'$3',
			$resultString
		);

		// 前処理の文字コードフラッシュコードを追加
		$preprocessCode = "ob_start('".$outputHandler."');\n";
		$preprocessCode .= "ob_implicit_flush( false );\n";
		$preprocessCode .= "mb_language('".$language."');\n";
		$preprocessCode .= "mb_detect_order('".$detectOrder."');\n";
		$preprocessCode .= "mb_internal_encoding('".$internalCharset."');\n";
		// 2009-07-01 DoCoMo XHTML対応 暫定 PHPheaderでセットしたContent-Typeの文字セットでob_get_cleanの取得文字コードを勝手に操作する為UTF-8で指定...
		if( preg_match('/\\<\\!DOCTYPE\\shtml\\sPUBLIC\\s\\"\\-\\/\\/i\\-mode group/',$resultString) > 0 ) {
			$preprocessCode .= 'if(preg_match(\'/^DoCoMo/\',$_SERVER[\'HTTP_USER_AGENT\']) > 0 ) {'."\n";
			$preprocessCode .= '$request->setResponseHeader(\'Content-Type\',\'application/xhtml+xml;charset='.$htmlReplaceCode.'\');'."\n";
			$preprocessCode .= '}'."\n";
		}
		// 言語によるメッセージバンドルの上書きコード
		if( strlen($buildInformation->output_language) > 0){
			$preprocessCode	.= '$GLOBALS[\'request\']->setLocale(\''.$buildInformation->output_language.'\');'."\n";
		} else {
			$preprocessCode	.= '$GLOBALS[\'request\']->setLocale(\'ja\');'."\n";
		}
		
		if( !isset($buildInformation->processPreModuleHash)
			|| !is_array($buildInformation->processPreModuleHash) ){
			$buildInformation->processPreModuleHash	= array();
		}
		if( !isset($buildInformation->processPreModuleHash[$this->priority])
			|| !is_array($buildInformation->processPreModuleHash[$this->priority]) ){
			$buildInformation->processPreModuleHash[$this->priority]	= array();
		}
		array_push( $buildInformation->processPreModuleHash[$this->priority], $preprocessCode );
		
		// 表示文字列に対する処理実行コードを記述
		if( !isset($buildInformation->convert_view_process_hash)
			|| !is_array($buildInformation->convert_view_process_hash) ){
			$buildInformation->convert_view_process_hash	= array();
		}
		if( !isset($buildInformation->convert_view_process_hash[$this->priority])
			|| !is_array($buildInformation->convert_view_process_hash[$this->priority]) ){
			$buildInformation->convert_view_process_hash[$this->priority]	= array();
		}
		if( strlen( trim( $convertKana ) ) > 0 ) {
			$postProcessCode = '$outstr = mb_convert_kana( $outstr, "' . $convertKana . '" );'."\n";
			array_push( $buildInformation->convert_view_process_hash[$this->priority], $postProcessCode );
		} else if ( 'docomo' == $buildInformation->agent_class
		|| 'docomo2' == $buildInformation->agent_class
		|| 'softbank' == $buildInformation->agent_class
		|| 'au' == $buildInformation->agent_class ) {
			$postProcessCode = '$outstr = mb_convert_kana( $outstr, "kna" );'."\n";
			array_push( $buildInformation->convert_view_process_hash[$this->priority], $postProcessCode );
		}
	}
}
?>