Hatena::ブログ(Diary)

脱サラ大学生のプログラム日記 RSSフィード

2012-02-14

EC-CUBEの納品用画面仕様書作成

| 23:06

ソースファイルから仕様書の自動作成実験です。EC-CUBEのソースからほぼ自動で画面仕様と画面キャプチャーを行なっています。

作成したPDF(Google Doc)

↑ファイル->元のファイルをダウンロードからacrobatでしおり表示して見たほうが見やすいです。

f:id:akiraneko:20120214232803p:image

↑こんな感じのページになります

ページクラスの抜き出し

LC_Pageから始まるファイルをすべて検索して処理を行います。中のファイルを見てみると以下のような行がありますので、ここを抜き出します。

<?php
$objFormParam->addParam('会社名', 'company_name', STEXT_LEN, 'KVa',  array("MAX_LENGTH_CHECK"));

半自動ツールなので、かなり無茶なコードですが、evalを駆使してデータの取得を行っています。。。上記以外にも必要そうなデータを取得しています。

当初はfgetsを利用して、行単位で取り込みを行なっていましたが、複数行に分割されていると取得できないので、token_get_allを利用してなんちゃってPHPソースのパースを行なっています。

画面キャプチャ用のhtml出力

ファイル名から推測されるURLにアクセスして、画面キャプチャを取得するhtmlを記述します。出力するファイルはSelenium IDE用のファイルで、Firefoxで一気にキャプチャします。

一部URLが自動的に変換できないところなどは対応表作って正しいURLを設定してあげてます。

画面キャプチャ

Selenium IDEを利用して一気にキャプチャします。最初にログインを行ってから、各画面にアクセスしてはキャプチャを繰り返します。プラグインの追加やデリート系のページについては画面キャプチャが面倒なのであきらめました。数枚であれば手で取ればいいですからね。

再度ツール実行

キャプチャした場所にファイルがあると項目のほかに画面キャプチャもhtmlに出力しています。印刷した際に一画面に収まるように縦に分割とかもしています。SEO設定画面は縦に長すぎるので表示していません。

htmlの保存

ローカルにファイルないと次のWordに貼り付けができないので、一度保存します。IE8とFirefox9では正常に保存と読み込みができました。

Wordで読み込み

保存したhtmlを読み込みます。h1タグとかをつけて出力してあるので、そのまま見出しで読み込まれます。

雛形Wordにコピーアンドペーストで貼り付ける

見出しなどに書式が設定されているファイルに貼り付けます。表紙や目次などもあらかじめ設定してあるのがよいと思います。

今回は最初の概要までは手で作って、それ以降はツールから貼り付けたものそのままになります。そのままだとリンク設定になっていますので、図を文章に保存するにしてから、リンクを解除します。

目次の更新

意外と大切!

見出しを選択してからF9ですべて更新します。

PDFに出力

そのままでもいいのですが、Word2007以降の人の場合にはしおり付きのPDFが出力できます。

考察

実は一年以上前に取り込み部分まで作っていたのですが、特に自分では利用しないので忙しさにかまけて放置していました。。。まだツールとしては荒いつくりなので、手を入れる必要があるとは思いますがプロトタイプとしては十分かと思います。

OSS使っても全部のページの仕様書頂戴といわれることが多いと思うので、こんなものがあってもいいかなーって思って作りました。カスタマイズしたところは、もう少し詳細仕様を別紙で起こして、共通部分はこれぐらいでいいよね?

ライセンスどうなっているんだーとか、改造してやるぞとか、使い方わからねーとかはコメントかメッセージ等ください。

気がついたら1年ぐらい経過していました。本当は画面遷移まで取ろうかと思いましたが、テンプレートとページクラスの両方からデータを取得しないといけないのでやめました。そのうち画面遷移図も作るかもしれません。

作成物

作成したPDF(Google Doc)

作成したプログラム

<?php

$def_base_url = "http://localhost/eccube/html";
$def_user_id = "admin";
$def_user_pass = "admin";
$def_user_id2 = "test@test.jp";
$def_user_pass2 = "test";
$def_out_dir = "C:\\p\\xampp\\htdocs\\eccube\\capimg";
$def_img_height = 1200;
$def_img_width = 640;
$def_product_id = 2;

