プラグイン:MultiCounterXの紹介3

 第3夜はMultiCounterXの本体パッケージMultiCounterXの中で、MT::Appオブジェクトのメソッドを使用した部分について解説します。第4夜は、貧弱な内容になりそうですがローカライゼーションについて記載して終了となる予定です。

6.MT::Appオブジェクトメソッドの利用

 MultiCounterX.pmのコードを参照しながらMT::Appオブジェクトメソッドを利用した部分について説明します。

(1)クエリー文字列の取得
 紹介2で説明した通り、Tags.pmのファンクションタグハンドラーの中で最後にimgタグでCGIを呼び出すときに付加したクエリー文字列を取り出すのが、paramメソッドです。MT::AppはCGI.pmの機能を実装しているそうで、CGIオブジェクトのparamメソッドと同等です。main0関数はMT::Appオブジェクトへのリファレンスを第一引数で受け取れるのでこれを使用します。
 コード1のピンク色の行が受け取っている部分です。ここではほとんどをパッケージ変数に代入しています。日本語文字列についてはURIエスケープしてCGIに渡されますが、paramメソッドで取り出すときにはURIアンエスケープされているようです。

(2)MTディレクトリ
 コード1の青色部分がMTディレクトりを取得するmt_dirメソッドです。ここではデバッグ時のログ出力ディレクトリ、アクセスログディレクトリ、カウントファイルディレクトリのフルパスを生成しています。

(3)STDOUTへのイメージ出力
 コード1の最後のオレンジの行のprintメソッドは引数で指定したデーをそのまま標準出力に出力します。ここでは生成したイメージデータを引数ににします。

<コード1>

sub main0 {
 my $app = shift;
 $Debug = 0; #0:運用、1:イメージ出力機能テスト、2:テキスト出力
 $Dlog = 0; #1:デバッグ用ログ出力
 $Fontfile = $app->param('Fontfile');
 $Ddir = $app->mt_dir . '/plugins/MultiCounterX/lib/logs/D';
 $CNTDIR = $app->mt_dir . '/plugins/MultiCounterX/lib/countfiles';
# このディレクトリは事前作成
 $LOGDIR = $app->mt_dir . '/plugins/MultiCounterX/lib/logs';
 if($Debug == 2){
  $CType = "text/html";
 }else{
  $CType = "image/png";
 }
 my $PID = $app->param('blogid'); # ブログID
 # カウンターフォーマットをクエリーから取得
 $FRAMEX = $app->param('XSIZE');
 $FRAMEY = $app->param('YSIZE');
 $FRAMEFCOLOR = $app->param('FILLCOLOR');
 $FRAMEBCOLOR = $app->param('BORDERCOLOR');
 $MESSIZE = $app->param('SIZE');
 $M1 = $app->param('M1');
 $M1COL = $app->param('M1COLOR');
 $M1X = $app->param('M1XPOS');
 $M1Y = $app->param('M1YPOS');
 $M2A = $app->param('M2A');
 $M2ACOL = $app->param('M2ACOLOR');
 $M2B = $app->param('M2B');
 $M2BCOL = $app->param('M2BCOLOR');
 $M2X = $app->param('M2XPOS');
 $M2Y = $app->param('M2YPOS');
 $M3 = $app->param('M3');
 $M3COL = $app->param('M3COLOR');
 $M3X = $app->param('M3XPOS');
 $M3Y = $app->param('M3YPOS');
$Ninsyou_flag = 1; # 認証不要
 $app->send_http_header("$CType"),$app->print(&dbg_out("Test1")),return if($Debug == 1);
&init_counter($app,$PID,$app->param('SesTimeOut'),$app->param('KanriID')); # カウンター初期化
 &initgd; # GD初期化
 $app->print(&imgout);
}

