D3モジュールの問題点として、イベント通知処理が面倒、というのがあります。
X2のNotificationHandlerは、triggerEvent()する時に、
ROOT/modules/(dirname)/language/(lang)/mail_template/(mail_template).tpl
を読みに行きます。
そこにファイルが無かった時点で、イベント通知は無効だとして処理がスキップされてしまいます。
それを回避するために、d3forumやpicoでは、それぞれ独自のtrigger_event関数を作っていたのですが、それは明らかに工数の無駄です。
D3モジュール用に、イベント処理テンプレートファイルをTRUST_PATHの下からも検索してくれる共通のルーチンを書けば良いだけです。
D3モジュールを使うならaltsys必須
というのも事実上ルール化してますので、D3NotificationHandlerクラスをaltsysに追加しました。
使い方は簡単です。
$notification_handler =& xoops_gethandler( 'notification' ) ;
$notification_handler->triggerEvent($category, $item_id, $event, $extra_tags, $user_list, $module_id, $omit_user_id);
require_once XOOPS_TRUST_PATH.'/libs/altsys/class/D3NotificationHandler.class.php' ;
$notification_handler =& D3NotificationHandler::getInstance();
$notification_handler->triggerEvent($mydirname, $mytrustdirname, $category, $item_id, $event, $extra_tags, $user_list, $omit_user_id);
ROOT/modules/(mydirname)/language/$language/mail_template/
TRUST/modules/(mydirname)/language/$language/mail_template/
ROOT/modules/(mydirname)/language/english/mail_template/
TRUST/modules/(mydirname)/language/english/mail_template/
8月29日深夜より、XUGJがアクセス過多でSWAPしまくり状態になり、ほぼダウンした状態になりました。
私が連絡を受けた時点ですでにSSHログイン効かない状態になっていて、かろうじて生きていたserver-statusで確認した限りでは、大量のクローラがW状態でした。明らかに大量のリクエストを処理しきれなかったのが原因でしょう。
# 大量のクローラーのうち、特に悪質だと思われるのは、baidu-jpとbecome。
# この2つは、iptablesレベルで弾いた方が良いかもしれません。
# XCLで運用しているみなさんもお気をつけください
その後も状況は悪化する一方で、sshは完全に無反応、server-statusも効かなくなり、もはやハードウエアリセットしか手はない状態です。
しかし、その専用サーバをホスティングしている会社は、週末は一切連絡がつきません(個人的にはそれが一番信じられませんが)。つまり、月曜の朝に社員が出社してくるまで、XUGJがダウンし続けることはほぼ確定しました。XUGJの管理をお手伝いしているものとしては大変心苦しいのですが、月曜朝までお待ちください。
XUGJのサーバが復活し次第、fabiさんと相談して、同様の事態にならないような対策(ホスティングサービスの変更も含む)を講じたいと思います。
(2008/9/1時点で復旧しています)
「今さら定義?」という気もするのですが、ホダ塾メンバーでさえも、D3の重要な仕様を知らなかったことに驚き、あらためて"D3"を定義したいと思います。
もともと"Duplicatable"は、X2の制限をいかにして回避するか、ということを考えて積み上げられてきたテクニックの集大成です。
つまり、「X2で動くこと」というのがすべての"Duplicatable"の大前提となります。それはD1・D2・D3に共通します。
だから、「XCL専用」のモジュールは、複製可能でXOOPS_TRUST_PATHを使おうとも、それはD3ではないのです。
もちろん、「X2でも動作確認しなさい」などと偉そうに言うつもりはありません。ただ、D3の構造を素直に利用すれば、X2でも自動的に動くはずなのです。(この部分には多少誇張が含まれてますが)
D3の構造を意図的に外して、XCL専用とするのも当然自由ですが、それがD3でないのは自明です。
D3の構造で作ったけど、できあがったものはX2互換がなかった、なんて可能性も当然考えられます。そしてX2での動作確認を必要条件にするつもりもありません。でも、そういうケースならX2互換にするのは簡単でしょう。
D3モジュールは、世界中のX2アーキテクチャーで動きます。ImpressCMSでも、JP版X2でも、もちろん本家版XOOPSでも(一部要修正)。だからこそ、XCL専用モジュールには"Duplicatable V3"という名前を冠して欲しくないのです。それはXCL以外の海外ユーザの誤解を招くからです。
前置きが長くなりましたが、D3モジュールの定義を書きます。
*必要条件(こうじゃなければD3モジュールとは呼べないもの)
(1) 原則的にX2互換であること
(2) dirnameが[0-9a-zA-Z_-]のキャラクター組み合わせで自由に決められること
(3) ほとんどのロジックがXOOPS_TRUST_PATHの内側にあること
(4) ROOT/modules/下にあるディレクトリをコピーするだけで複数動作すること(そこにソースコード書き換えは一切発生しないこと)
(5) XOOPS_TRUST_PATHの内側(ロジックの記述されたファイル)は複製する必要がないこと
*推奨条件(そうじゃなくても良いが、できれば対応して欲しいもの)
- ROOT/modules/(dirname)/mytrustdirname.php ファイルを用意すること
- 利用する各テーブルは (prefix)_(dirname)_(table) という名前でCREATE TABLEされること
- テンプレートは (dirname)_(tplfile) という形でDBに取り込まれること
- blocks/(tplfile).html という階層を持ったテンプレートをブロックに利用しないこと(=ブロック用のテンプレートも他のmoduleテンプレートと同様に扱うこと)
- 特に理由がなければ、ブロックも複製可能とすること(can_cloneのセット)
- D3言語マネージャを利用すること
- コメントにはd3コメント統合が利用できること
「推奨条件」はまだ増えるかもしれませんが、「必要条件」は最初の5つだけです。
なお、D3モジュールの構造については、Gnaviのkentaroさんが判りやすいドキュメントを作成してくれています。まだ途中ではありますが、非常に良くできたテキストで、これからD3モジュールを作ろうという人にも、すでに作ったことのある人にも役立つと思います。
http://xoops.iko-ze.net/modules/pukiwiki/
EMLH-1.30相当の機能をpreloadで実現してみました。HDのpreload/disabledにもこっそり忍ばせてあったりします
preload/MultiLanguagePostMerger.class.php
<?php
if (!defined('XOOPS_ROOT_PATH')) exit();
@include_once XOOPS_ROOT_PATH . '/modules/cubeUtils/class/MultiLanguage.class.php';
class MultiLanguagePostMerger extends XCube_ActionFilter
{
function preFilter()
{
if ( ! empty( $_POST ) && file_exists(XOOPS_ROOT_PATH.'/modules/cubeUtils/class/MultiLanguage.class.php')) {
// just after MultiLanguagePreLoad
$this->mController->mGetLanguageName->add(array(&$this, 'postMerger'),XCUBE_DELEGATE_PRIORITY_FINAL+1);
}
}
function postMerger()
{
global $cubeUtilMlang ;
if( is_object( $cubeUtilMlang ) ) $this->mergeRecursive( $_POST ) ;
}
function mergeRecursive( &$data )
{
global $cubeUtilMlang ;
$merged_string = '' ;
$langs_counter = 0 ;
foreach( array_keys( $data ) as $index ) {
if( is_array( $data[ $index ] ) ) {
$this->mergeRecursive( $data[ $index ] ) ;
} else if( in_array( $index , $cubeUtilMlang->mLanguages ) ) {
$merged_string .= '['.$index.']'.$data[ $index ].'[/'.$index.']' ;
$langs_counter ++ ;
}
}
if( $langs_counter == sizeof( $cubeUtilMlang->mLanguages ) ) {
$data = $merged_string ;
}
}
}
EMLHに限らず、多言語系のHackはデータ入力にやや困難を抱えています。
[en]English[/en][ja]日本語[/ja]
<input type="text" name="subject" id="subject" size="80" maxlength="255" value="<{$content.subject}>" />
English:
<input type="text" name="subject[en]" id="subject[en]" size="80" maxlength="255" value="<{$content.subject|easiestml:"en"}>" />
Japanese:
<input type="text" name="subject[ja]" id="subject[ja]" size="80" maxlength="255" value="<{$content.subject|easiestml:"ja"}>" />