プラグイン:MultiCounterXの機能アップ

以前紹介したMT用プラグインMultiCounterXに、ログ集計グラフ機能を追加したので備忘禄を兼ねて記事にしておきます。とりあえずMT5.2.2で動作確認しました。そのうちGitHubで公開していこうと思いますのでその時はまたご案内します。

1.追加機能概要

 この記事の下方にも設定されているカウンターなわけですが、特徴としては下記です。

  • GDを使った画像出力(テキストフォントをそまま画像化)
  • セッション管理型訪問カウンター
  • クッキーカウンター
  • 各種メッセージ出力
  • かなりフレキシブルな出力フォーマット設定
  • 詳細な独自アクセスログ出力

 これら特徴のうち最後のアクセスログを使用してカウンターそのものをクリックするとログ集計してグラフ化する機能を今回追加しました。

 グラフ化するアプリ自体は以前作ったpsgiをMT用に少しモディファイしたpsgiで、今のところ、月指定で、日ごとの訪問者数をエージェント別積み上げ棒グラフにする機能と、その月の総訪問者数をエージェント毎のパーセント円グラフにする機能の2つが実装されています。このアプリをMTフレームワークを利用したCGIから呼び出します。カウンターをクリックすると、管理者ログイン画面を出してログイン成功すると月やグラフ種類の選択画面が出ます。ここまでがプラグインが生成した画面です。この画面でグラフ種類を選ぶとグラフ化アプリが呼び出されます。グラフ化アプリにはログイン情報やプラグインが取得したブログ情報を渡しています。これによりグラフ画面にブログ記事IDや記事タイトルの表示を可能にしています。


20170211A.jpg

一旦プラグイン設定で入力してある管理IDとパスワードを入力

20170211B.jpg

 

GOを押すと月とグラフメニュー選択画面を表示

20170211C.jpg

棒・折れ線グラフ

20170211D.jpg

円グラフ

20170211E.jpg

 

2.ブログ設定の追加

 ブログレベルの設定情報に下記を追加しました。

20170211F.jpg

20170211G.jpg

カウンター管理者名は以前からありましたが使ってませんでした。「訪問人数グラフ表示を行う」にチェックを付けて表示プログラムのURLに正しく入力しておき、設定したカウンター管理者名とパスワードを、カウンターをクリックした後の画面上のID,PASSに入力するとグラフ化メニューが表示される仕様です。

3.プログラムの変更

 カウンターはファンクションタグプラグインですので、テンプレートに<mt:CounterMessagesX>というタグを配置したところに、htmlのimageタグを出力するようになっています。この出力を決めているのがTag.pmです。今回の機能追加により、以下のような出力分岐をすることにしました

「グラフ表示を行う」にチェックが入っていて且つグラフ表示プログラム欄に入力あり
  →カウンターイメージタグにa hrefタグでグラフ表示用ログイン画面へのリンク付で出力
「グラフ表示を行う」にチェックが入っていないか又はグラフ表示プログラム欄が空欄
  →カウンターイメージタグのみ出力


下記がその部分です。DoAnalysisが「訪問人数グラフ表示を行う」、AnalysisProgramが「訪問人数グラフ表示プログラムURL」に対応するconfig.yamlで今回追加した設定項目名です。下記if文の最初がaタグ付き出力部分で、本プラグインCGI URLに$retst2というクエリーを付加したURLとなっています。$retst2には「__mode」というキーのパラメータを渡していますが、これが要点です。このキーの値は、プラグインCGIアプリの中で最初に呼ばれるinit_requestという関数の中で、対応する関数へのリファレンスが定義されています。

<Tag.pm>

・・・・・・
my $retst2 = "__mode=clogin&Page=$kiziID&cgi=$CGIURL&bid=$blog_id";
if(($plugin->get_config_value('DoAnalysis', $blog_id) eq 'do') and  
  ($plugin->get_config_value('AnalysisProgram', $blog_id) ne '')){
     return '<a href="'.$CGIURL.'?'.$retst2.'">
        <img src = "' . $CGIURL .'?' . $retst .'"/></a>';
}else{
     return '<img src = "' . $CGIURL .'?' . $retst .'"/>';
}