$def_urllist = array( 
	$def_base_url."/admin/index/index.php" => $def_base_url."/admin/index.php",
	$def_base_url."/admin/products/class_category.php" => $def_base_url."/admin/products/classcategory.php",
	$def_base_url."/admin/products/uploadcsv.php" => $def_base_url."/admin/products/upload_csv.php",
	$def_base_url."/admin/products/uploadcsvcategory.php" => $def_base_url."/admin/products/upload_csv_category.php",
	$def_base_url."/admin/system/admin_area.php" => $def_base_url."/admin/system/adminarea.php",
	$def_base_url."/mypage/down_load.php" => $def_base_url."/mypage/download.php",
	$def_base_url."/admin/system/admin_area.php" => $def_base_url."/admin/system/adminarea.php",
	$def_base_url."/products/detail.php" => $def_base_url."/products/detail.php?product_id=".$def_product_id,
	$def_base_url."/products/review.php" => $def_base_url."/products/review.php?product_id=".$def_product_id,
	$def_base_url."/input_zip/index.php" => $def_base_url."/input_zip.php?zip1=100&zip2=0001",
);

$def_nodisp_urllist = array( 
	$def_base_url."/admin/basis/seo.php",
	$def_base_url."/admin/plugin/install.php",
	$def_base_url."/admin/plugin/uninstall.php",
);

ini_set('display_errors', 'Off');

if( isset( $_GET['file'] ) ){
	dispImg();
	exit;
}

$sfp = fopen( "selenium.html", "w" );

require_once 'html/require.php';

define ("DEFAULT_DSN", DB_TYPE . "://" . DB_USER . ":" . DB_PASSWORD . "@" . DB_SERVER . ":" .DB_PORT . "/" . DB_NAME);

define ("CLASS_IMAGE_WIDTH", "CLASS_IMAGE_WIDTH");
define ("CLASS_IMAGE_HEIGHT", "CLASS_IMAGE_HEIGHT");

require_once 'data/mtb_constants_init.php';

$searchEcCube = new searchEcCubeClass;
$searchEcCube->checkDir(".");

$now_h1type = "none";

seleniumHead($sfp);

