Phased Upgrade (1)
Legacy
モジュールはモジュールアップグレードのための新しい仕様を実装しました。 XOOPS2 JP
において、アップデートスクリプトの仕様がアップグレードステップに対して十分ではなかったため、モジュール開発者は彼らのモジュールを自在にアップグレードすることができませんでした。モジュールの歴史の上では、多くのことが変更されます。
DB
テーブルへの新しいフィールドの追加、モジュールへの新しいブロックの追加、コールバック関数の改名やリソースの除外……
XOOPS JP
はこれらの情報を厳密な定義なしで自動的に更新しようと試みます。すなわち、そこに厳密なルールはありません。そのため、モジュール開発者は
XOOPS2 JP がどのようにモジュールを更新するかを調べるために XOOPS2 JP
を探索しなければなりませんでした。
ベータ3で、 Legacy System モジュールは vBulletin
ライクな段階的アップグレードモード (phased upgrade mode)
を導入しました。このモードでは、アップグレードはマイルストーン・バージョンに制限されます。たとえば、以下のような悪魔的なチェンジログを持つモジュールがあるとします。
- v0.10 初版 (varchar(255)の value フィールドが DB
テーブルに存在)
- v0.20 新たに整数フィールド 'value2' をテーブルに追加
- v0.30 既存フィールド 'value' を DB テーブルから削除
- v0.35 'value2' を 'value' に改名
この悪魔的なチェンジログに対して、あなたはどのようにコールバック関数を書きますか? 不可能ではありませんが、それはとても困難です。大半のプログラマは
XOOPS2 JP
のよくないスペックと格闘することに時間を浪費したいと思わないでしょうから、大胆な変更は失われていきます。
段階的アップグレードは、アップグレードを複数のプロセスに分割することを可能にします。この例であれば、
1) v1.0 -> v2.0 upgrade
2) v2.0 -> v3.0 upgrade
3) v3.0 -> v3.5 upgrade
この方法により、ユーザーはいかなるバージョンからも正常に最新版へアップグレードすることができます。そして、モジュール開発者は
Legacy System モジュールの自動的不正確アップグレード機能を抑制することができます。
モジュール・アップデート機能はベータ3より Legacy_PhasedUpgrader
クラスを使用します。モジュール開発者が段階的アップグレード(phased upgrade)を望む場合、彼は
Legacy_PhasedUpgrader
のサブクラスを宣言しなければなりません。彼はクラスの全メソッドをオーバーライドすることができますが、
Legacy_PhasedUpgrader
はモジュール開発者が段階的アップグレードを容易に実現できるように設計されています。したがって、マイルストーンバージョン番号とそのバージョンへのコールバックメソッドを定義するだけでよいでしょう。
Example Module "upgradeTest":
-
まずはじめに、
upgradeTest-0.10
をインストールしてください
-
次に、
upgradeTest-0.35
をアップロードし、それからこのモジュールをアップデートしてください。
-
あなたは三段階でアップグレードしなければならないでしょう。
この例のチェンジログは上の悪魔的チェンジログです。しかし、あなたは以下のようなステップで正確にアップグレードを達成するでしょう。
(1) upgradeTest 0.10 -> upgradeTest 0.20 (Phased
Upgrade) -> (2)
(2) upgradeTest 0.20 -> upgradeTest 0.30 (Phased
Upgrade) -> (3)
(3) upgradeTest 0.30 -> upgradeTest 0.35
upgradeTest-0.35 はモジュール開発者のための良いサンプルです。
OSC2006/Fall Inside Story
インサイドストーリーといっても、これは別におおげさな話ではありません。先週の土曜、私は
OSC2006/Fall (Open Source Conference 2006 tokyo Fall)
に出掛けました。これは日本オープンソース界でもっとも有名なイベントです。多数の企業とコミュニティがこのイベントに参加しました。彼らはブースを開き、講演を行いました。
XOOPS Cube 日本コミュニティも参加しました。 XUGJ (Xoops Users Group
Japan) メンバーがブースで出展しました。開発チームからは、私と nobunobu
さんがスピーチを行いました。このインサイドストーリーはそのスピーチに関するものです。
先週の金曜日、翌日のためのプレゼンテーションファイルはまだ完成していませんでした。初代開発チームはもうすぐその役割を終えるので、
OSC2006/Fall は開発チームにとって最後のイベントです。次の OSC
からは、モジュール開発者が主役と中核を担うようになります。したがって、私は自分の意見のすべてを話すつもりでした。私はプレゼンテーションファイルを完成させるために最善を尽くしました。そして、
AM 3:30 、それは完成しました。ファイルは私の mac mini に格納され、 mac mini
は私のバッグに格納されました。それから私は睡眠を取りました。
翌日、私は繰り返し mac mini の VGA アダプタを確認していました。7月の XTC2006
イベントで、私は VGA を忘れたことがありました。そのため、 XTC
スタッフは私のスピーチが始まる前にショップに駆け込まなければなりませんでした。私は同様の失敗を恐れていました。私はバッグの中で
mac mini の VGA アダプタの存在を確認すると、新宿へ出発しました。そのとき、 mac mini
の AC アダプタは私の部屋の床の上にありました……
私は特急列車に5ドルを払うと、誰よりも早く講演会場に到着しました。それから、私は自分のスピーチの準備を始めました。もちろん、その準備は終わりませんでした……
mac mini は AC アダプタなしではブートアップできないからです。信じられない!
私には20分しかありませんでした。もちろん、 AC
アダプタを取りに帰宅することは不可能です。開発チームのメンバーは、私が ML
にいくつかの古いバージョン投稿した PDF
ファイルを使うことを提案しました。他に方法はありません。しかし、講演会場ではネットにつなぐことはできませんでした。私はブースへ行ってダウンロードをお願いしました。しかし、ブースでも、誰もネットにつなぐことができていませんでした。
gusagi
さんは彼のモバイルカードを使ってファイルをダウンロードしてくれました。そのおかげで、私はスピーチ用の
PDF ファイルを手にいれることができました。
この準備のために私は19分を費やしました。私は講演会場へ駆け込みました。私のスピーチは何の問題も(そして何のアニメーションも)なく終了しました。
それから、私は次のスピーチのために AC
アダプタを取りに帰宅しなければなりませんでした……なぜなら、次のスピーチのための PDF
ファイルは作られていないからです。私はそれのために2時間を費やしました。
ところで、私は3週間にわたり風邪をひきつづけています。そして、このトラブルで病状は悪化しました。再び講演会場に到着した時、私は2つの薬を使いました。恐らくこの2つの薬の組み合わせは私にとって悪かった。体調は最悪になりました。しかし、お客さんは私の2回目のスピーチを楽しんでくれました。
私の持ち時間をこのトラブルで失ってしまったことと、体調が悪すぎたので、私は他の OSS
のブースやスピーチを訪問することができませんでした。新しいページが、私のトラブル伝説に加えられました。
しかし、私は OSC2006/Fall に加わったことをうれしく思っています。あなたは私のスピーチの
PDF ファイルここで見ることができます。
Legacy_AbstractModuleInstaller
誰だこのくそったれクラスを書いたのは!? 俺だ……
最近、私はこのタスクに挑戦しています。私はこのタスクを
Beta 2 で仕上げることが出来なかった。しかし、
Legacy_AbstractModuleInstaller
はモジュール開発者向けに設計されていないので、これは少し難しい……私はこのクラスを掃除することにしました。
もしこのタスクが達成されれば、モジュール開発者は vB
ライクな段階的アップデートを使うことができるようになります。私は Beta 3
までにそれを仕上げて、モジュール開発者にレビューをお願いしなくてはいけません。
XOOPS Cube Legacy KICK START GUIDE
私は、「XOOPS Cube Legacy
キックスタートガイド」を Legacy
モジュールのヘルプに加えました。KICK START
は、私のお粗末な英語で書かれています。心配はいりません。私の友人は、それを編集してくれます。
ビギナーは、このキックスタートで XOOPS Cube Legacy 2.1
の基礎的な使用を学ぶかもしれません。しかし、ひとつ問題があります……
ありえないことに、KICK START
は、「ニュース」モジュール &
「newbb」モジュールを説明に使います !
D3
modles ( bulletin2
、 d3forum )
が私の英語では説明できないからです……
。それに、
D3
モジュールは、特別なディレクトリツリーを必要とします。そのため、私は、最初のチュートリアルにそれについて書くことに躊躇してしまいました。
おそらく、 bulletin1
、及び、 xhnewbb
を選択するべきでした。しかし、これらのものは、レビューをされるでしょう。私達にとって重要なことは、レビューのための標準のチュートリアルの草稿を得たことだと思います。
Legacy_AbstractBlockProcedure
Description
Legacy_Controller
はXoosModue
インスタンスと同様にXoopsBlock
インスタンスを直接使用しません。
ブロックプロセスでは、Legacy_Controller
はLegacy_AbstractBlockProcedure
クラス系を使用します。
これとLegacy_AbstractModule
は同じ概念です。
Legacy_AbstractModule
を理解していないなら、このエントリを読んでください。
モジュールがクラス使用を宣言しない場合では、Legacy_Controlle
はアダプターのクラスとしてLegacy_BlockProdecureAdapterを使用します。
このクラスはXOOPS2
仕様を完全に模倣します。
Legacy_AbstractModule
とは異なり、Legacy_Controller
は明示宣言なしではブロックのクラスを見つけようとしません。
したがって、モジュール開発者はそれを望むならxoops_version.php
でのブロックのクラス名を定義する必要があります。
How to create instance
- $modversion['blocks'][x]['class'] = '{Class}';
を xoops_version.php で定義します
- $modversion['blocks'][x]['file']で指定されたファイルに
Legacy_BlockProcedure のサブクラスとして {Dirname}_{Class}
クラスを定義します
- メソッドを実装します
開発者はこれを何のために使いますか?
Legacy_Controller
が正しくアダプターのクラスを使用するので、多くの場合、モジュール開発者はこのメカニズムを使用する必要はありません。
しかし、いくつかのケースでは、XOOPS2 JP
仕様は十分ではありません。
それに対して、このメカニズムは役に立ちます。
XoopsBlockへのアクセス
XOOPS2 JP
によって呼ばれたブロックショー関数は、この関数のシグニチャがXoopsBlock
インスタンスを含んでいないので、XoopsBlock
インスタンスにアクセスすることができません。Legacy_Controller
は、Legacy_BlockProcedure::execute()
をブロックショー関数の代わりにコールします。したがって、モジュール開発者は$this->_mBlock
にアクセスできます。
XoopsBlock解釈の変更
たとえば、piCal
はブロックのタイトルを変えるためにcommon.php
が使用した大域変数にアクセスします。
それはすばらしく、かつ、正統でないアプローチです。
しかし、XOOPS Cube Legacy
はそのような場合のための正統のアプローチを提供します。
クラスを作成してください、そして、getTitle()
をオーバーライドしてください。
ヒドゥンブロック
仮想のcron
としてブロックキャッシュつきブロックを使用するのを望んでいるなら、isDisplay()
をオーバーライドしてください。
isDislay()
がfalse
を戻す場合、Legacy
はブロックディスプレイなしでキャッシュを作成しようとします。
描画プロセスの変更
common.php
がブロックを描画するため、XOOPS2
JP
ブロックはレンダリングプロセスを変えることができません。
しかし、XOOPS Cube Legacy
では、Legacy_BlockProcedure
がそれ自身の結果をレンダリングしようとします。
したがって、モジュール開発者はテンプレートファイルや依存レンダーシステムを変更することが出来ます。
Note
もし
$modverison['block'][x]['class']
が定義済みであるなら、モジュールインストーラは
$modversion['block'][x]['show_func']
を無視します。
実例
β
の
stdCache
モジュールを見てください。
How to prevent XoopsErrorHandler
まずはじめに、GIJOEさんのエントリを読んでください。いくつかのXOOPS2が使用するライブラリとモジュールは、
Notice や Warning
を発生させます。それらはLegacy
の働きに干渉します。
熟慮を重ねた末、私は、再びXoopsErrorHandler
を配置することにしました。しかし、回避策がここにあります。
Legacy_Controller
はデバッガインスタンスを作成するのにデリゲートを使用するようになりました。
したがって、モジュール開発者とユーザはpreloadかmodule
preloadでカスタムデバッグモードを使用することができます。
以下のコードは例です。 '
preload/DevelopPHPDebugger.class.php'
ファイルを作成してください、そして、以下のコードをコピーしてください。
if
(!defined('XOOPS_ROOT_PATH'))
exit();
require_once
XOOPS_ROOT_PATH .
"/modules/legacy/class/Legacy_Debugger.class.php";
class
DevelopPHPDebugger
extends
XCube_ActionFilter
{
function
preFilter()
{
$this->mController->mSetupDebugger->add("DevelopPHPDebugger::myFactory");
}
function
myFactory(&$instance,
$debug_mode)
{
switch($debug_mode)
{
case
XOOPS_DEBUG_PHP:
$instance
=
new
My_PHPDebugger();
break;
case
XOOPS_DEBUG_MYSQL:
$instance
=
new
My_MysqlDebugger();
break;
case
XOOPS_DEBUG_SMARTY:
$instance
=
new
My_SmartyDebugger();
break;
case
XOOPS_DEBUG_OFF:
default:
$instance
=
new
Legacy_NonDebugger();
break;
}
}
}
class
My_PHPDebugger
extends
Legacy_PHPDebugger
{
function
prepare()
{
error_reporting(E_ALL);
}
}
class
My_MysqlDebugger
extends
Legacy_MysqlDebugger
{
function
prepare()
{
}
}
class
My_SmartyDebugger
extends
Legacy_SmartyDebugger
{
function
prepare()
{
}
}
Legacy_AbstractModule
Description
サブコア
Legacy
は、仮想コントローラを持っています。このコントローラは、新しいインタフェースを通じて、モジュール、ブロック、及び、テーマを扱います。
(XOOPS Cube
における「コントローラ」は CMS
の手続きとしての一種の枠組であって、開発フレームワークではありません )
XOOPS2 case
まず初めに、
XOOPS2
の仕様を思い出してください。XOOPS2
には XoopsModule
、及び、 XoopsBlock
があります。これらのクラスは、モジュールデータ &
ブロックデータを扱うための基底クラスです。 XOOPS2
は、それらを直接扱います。従って、モジュール開発者は、 XOOPS2
が xoops_version
のデータをどのように解釈するかということに、従わなければなりません。例えば、モジュールは、いかなる影響も
XOOPS2
のキャッシュ機能に与え得ず、また、ブロックのタイトルを変更することもできません。
Legacy case
さて、
Legacy
の代替アーキテクチャを見ていきましょう。Legacy controller
は、 XoopsModule
、及び、 XoopsBlock
を直接使いません。Legacy
は、データ解釈を Legacy_AbstractModule
、及び、 Legacy_AbstractBlockProcedure
に委託します。これらのクラスは、コントローラと接続するためのインタフェースを持つ抽象クラスです。モジュール開発者は、コントローラから使用されるように、これらのクラスのサブクラスを定義し得ます。サブクラスには、そのメンバープロパティとして
XoopsModule
オブジェクトがあります。従って、モジュール開発者は、彼のモジュールサブクラスにおいてデータ解釈を変えることが可能です。
How to create an instance
- 'Module.class.php' ファイルをモジュールの /class
ディレクトリ下に作成してください
- {Dirname}_Module クラスを Legacy_AbstractModule
のサブクラスとして定義してください
- メソッドを実装してください
{Dirname}_Module
がすでに定義されている場合は、インスタンスファクトリは 'Module.class.php'
をロードしません。このルールは複製可モジュールに有効かも知れません。ぜひレビューしてください。
詳細は /module/legacy/class/Module.class.php
を例としてご覧ください。また、実装すべき '
オーバーライド可能'
なメンバ関数については、 Legacy_AbstractModule
をご覧ください。
For compatibility
大部分のモジュールは、そのようなサブクラスを持っていません。モジュールがそのようなサブクラスを持っていない場合、
Legacy
は、 'Legacy_ModuleAdapter'
を XOOPS2
互換性のためのアダプタクラスとして使います。このアダプタは、完全に XOOPS2
仕様を模倣します。更に、このアダプタクラスは抽象クラスではありませんので、迅速な使用に有益です。モジュール開発者は、このアダプタクラスをサブクラスのための基底クラスに選ぶかもしれません。
Is it possible to change
factory?
ファクトリの前提条件は、
$xoopsModule->get('dirname')
によって指定されたモジュールが、モジュールの /class
ディレクトリに Module.class.php
を持っていることです。この仕様は、複写可能なモジュールにとっては、には不幸です。サブクラス、及び、アダプタクラスのインスタンスを生成するためのファクトリは、
Legacy_Utils
に静的関数としてあります。そのため、モジュール開発者は、命名規則を変更出来ません。言い換えれば、そのファクトリは固定パイプライン機能です。しかし、ファクトリの関数は、
XCube_Delegate
を使います。従って、開発者は、デリゲートを通じて固定パイプラインのファクトリに割り込むことができます。
同様に、既に指定されたクラスが定義されているならば、 Legacy
が Module.class.php
の読み込みをスキップすることは、重要です。従って、複製可能なモジュールへの多くの解決策が発案されるでしょう。ぜひレビューをお願いします。
Note
Legacy
が作成するインスタンスは、 $root->mContext->mModule
にセットされます。ルートオブジェクトを得ることによって、モジュール内でこのインスタンスにアクセスすることができます。
Reviews
"基底クラスは
Legacy
モジュールの /kernel
ディレクトリにある。したがって、ファクトリもまたファイルを /kernel
ディレクトリに求めるべきである。" (minahito)
How to upgrade to Beta from Alpha
You must do some processes before Beta installation.
Uninstall the base module and the user
module
At first, turn off the active value of
these modules in the module management:
Then, you'll be forward to the 2nd installer.
Uninstall
two modules completely.
Don't forget clicking 'Uninstall'.
Remove the base module form your file
system
You must use the legacy module instead of
the base module. Therefore, you don't need the base
module. If you keep the base module, Beta may get
some troubles. You must remove it. OK?
Overwrite files with the beta
Then, you will
see the following screen after upgrade. Click
'Install' button to work the beta.
The class dialog for important classes of Beta
主要なクラス、重要なプロパティとメソッドがこのダイアログに載っています。このダイアログはすべての要素を含んでいるというわけではありません。しかし、それは
Beta を読むには十分です。
PDFファイルはここにあります。印刷して、トイレの壁に貼ってください:
A new team style in Cube world
XOOPS Cube
は小さい政府主義を志向し、小型のコアプログラムとコンベンションを開発します。
XOOPS JP
はマルチバイトとセキュリティ方針に関して
XOOPS2
と異見があります。これらの問題により、私たちはフォークしました。
だれでもCube
の世界では公式のマークなしで解決策を開発することが出来るので、Cube
には同様の問題はありません。
しかし、何人かのユーザは、Cube
は新しい公式サイトを得るためにフォークしたのだと考えています。
彼らは、セントラルチームが何であるかを見いだすことができていないので、Cube
の方針に混乱しています。
私たちの方針はまだ(厳格に)統一されてはいません。しかし、私たちはXOOPS2
の中央集権制とは異なったスタイルを目的としています。これは確実なことです。無政府主義は活発な人々の情熱を妨げません……
なぜなら、だれも認可を得る必要がないからです。チームメンバーの数には上限がありますので、オープンな公式のチームは実現困難です。
しかし、公式という概念が存在しないなら、開発者は、いつでも自由に加わって、抜けることができます。
私たちはCube
に関するどんなプロジェクトにも干渉するようなキャプテンを必要としていません。
オフィシャルと3rdの違いを取り除く
公式サイトが中央であることは良い考えではありません。Cube
には、交換可能なベースモジュールと十二分な柔軟性があります。
しかし、サイトには、1
つの特定の実現がなければなりません。
それはCube
の真価の否定です。
そして、私は、他のリポジトリにおける行動派の人々が '3rd party'
と呼称されることを理解することができません。
それはナンセンスです!
いかなるプロジェクトのいかなる開発者も他のプロジェクトにいかなる特権を持ちません。
行動派はお気に入りのプロジェクトを選択する
例えば、現在、私は
Cube 開発チームのコアメンバーのひとりです。
しかし、私は、XUGJ
の通常メンバーでありたいです。もちろん、私が、XUGJ
で一生懸命活動するのを望んでいるなら、XUGJ
は私を受け入れるでしょう。
xoopscube.jp
は私たちではなく行動派の方々によって管理されるでしょう。
管理者は、彼らのデフォルトのための1
つのベースモジュールを選んで、xoopscube.jp
パッケージを計画します。
私はその計画に干渉しません。
そして、私には、そのプランに関して一切の義務がありません。
しかし、それがおもしろいなら、私は、開発者としてプランに参加することを望むかもしれません。
この場合、私はコアメンバーではなく、ゲスト開発者です。
開発者は自分の自由時間に合わせてどのプロジェクトに参加するか決定する
開発者は自分の自由時間がどれくらい長いかによって、バイキング料理を楽しみます。
「うーん、一日あたり3時間の自由時間か……」
「どのプロジェクトを選ぼうか?」
メンバー交替
私は来年、開発チームを離れるつもりです。
それはCube
スタイルのための一種のテストです。
このスケジュールは昨年に決められました。
しかし、コアメンバーには多すぎる義務がないので、次世代開発者を見つけるのは簡単でしょう。彼が
.jp
か .org
に参加することを望んでいるなら、彼は、それらにメンバーであることを要求するかもしれません。
彼が望むなら、より多くのプロジェクトを選べばよいでしょう。
私はCube
ツール開発があるXOOPS
Cube
を継続するつもりです。そして、必要に応じて、私は、再びメンバーであることを要求するかもしれません。
How to make cool dialogs by OmniGraffle
Interface in PHP4
私たちはPHP4でインタフェースと多重継承を使用することができません。そのため、いくつかの XCube
層のクラスを設計することが困難になっています。
例えば、XCube_PageNavigatorは、情報の交換のために他のインスタンスに接続する必要があります。しかし、他のクラスは他の基底クラスを拡張するかもしれません。したがって、XCube_PageNavigatorによってコールされるメソッドを持っている抽象クラス(インターフェイス)を定義したいと考えます。しかしながら、それはPHP4では不可能です。ですから、私は
XCube_Delegate を使用しなければなりません。
といっても、PHP4
は型安全ではありませんから、私は開発者のためにインターフェイス定義を示すためにダミーのクラスを定義することができます。ひょっとすると、PHPの偉大なプログラマはそのようなコードをスマートに書いているのかもしれない。しかし、私はPHPとライトウェイトのプログラミングに関する
Tip を知りません。私の経験は型安全な言語のみです。そのため、XOOPS
CubeのソースコードはPHPプログラマに対して決して美しくありません……
私は私たちが使用するプログラム言語が何であるかにこだわりません。
PHP4がレンタルサーバの主要な環境であるなら、私たちはXOOPSにPHP4を使用するべきです。
これはエンタープライズではありません、ただ趣味です。しかし、PHP4のいくつかの仕様がXOOPS
Cubeコードを不透明にします。
私は頭が固いのです。そして、私は、ライトウェイト言語を使いこなせていません。私は、さらに学ぶ必要があります。
I'm home...
忙しすぎる……私は平日家にいることができません。そのため、このブログも更新できずにいます……というのも、このサイトは
Mac アプリケーションで生成されているからです。先月のエントリ数はたったの5つ。う〜ん……
今夜は着替えを取りに帰宅しました。忙しいスケジュールの間でも、ブログを更新するためにどのような方法がありますか? 私はリモートデスクトップを試してみるつもりです。それがうまくいけば、ちょっとした休憩時間にブログを更新できるようになります。