テンプレートファイルに追加した上記2つに対応するタグについても掲載しておきます。

<mc_setting_blog.tmpl>

・・・・・・
<mtapp:setting
 id="AnalysisProgram"
 label="<__trans phrase='_MCXAnalysisProgram'>">
  <input type="text" name="AnalysisProgram" id="AnalysisProgram"  
 value="<mt:var name="AnalysisProgram" escape="html">"  size="30" />
</mtapp:setting>
<mtapp:setting
 id="DoAnalysis"
 label="<__trans phrase='_MCXDoAnalysis'>">
  <input type="checkbox" name="DoAnalysis" id="DoAnalysis" value="do"
  <mt:if name="DoAnalysis"> checked="checked"</mt:if> size="20"/>
</mtapp:setting>

プラグインアプリのinit_requestの部分は下記です。__modeというクエリーパラメータで指定できるのは、clogin,selection,counter の3つです。これら3つのパラメータに対応する関数が定義されているのがわかります。disp_login1はログイン画面表示を提供、disp_selectionは月とグラフ種類選択画面を提供、main0はカウンター画像イメージデータを提供 という役割になります。

<MultiCounterX.pmのinit_request>

sub init_request {
    my $app = shift;
    $app->SUPER::init_request(@_) or return;
    $app->add_methods(
     'clogin'=>\&disp_login1,
     'selection'=>\&disp_selection,
     'counter'=>\&main0
    );
    $app->{default_mode} = 'clogin';
・・・・・・・・・・・・・
  $app->{requires_login} = 0;
}

「$app->{requires_login} = 0」は「リクエストのたびにMTログイン状態を確認しログイン状態で無ければMTが提供するログイン画面を最初に出す」という機能を使わない、という意味です。よって本来これを「1」にしておけば一々ログイン画面をアプリ側で作る必要ないのですが、うまく動きませんでした。これを1にしておくと、MTログイン画面は出るのですが、formのリンク先がまずく、
<form method="post" action="http:/mt.psgi -p 5000">
となっていました。MT管理画面で出る画面と比較するとおそらく/mt/mt.cgiにならなくてはいけないのだと思います。MTをpsgi化していると起きる不具合なのか、解決できませんでした。

最後にグラフのタイトル欄にブログタイトル文字列を表示したかったのでこの機能の実現方法を紹介して終わりです。下記が本プラグインのパッケージ最初に宣言しているモジュールです。

<MultiCounterX.pmのモジュール定義>

package MultiCounterX;
use strict;
use base 'MT::App';
use GD;
use Jcode;
use File::Path;
use MT::Entry;
use Encode;
use URI::Escape;

ブログのタイトル部に記事タイトルを表示するために、MT::Entry、Encode、URI::Escapeを今回追加しました。下記はdisp_selection関数内で記事タイトルを画面にhidden属性のフォームタグに埋め込むコードです。ブログの記事IDはTag.pmで出力したクエリーパラメータを引き継いでおり、「page」というパラメータで取得できるようにしています。この値をMT::Entryというブログ記事1件1件分を扱うためのオブジェクトのloadメソッドに渡すと、指定した記事オブジェクトリファレンス「$entry」が取得できます。このオブジェクトのtitleメソッドを使用すれば記事に書かれているタイトル文字列を取得できるわけです。

<MultiCounterX.pmのdisp_selection

・・・・・・・・・・・
my $entry = MT::Entry->load($app->param('page'));
my $tit = $entry->title;
Encode::decode('utf8',"$tit") if !(Encode::is_utf8("$tit"));
$tit = uri_escape_utf8( $tit );
$dst .= "<input type = \"hidden\" name = \"Title\" value = \"" . $tit . "\">\n";
・・・・・・・・・・・

Encode::decodeの行はFlagged(utfフラグ)で無ければFlaggedにする処理です。mtで入力した日本語は全てFlaggedのutf8になってるみたいですが。。念のため。

次の行は全角の日本語をuriエスケープするための処理です。これは必須です。当然受信するグラフ化アプリ側はunescape処理が必要ですので今回追加しました。

最後にhtml出力用の変数に代入しています。