$pb_flag = false;
foreach( $searchEcCube->checkList as $file ){
	$h1type = getH1Type($file['file']);
	if( $h1type != $now_h1type ){
		$now_h1type = $h1type;
		$print_h1type = getH1typename($now_h1type);
		echo "<h1>$print_h1type</h1>";
		$pb_flag = false;
	}

	if( $pb_flag == false ){
		$pb_flag = true;
	} else {
		echo '<div style="page-break-after:always"></div>'."\n";
	}

$data_file = substr( $file['file'], 1 );
	echo <<<__EOF__
<h2>{$file['title']}</h2>
__EOF__;

	$url = seleniumPage($sfp, $file['file'] );

	preg_match( '/LC_Page_(.*)\.php/', $file['file'], $match );
	$pageName = strtolower( $match[1] );
	$img_file = "capimg/{$pageName}.png";

	list($width, $height, $type, $attr) = getimagesize($img_file);
	$img_filesize = filesize($img_file);
	if( 0 < $height && $height < 3000 ){
		$img_cnt = floor( $height / $def_img_height ) + 1;
		echo '<h3>画面キャプチャ</h3>';
		echo '<table border="1" style="width:'.$def_img_width.'px;"><tr><td>';
		for( $i = 0 ; $i < $img_cnt ; $i++ ){
			$img_file_url = "?file=capimg/{$pageName}.png&ct=$i&h=$def_img_height";

			// 200以下の場合
			$h = $def_img_height;
			if( $img_cnt-1 == $i ){
				$h = $height % $def_img_height;
			}

			$h = floor( $h / ( 1.0 * $width / $def_img_width ) );
			echo '<img src="' . $img_file_url . '" width="'.$def_img_width.'" height="'.$h.'">' . "<br />\n";
		}
		echo "</td></tr></table>\n";
	} else {
//		echo '<h3>画面キャプチャ</h3>';
//		echo '画面なし';
	}

	echo "<h3>ファイル</h3>\n";
	echo $data_file. "<br />\n";

	echo "<h3>URL</h3>\n";
	echo $url. "<br />\n";

	if( count( $file['data2'] ) ){

	echo <<<__EOF__
<h3>パラメータ</h3>
<table border=1 width="100%">
<tr>
	<th bgcolor="gray" width="20%">項目名</th>
	<th bgcolor="gray" width="15%">name</th>
	<th bgcolor="gray" width="10%">長さ</th>
	<th bgcolor="gray" width="10%">コンバート</th>
	<th bgcolor="gray" width="35%">チェック内容</th>
	<th bgcolor="gray" width="15%">デフォルト</th>
	<th bgcolor="gray" width="5%">DB入力</th>
</tr>
__EOF__;

	foreach( $file['data2'] as $data ){
		echo "<tr>\n";

		// 項目名
		echo "<td>";
		echo $data[0];
		echo "</td>\n";

		// name
		echo "<td>";
		echo $data[1];
		echo "</td>\n";

		// 長さ
		echo "<td>";
		echo $data[2];
		echo "</td>\n";

		// コンバート
		echo "<td>";
		echo $data[3];
		echo "</td>\n";

		// チェック項目
		echo "<td>\n";
		echo implode(", ", arrayGetName( $data[4] ) );
		echo "</td>\n";

		// デフォルト
		echo "<td>";
		echo $data[5];
		echo "</td>\n";

		// DB
		echo "<td>";
		echo ($data[6])?"":"";
		echo "</td>\n";

		echo "</tr>\n";
	}

	echo <<<__EOF__
</table>
<br />
__EOF__;
	}

	if( count( $file['data3'] ) ){

	echo <<<__EOF__
<h3>ファイルアップロード</h3>
<table border=1 width="100%">
<tr>
	<th bgcolor="gray" width="20%">項目名</th>
	<th bgcolor="gray" width="15%">name</th>
	<th bgcolor="gray" width="20%">指定する拡張子</th>
	<th bgcolor="gray" width="10%">制限サイズ</th>
	<th bgcolor="gray" width="10%">必須</th>
	<th bgcolor="gray" width="10%">横幅</th>
	<th bgcolor="gray" width="10%">縦幅</th>
	<th bgcolor="gray" width="5%">画像</th>
</tr>
__EOF__;

	foreach( $file['data3'] as $data ){
		echo "<tr>\n";

		// 項目名
		echo "<td>";
		echo $data[0];
		echo "</td>\n";

		// name
		echo "<td>";
		echo $data[1];
		echo "</td>\n";

		// 指定する拡張子
		echo "<td>";
		echo implode(", ", $data[2] );
		echo "</td>\n";

		// 制限サイズ
		echo "<td>";
		echo $data[3];
		echo "</td>\n";

		// 必須
		echo "<td>\n";
		echo $data[4];
		echo "</td>\n";

		// 横幅
		echo "<td>";
		echo $data[5];
		echo "</td>\n";

		// 縦幅
		echo "<td>";
		echo $data[6];
		echo "</td>\n";

		// 画像
		echo "<td>";
		echo $data[7];
		echo "</td>\n";

		echo "</tr>\n";
	}

	echo <<<__EOF__
</table>
<br />
__EOF__;
	}

	if( count( $file['data'] ) ){

	echo <<<__EOF__
<h3>入力チェック</h3>
<table border=1 width="100%">
<tr>
	<th bgcolor="gray" width="20%">項目名</th>
	<th bgcolor="gray" width="10%">必須</th>
	<th bgcolor="gray" width="20%">入力種別</th>
	<th bgcolor="gray" width="10%">範囲チェック</th>
	<th bgcolor="gray" width="40%">チェック内容</th>
</tr>
__EOF__;

	foreach( $file['data'] as $data ){
		echo "<tr>\n";

		// 項目名
		echo "<td>";
		echo $data[0][0];
		echo "</td>\n";

		// 必須
		$checkTypeList = array();
		$checkTypeList[1] = array();
		$checkTypeList[2] = array();
		$checkTypeList[3] = array();
		foreach( $data[1] as $checkName ){
			$type = getCheckType($checkName);
			$checkTypeList[$type][] = $checkName;
		}

		echo "<td>\n";
		echo implode("<br />", arrayGetName( $checkTypeList[1] ) );
		echo "</td>\n";
		echo "<td>\n";
		echo implode("<br />", arrayGetName( $checkTypeList[2] ) );
		echo "</td>\n";
		echo "<td>\n";
		echo implode("<br />", arrayGetName( $checkTypeList[3] ) );
		echo "</td>\n";

		// チェック項目
		array_shift($data[0]);
		echo "<td>\n";
		echo implode(", ", $data[0] );
		echo "</td>\n";

		echo "</tr>\n";
	}

	echo <<<__EOF__
</table>
__EOF__;
	}

}