(4)カウンター初期化
 コード1で呼び出しているinit_counterサブルーチンは、MT::Appオブジェクトリファレンス、ブログID、セッションタイムアウト値、管理者IDを引数にしてカウンター自体を初期化し各カウンター値を更新します。またセッションID・クッキーカウンター値(ブラウザ毎の訪問回数)等をクッキーに送信・保存するためにsend_cookieサブルーチンを呼び出します。但し、受信したクッキーによる判定ステートが「セッションIDが存在&そのIDが使用中&セッションタイムアウトしていない状態」の時のクッキー再送信処理はここで直接記述しています。
 このサブルーチンがカウンターアルゴリズムのメインになりますが、古いコードですので省略します。

(5)クッキーの送信
 受信したクッキーによる判定ステートが「セッションIDが存在&そのIDが使用中&セッションタイムアウト状態」or「セッションIDが存在&そのIDが未使用」or「セッションIDが存在しない」の3種の場合にinit_counterサブルーチンから呼ばれるサブルーチンがコード2(send_cookieサブルーチン)です。ここでセッションID・クッキーカウンター値(ブラウザ毎の訪問回数)等をクッキーに送信・保存します。
 この処理と上記init_counterサブルーチンの中で直接行うcookie送信処理をMT::Appオブジェクトメソッドを使用してみました。
 青字の部分がそのコードですbake_cookieメソッドでクッキーを生成して、ピンク色の行のsend_http_headerメソッドで他のヘッダーとともに送信します。bake_cookieの引数がクッキー情報です。sixapartのオブジェクトリファレンスでは「CGI::Cookie(または同じ引数を取るApache::Cookie)の「new」メソッドに渡すことができる有効な引数であれば、何でも指定可能です。」だそうです。
 
ここではセッションID、セッション登録日(秒)、クッキーカウンター値、ユーザーID(クッキー受信していた場合に限る:今のところユーザーIDを新規にクッキー送信する機能は未作成なので実際には送信されない)の4種類のクッキーを有効期限が送信日から5年として送信します。各クッキーのハッシュデータ生成後都度bake_cookieして最後に1回だけsend_http_headerします。クッキーデータのキーとバリューはセッション登録日以外はこのサブルーチン呼び出し元のinit_counter内で生成されます。
 send_http_headerの引数にはコンテントタイプを指定します。ここでは当然「image/png」がパッケージ変数$CTypeに格納されています。

<コード2>

sub send_cookie{
my($app,$scid,$unval) = @_;
&debug_write("empty_id -- $empty_id");
if (!($empty_id == 10000)){ #空きID有れば
    my $start = time;
    my $exp_st2 = get_local_time('exp',$start+60*60*24*365*5); #有効期限5年
    #######cookie送信処理  MT::Appの機能を使う
    my %ckdt =
    (   '-name'  => "$idnamekey",
        '-value' => "$empty_id",
        '-expires' => "$exp_st2",
        '-path' => "$cpath"
    );
    $app->bake_cookie(%ckdt);
    %ckdt =
    (   '-name'  => "$datenamekey",
        '-value' => "$start",
        '-expires' => "$exp_st2",
        '-path' => "$cpath"
    );
    $app->bake_cookie(%ckdt);
    $C_cnt++;
    %ckdt =
    (   '-name'  => "$ccntnamekey",
        '-value' => "$C_cnt",
        '-expires' => "$exp_st2",
        '-path' => "$cpath"
    );
    $app->bake_cookie(%ckdt);
    if($unval){
        %ckdt =
        (   '-name'  => "$unamekey",
            '-value' => "$unval",
            '-expires' => "$exp_st2",
            '-path' => "$cpath"
        );
    }
    ##########################################
    &debug_write("1 empty_id -- $empty_id : datenamekey -- $start : Ninsyou_flag -- $Ninsyou_flag");
    &id_out($empty_id,$start); #ID情報をファイルへ
    if(-e $CNTFILE){ #訪問中カウンターファイル
    ・・・(省略:訪問中カウンタ値更新しファイルへ)・・・
}else{ } $app->{no_print_body} = 1 if($Debug != 2); $app->send_http_header("$CType"); }else{ #空きIDなければクッキー送信しない $app->{no_print_body} = 1 if($Debug != 2); $app->send_http_header("$CType"); } &debug_write("2 empty_id -- $empty_id : datenamekey -- $start : Ninsyou_flag -- $Ninsyou_flag"); }