<!--
   $FML: cgi.sgml,v 1.11 2003/04/15 14:51:40 fukachan Exp $
-->

<chapter id="cgi.internal">
	<title>
	CGI プロセスの内部構造
	</title>


<sect1 id="cgi.internal.method">
	<title>
	メソッド
	</title>

<para>
FML::CGI のクラスは以下のメソッド群を実装して下さい。
<screen>
html_start()
run_cgi_main()
run_cgi_title()
run_cgi_navigator()
run_cgi_menu()
run_cgi_command_help()
run_cgi_options()
html_end()
</screen>
ここで
html_start() は、
ようするに HTML の先頭部分、たとえば DOCTYPE から BODY あたりを、
html_end() は
/BODY と /HTML を表示する部分をカスタマイズするために用います。
run_◎◎ メソッド群では BODY の部分を定義しています。
</para>

<para>
$curproc の run() メソッドは
<screen>
html_start()
run_cgi_XXX() 群を実行(テーブル状に出力を配置する)
html_end()
</screen>
を順番に実行しています。
つまり CGI プロセスの実行のフロー( FML::Process::Flow 参照)は
<screen>
new()
prepare()
verify_request()
run()
   html_start()
   run_cgi_○○()
   html_end()
finish()
</screen>
ということになります。
</para>

</sect1>


<sect1 id="cgi.internal.frames">
	<title>
	CGI の画面の作りとメソッド
	</title>

<para>
fml CGI スクリプトでは典型的な画面が次のように分割されると考えています。
<screen>
          ヘッダ
◎        メニュー    ◎
バー１    メイン      バー２
◎        メニュー    ◎
          フッタ
</screen>
なお、バー１と２の部分は navigation などと呼ばれます。
</para>

<para>
ヘッダ部分( HTTP ヘッダではなく、HTML の DOCTYPE から BODY あたり)やフッ
タの部分は html_start() および html_end() で HTML コードを生成します。
</para>

<para>
一方、BODY の中身は真中の３ｘ３のテーブル状の部分で、run_cgi() から呼
ばれるメソッドが生成しています。
</para>

<para>
run_cgi() の中身をもっと細かくすることと、画面上のどの部分をどのメソッ
ドが記述するのかを指定できるアクセスメソッドが必要です。また、これにあ
わせて BODY の中身もより細かく次のような３x３の精度で表現されています。
<screen>
nw   north  ne
west center east
sw   south  se
</screen>
</para>


<sect2>
	<title>
	現在の CGI の画面の構造	
	</title>

<para>
以下のような３x３のテーブル構造をとっており、
それぞれ次のメソッドが表示を担当しています。
<screen>
run_cgi_main
			run_cgi_title
run_cgi_navigator	run_cgi_menu	run_cgi_command_help
run_cgi_options
</screen>
HTML のレベルでは、TABLE 命令を使って疑似的なナビゲーションバーのよう
なものを作っています。そして、ハッシュテーブルで定義されている関数を決
められた順番で実行し、テーブルを作成しています。
</para>

<para>
run_cgi_main() は何らかの処理をしない限り何も表示しません。大抵は「な
し」か「OK …」程度です。エラーメッセージを表示することもあります。ま
た、この関数はＭＬ一覧などをきちんと最新の情報にするために、画面を描く
前に実行する必要があります。
</para>

<para>
ちなみに、run_cgi_main() は個々の関数を呼び出すためのトップレベルのア
ダプター層で、FML::CGI::Menu::Admin に定義されています。個々のコマンド
は、makefml の時と同様に、この関数経由で実行されます。
</para>

<para>
ただし、ログやメンバーリスト一覧のように run_cgi_menu() から結果の表示
をしているものもあります。これは表示のオプションの指定をさせるために、
run_cgi_main() ではなく run_cgi_menu() 経由で表示しているともいえるの
ですが、なにしろコマンドの結果の表示が長いので、今のように menu() 経由
のほうがよいと思います。
</para>

</sect2>

</sect1>


<sect1 id="cgi.internal.trampoline">
	<title>
	画面とトランポリン機構
	</title>

<para>
CGI の表示部分は
FML::Command::
以下のクラスに移動させました。
しかしながら、
FML::Command::
の中に実体があるとは限らず
object composition の形式で
FML::CGI:: クラスが提供するメニュー生成クラスを
使うことになっています。
たとえば subscribe の場合
<screen>
FML::CGI::Admin::Main →
FML::Command::Admin::subscribe →
FML::CGI::Admin::User →
メニューの表示
</screen>
などとなっていて、
Mach のトランポリン機構のように、いったりきたりします。
</para>

</sect1>


<sect1 id="cgi.internal.problems">
	<title>
	備考: FML::CGI::Admin:: ではハードコーディングするしかない？	
	</title>

<para>
例えば FML::CGI::Admin::User では
$comname と maps の関係がハードコーディングされてるけれど、
でも、これはある程度はしかたないでしょう。
</para>

<para>
設定ファイルに追い出すと、とてつもなくいっぱい変数が必要になりそうです
が、できるだけ config.cf で変更可能であるようにこころがけています。
</para>

</sect1>


<!-- 後半では .cgi の実装例について解説する -->
&sect.internal.cgi.examples;


</chapter>