seleniumFoot($sfp);
fclose($sfp);


class searchEcCubeClass{
	var $arrAllowedTag = "<arrAllowedTag>";
	var $arrReviewDenyURL = "<arrReviewDenyURL>";
	var $checkList = array();
	function lfGetSqlDenyList(){}

	function checkDir($path){
		$list = scandir( $path );
		foreach( $list as $file ){
			$pathname = $path . "/" . $file;

			if( $file == '.' || $file == '..'){
				continue;
			}

			if( is_dir( $pathname ) ){
				$this->checkDir( $pathname );
			} else if( preg_match( "/^LC_Page.*\.php$/", $file ) ){
				$this->checkFile($pathname);
			}
		}
	}

	function checkFile($path){
		$cnt = "#N#";
		$no = "#No#";
        $classcategory_id1 = "classcategory_id#id#_1";
        $classcategory_id2 = "classcategory_id#id#_2";
        $quantity = "quantity<id>";
		$pageTitle = "";
		$i = "#i#";

		$checkList = array();
		$checkList2 = array();
		$checkList3 = array();

		$objErr = new objErr;
		$objWebParam = new objErr;
		$masterData = new masterData;
		$this->objDate = new objDateClass;
		$this->objFormParam = new objErr;
		$this->objUpFile = new objErr;
		$this->lfGetSqlDenyList = new objErr;
		$objUpFile = new objErr;
		$objFormParam = new objErr;
		$objCheckCategory = new objErr;
		$arrList = array(
			"startyear_m" => "#startyear_m#",
			"startmonth_m" => "#startmonth_m#",
			"startyear" => "#startyear#",
			"startmonth" => "#startmonth#",
			"startday" => "#startday#",
			"endyear" => "#endyear#",
			"endmonth" => "#endmonth#",
			"endday" => "#endday#",
		 );

		$filebody = file_get_contents($path);
		$lines = file2lines($filebody);
		foreach( $lines as $line ){
			if( preg_match( "/objErr->doFunc(.*);/", $line ) ){
				eval( $line );
				$checkList[] = array( $objErr->var1, $objErr->var2 );
			} else if( preg_match( "/objCheckCategory->doFunc(.*);/", $line ) ){
				eval( $line );
				$checkList[] = array( $objCheckCategory->var1, $objCheckCategory->var2 );
			} else if( preg_match( "/this->objFormParam->addParam(.*);/", $line ) ){
				eval( $line );

				$checkList2[] = array(
					$this->objFormParam->disp_name,
					$this->objFormParam->keyname,
					$this->objFormParam->length,
					$this->objFormParam->convert,
					$this->objFormParam->arrCheck,
					$this->objFormParam->default,
					$this->objFormParam->input_db
				);
			} else if( preg_match( "/objFormParam->addParam(.*);/", $line ) ){
				eval( $line );
				$checkList2[] = array(
					$objFormParam->disp_name,
					$objFormParam->keyname,
					$objFormParam->length,
					$objFormParam->convert,
					$objFormParam->arrCheck,
					$objFormParam->default,
					$objFormParam->input_db
				);
			} else if( preg_match( "/this->objUpFile->addFile(.*);/", $line ) ){
				eval( $line );
				$checkList3[] = array(
					$this->objUpFile->disp_name,
					$this->objUpFile->keyname,
					$this->objUpFile->arrExt,
					$this->objUpFile->size,
					$this->objUpFile->necessary,
					$this->objUpFile->width,
					$this->objUpFile->height,
					$this->objUpFile->image
				);
			} else if( preg_match( "/objUpFile->addFile(.*);/", $line ) ){
				eval( $line );
				$checkList3[] = array(
					$objUpFile->disp_name,
					$objUpFile->keyname,
					$objUpFile->arrExt,
					$objUpFile->size,
					$objUpFile->necessary,
					$objUpFile->width,
					$objUpFile->height,
					$objUpFile->image
				);
			} else if( preg_match( "/\*(.*)のページクラス/", $line, $match ) ){
				$pageTitle = trim( $match[1] );
			}
		}

		if( count( $checkList ) != 0 || count( $checkList2 ) != 0 || count( $checkList3 ) != 0 ){
			$this->checkList[] = array( "title" => $pageTitle, "file" => $path, "data" => $checkList, "data2" => $checkList2, "data3" => $checkList3 );
		}
	}
}

class objErr{
	var $var1;
	var $var2;

	var $disp_name;
	var $keyname;
	var $length;
	var $convert;
	var $arrCheck;
	var $default;
	var $input_db;

	var $arrExt;
	var $size;
	var $necessary;
	var $width;
	var $height;
	var $image;

	function doFunc( $set_var1, $set_var2 ){
		$this->var1 = $set_var1;
		$this->var2 = $set_var2;
	}

    function addParam($disp_name, $keyname, $length="", $convert="", $arrCheck=array(), $default="", $input_db="true") {
        $this->disp_name = $disp_name;
        $this->keyname = $keyname;
        $this->length = $length;
        $this->convert = $convert;
        $this->arrCheck = $arrCheck;
        $this->default = $default;
        $this->input_db = $input_db;
    }

	function addFile($disp_name, $keyname, $arrExt, $size, $necessary=false, $width=0, $height=0, $image=true){
		$this->disp_name = $disp_name;
		$this->keyname = $keyname;
		$this->arrExt = $arrExt;
		$this->size = $size;
		$this->necessary = $necessary;
		$this->width = $width;
		$this->height = $height;
		$this->image = $image;
	}
}

class masterData{
	function getMasterData(){
		return "#URL#";
	}
}

class objDateClass{
	function getStartYear(){
		return "#StartYear#";
	}
	function getEndYear(){
		return "#EndYear#";
	}
}

function arrayGetName( $array ){
	$ret = array();
	foreach( $array as $data ){
		$ret[] = getName( $data );
	}

	return $ret;
}

function getName( $str ){
	switch( $str ){
		case "EXIST_CHECK": return "必須";
		case "ALL_EXIST_CHECK": return "すべて必須";
		case "TOP_EXIST_CHECK": return "上位が入力済み";
		case "ONE_EXIST_CHECK": return "どれか選択";
		case "FILE_EXISTS": return "ファイルの存在チェック";

		case "NUM_CHECK": return "数値";
		case "GRAPH_CHECK": return "英数記号";
		case "KANA_CHECK": return "カナ";
		case "EMAIL_CHECK": return "E-Mail形式";
		case "MOBILE_EMAIL_CHECK": return "携帯Mail";
		case "EMAIL_CHAR_CHECK": return "E-Mail文字種";
		case "TEL_CHECK": return "電話形式";
		case "ZERO_CHECK": return "0チェック";
		case "ALPHA_CHECK": return "半角英字";
		case "CHECK_DATE": return "日付形式(ymd)";
		case "CHECK_DATE2": return "日付形式(ymd-hm)";
		case "KANABLANK_CHECK": return "カナ(スペース許可)";
		case "ALNUM_CHECK": return "英数";
		case "FILE_NAME_CHECK": return "ファイル名形式";
		case "FILE_NAME_CHECK_BY_NOUPLOAD": return "ファイル名形式(アップロード以外)";
		case "HTML_TAG_CHECK": return "Htmlタグ";
		case "URL_CHECK": return "URL形式";
		case "IP_CHECK": return "IPアドレス";
		case "PROHIBITED_STR_CHECK": return "禁止文字";
		case "SPTAB_CHECK": return "スペース・タブのみ";
		case "NO_SPTAB": return "スペース・タブ";
		case "ZERO_START": return "先頭が0";

		case "MAX_LENGTH_CHECK": return "最大";
		case "NUM_COUNT_CHECK": return "桁数";
		case "CHECK_SET_TERM": return "期間チェック";
		case "CHECK_SET_TERM2": return "期間チェック(秒まで)";
		case "NUM_RANGE_CHECK": return "最小・最大";
		case "GREATER_CHECK": return "値比較(<)";
		case "DIFFERENT_CHECK": return "値比較(!=)";
		case "SELECT_CHECK": return "リスト範囲内";
		case "EQUAL_CHECK": return "一致";
		case "MIN_CHECK": return "最小";
		case "MAX_CHECK": return "最大";
		case "MIN_LENGTH_CHECK": return "最小長チェック";
	}

	return "####" . $str;
}

function getCheckType( $str ){
	switch( $str ){
		case "EXIST_CHECK": // 必須
		case "ALL_EXIST_CHECK": // すべて必須
		case "TOP_EXIST_CHECK": // 上位が入力済み
		case "ONE_EXIST_CHECK": // どれか選択
		case "FILE_EXISTS": // ファイルの存在チェック
			return 1;

		case "NUM_CHECK": // 数値
		case "GRAPH_CHECK": // 英数記号
		case "KANA_CHECK": // カナ
		case "EMAIL_CHECK": // E-Mail形式
		case "MOBILE_EMAIL_CHECK": // 携帯Mail
		case "EMAIL_CHAR_CHECK": // E-Mail文字種
		case "TEL_CHECK": // 電話形式
		case "ZERO_CHECK": // 0チェック
		case "ALPHA_CHECK": // 半角英字
		case "CHECK_DATE": // 日付形式(ymd)
		case "CHECK_DATE2": // 日付形式(ymd-hm)
		case "KANABLANK_CHECK": // カナ(スペース許可)
		case "ALNUM_CHECK": // 英数
		case "FILE_NAME_CHECK": // ファイル名形式
		case "FILE_NAME_CHECK_BY_NOUPLOAD": // ファイル名形式(アップロード以外)
		case "HTML_TAG_CHECK": // Htmlタグ
		case "URL_CHECK": // URL形式
		case "IP_CHECK": // IPアドレス
		case "PROHIBITED_STR_CHECK": // 禁止文字
		case "SPTAB_CHECK": // スペース・タブのみ
		case "NO_SPTAB": // スペース・タブ
		case "ZERO_START": // 先頭が0
			return 2;

		case "MAX_LENGTH_CHECK": // 最大
		case "NUM_COUNT_CHECK": // 桁数
		case "CHECK_SET_TERM": // 期間チェック
		case "CHECK_SET_TERM2": // 期間チェック(秒まで)
		case "NUM_RANGE_CHECK": // 最小・最大
		case "GREATER_CHECK": // 値比較(<)
		case "DIFFERENT_CHECK": // 値比較(!=)
		case "SELECT_CHECK": // リスト範囲内
		case "EQUAL_CHECK": // 一致
		case "MIN_CHECK": // 最小
		case "MAX_CHECK": // 最大
		case "MIN_LENGTH_CHECK": // 最小長チェック
			return 3;
	}

	return -1;
}

function getH1Type( $file ){
	if( preg_match( "/\/data\/class\/pages\/(.*?)\//", $file, $match ) ){
		$ret = trim( $match[1] );
		return $ret;
	}

	return null;
}

function getH1typename( $name ){
	switch( $name ){
		case "": return "全体";
		case "admin": return "管理者";
		case "regist": return "登録";
		case "shopping": return "ショッピング";
		case "products": return "商品";
		case "campaign": return "キャンペーン";
		case "contact": return "お問い合わせ";
		case "entry": return "会員登録";
		case "inquiry": return "アンケート";
		case "mypage": return "MyPage";
		case "frontparts": return "フロントパーツ";
		case "tb": return "トラックバック";
		case "cart": return "カート";
		case "forgot": return "パスワード発行";
	}

	return "####" . $name;
}

function seleniumHead( $fp ){
	global $def_base_url;
	global $def_user_id;
	global $def_user_pass;
	global $def_user_id2;
	global $def_user_pass2;
	global $def_out_dir;
	global $def_product_id;

	$str =<<<__ECHO__
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>test</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">test</td></tr>
</thead><tbody>

<tr>
	<td>open</td>
	<td>{$def_base_url}/mypage/login.php</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>css=dd &gt; input[name=&quot;login_email&quot;]</td>
	<td>$def_user_id2</td>
</tr>
<tr>
	<td>type</td>
	<td>css=dd &gt; input[name=&quot;login_pass&quot;]</td>
	<td>$def_user_pass2</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=log</td>
	<td></td>
</tr>

<tr>
	<td>open</td>
	<td>{$def_base_url}/products/detail.php?product_id={$def_product_id}</td>
	<td></td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>id=cart</td>
	<td></td>
</tr>

<tr>
	<td>open</td>
	<td>{$def_base_url}/admin/</td>
	<td></td>
</tr>
<tr>
	<td>type</td>
	<td>login_id</td>
	<td>$def_user_id</td>
</tr>
<tr>
	<td>type</td>
	<td>password</td>
	<td>$def_user_pass</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>css=span</td>
	<td></td>
</tr>

__ECHO__;

	fwrite( $fp, $str );
}

function seleniumFoot( $fp ){
	$str =<<<__ECHO__
</tbody></table>
</body>
</html>
__ECHO__;
	fwrite( $fp, $str );
}

function seleniumPage( $fp, $name ){
	global $def_base_url;
	global $def_out_dir;
	global $def_urllist;
	global $def_user_id;
	global $def_user_pass;
	global $def_nodisp_urllist;

	preg_match( '/LC_Page_(.*)\.php/', $name, $match );
	$match[1] = preg_replace('/([A-Z][a-z]+)([A-Z][a-z]+)$/', '$1#$2', $match[1]);
	$pageName = strtolower( $match[1] );
	$pageName = str_replace( "#", "", $pageName );
	$pagePath = strtolower( $match[1] );
	$pagePath = str_replace( "_", "/", $pagePath,$ct );
	$pagePath = str_replace( "#", "_", $pagePath );
	$url = "{$def_base_url}/$pagePath";
	
	if( strpos($pagePath, "admin/") === 0 && $ct === 1 ){
		// index
		$url .= '/index.php';
	} else if( $ct === 0 ) 
		// index
		$url .= '/index.php';
	else {
		$url .= '.php';
	}
	
	if( isset( $def_urllist[ $url ] ) ){
		$url = $def_urllist[ $url ];
	}
		
	if( array_search( $url, $def_nodisp_urllist ) === false ){
		$str =<<<__ECHO__

<tr>
	<td>open</td>
	<td>$url</td>
	<td></td>
</tr>
<tr>
	<td>captureEntirePageScreenshot</td>
	<td>{$def_out_dir}\\{$pageName}.png</td>
	<td></td>
</tr>

__ECHO__;
	}

	// ログイン画面
	if( $url === $def_base_url . '/admin/index.php' ){
		$str .=<<<__ECHO__
<tr>
	<td>type</td>
	<td>login_id</td>
	<td>$def_user_id</td>
</tr>
<tr>
	<td>type</td>
	<td>password</td>
	<td>$def_user_pass</td>
</tr>
<tr>
	<td>clickAndWait</td>
	<td>css=span</td>
	<td></td>
</tr>
__ECHO__;
	}

	fwrite( $fp, $str );
	
	return $url;
}

function dispImg(){
	$src_img = imagecreatefrompng($_GET['file']);
	$img_height = @$_GET['h'];
	if( $img_height == 0 ){
		$img_height = 200;
	}
	$top = @$_GET['ct'] * $img_height;
	$src_width = imagesx($src_img);
	$src_height = imagesy($src_img);

	$img_width = $src_width;

	if( $src_height < $top + $img_height ){
		$img_height = $src_height % $img_height;
	}

	$dst_img = imagecreatetruecolor($img_width, $img_height);
	imagecopy($dst_img, $src_img, 0, 0, 0, $top, $img_width, $img_height);

	header('Content-Type: image/png');
	imagepng( $dst_img );
	imagedestroy($dst_img);
}

function file2lines($file){
	$token = token_get_all($file);
	
	$lines = array();
	$line = '';
	$case_flag = false;
	foreach($token as $key=>$data){
		if( is_string($data) ){
			if( $data === '{' || $data === '}' || ( $case_flag === true && $data === ':' )
				|| $data === ';' )
			{
				$lines[] = $str = ereg_replace("\r|\n","", trim( $line . $data ) );
				$line = '';
			} else {
				$line .= $data;
			}
		} else {
			$skip_token = array(
				T_COMMENT, T_DOC_COMMENT,
				T_OPEN_TAG,
			);
	
			if( $data[0] == T_CASE || $data[0] == T_DEFAULT ){
				// case start
				$case_flag = true;
			} else if( array_search( $data[0], $skip_token ) !== false){
				// reg
				$lines[] = ereg_replace("\r|\n","", trim( $line . $data[1] ) );
				$line = '';
			} else {
				$line .= $data[1];
			}
			$token[$key][99] = token_name($data[0]);
		}
	}

	return $lines;
}