MODx Revolutionのコンセプトと概念の整理

プログラム(機能)関連の開発の話題
neran
メンバー
メンバー
記事: 22
登録日時: 2009年10月23日(金) 00:47

MODx Revolutionのコンセプトと概念の整理

投稿記事by neran » 2009年10月26日(月) 19:23

MODx Revolution の日本語対応に参加しようとしている者です。
まだ公開前であり、なかなかRevoについてまとまった情報が無いため、こちらをお借りして、ざっとまとめたいと思います。

まず、過去の情報やbetaを見て、私が把握できているものを掲示いたします。
かなり思い込みで書いている可能性が高く、疑問も混ざっているので、誤りや過不足を指摘していただけると嬉しいです。特にコンセプトは触れ込みを鵜呑みにしているので、実態とのズレがひどいかも知れません。
なお、なるべく訳語を既定しないように、機能の名称などはRevo本来の英語表記のままにしています。



コンセプト
Revoは、これまでの一般的なCMSと違い、CMSを構築するためのフレームワークとなる。
ユーザーは管理したいコンテンツに合わせたシステムを、Revoの上に構築する。例えば飲食店を紹介する場合と、書評を行う場合では、コンテンツの形成に必要とする情報が違う。Evoを含む既存のCMSでは、情報の構成に一定の強い拘束があり、それを外れた情報は取り扱いが難しい。一方Revoは、取り扱いたい情報を定義し、そのインターフェースを定義する事で、飲食店向けCMSにも、書評用CMSにもなりうる(Google Spreadsheetsに於ける、Form機能の様な層をRevoが担う?)。

まっさらなRevoは柔軟な足場であり、取り扱う情報に明確な方向性を持たないが、コンテンツの管理に必要な一通りの機能を持つ。
コンテンツとして配信される単位となる、Resource。Resourceを形成する、FieldやTemplate Variableとそのインターフェース。動的で柔軟な管理を助けるChunkやSnipet、Plugin。UserとUser group、Roleを用いたアクセスコントロール。Lexiconではシステム上の語彙の管理を可能にする。他にも、イベントのロギングや、入力候補の一括管理、静的なファイルの取り込み、コンテンツタイプの管理、管理操作そのもの追加や削除などがある。
Revoでは用意されたこれらの機能を、取捨選択し、組み合わせ、調整する事で、目的に合致したCMSを構築する。

疑問点・不明点
実際にどのレベルまで細かなカスタマイズが可能か。承認フロー的な細かい操作権限の分割、必要な入力項目がコンパクトにまとまった記事編集ページなど、Evoで難しかった事が、実用に充分な品質でバッドノウハウ無しに実現可能か。


構成要素

Resource :
公開されるコンテンツの基本的な単位。
各Resourceの単位で、公開/非公開の調整や、複製、削除などを行う。

Resource / Document :
もっとも一般的なコンテンツ。
タイトルや自由記述の中身を持ち、通常はWebページとして表現される。

Resource / Weblink :
把握できていません。
単なるリンク…なんでしょうか? リンク集などであれば、リンクがResourceというのも判るような。

Resource / Symlink :
把握できていません。
Weblinkとの違いもわかっていません。シンボリックリンク的な何か?

Resource / Static Resource :
ファイルベースの静的なResource。
画像等をResourceとして管理可能する。


Element :
コンテンツの生成を助けたり、複雑な管理を可能にする、追加要素。

Element / Template :
Resourceの雛形。
いわゆるテンプレートとしての機能があり、複数のResourceを構造化する。

Element / Template Valiable :
情報の雛形。
名称と型を定義し、Templateと紐付ける事で、Resourceに共通の追加情報を与える。
紐付けは多対多で行えるため、基本セットの使いまわしが楽。

Element / Chunk :
文字列として評価される。
局所的なテンプレートとして用いたり、Snipetのテンプレートとして用いる。

Element / Snipet :
PHPのコードとして評価される。
生のPHPコードが書けるため、文字列の組み立てから分岐、繰り返しなど、PHPに出来る事が何でも出来る(die()も可)。
動的なメニューの生成や、Resourceとしての入力値に基づくデコレーションなど、非常に多くの処理が可能。

Element / Plugin :
MODxのイベントモデルに連動可能なPHPコード。
管理機能の拡張や、大幅な機能追加などに用いる。

Element / Category :
ResourceやElementなど、MODxの管理対象を分類するラベル。


その他 :

Contexts :
把握できていません。
デフォルトが「mgr」と「web」という事は、システム全体のスイッチング用?
「web_auth」だとこの処理云々、といった書き方が可能か?
Namespaceとの違いは?

Lexicon :
語彙セット。
管理画面に表示される要素の名称や、解説の文章を管理する。
単なる翻訳にとどまらず、目的に応じたカスタマイズが可能。
Field Labelとの絡みは??

Action :
把握できていません。
管理画面でメニューから実行可能な項目?
それとも、もっと広い意味での処理セット?

Package :
SnipetやPluginなどをまとめたセット。
この単位で、バージョン管理や導入が容易になる?
中身の競合の解決は?

Namespace :
把握できていません。
何に対する名前空間なのか?
Snipet等のコードに対してだとPHPの領分であって、
MODxで管理すべきじゃないだろうし。

Form Customization :
管理画面の様々なフォームをカスタマイズする。
ManagerManagerのRevo実装?
まだうまく動かせていません。longtitleすら消えてくれない。

Property Sets :
TemplateにあるPropertyの雛形。
…だけれども、どう生かすのかが判らない。
Template側にPropertyを用意しても、Resourceの生成時には使わない?
Form Customizationでの指定が必要?




取り敢えず、ざっと見回して目に付いたものだけですが、指摘いただければ追加・修正し、RevoのGoogle CodeのWikiにまとめようと思います。
Revoの実際に詳しい方、どうかよろしくお願いいたします。
アバター
enogu
メンバー
メンバー
記事: 32
登録日時: 2009年9月02日(水) 23:56

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by enogu » 2009年10月26日(月) 23:16

neranさんはじめまして。私も最近Revoをさわっている身です。
イントラネット向けにチューニングしようと、管理機能サイドをいくらか弄った結果をご報告します。

Contextsは個人的には一つのマネージャで複数のサイトを管理する枠組みと考えています。What's New in Revolution 2.0(http://svn.modxcms.com/docs/display/revolution/What's+New+in+Revolution+2.0)でのContextsのくだりにこんなことが書いてありましたので。
Contexts - this allows developers to assign different views of your site based on pretty much any criteria. This means native multi-sites, subdomains, running the core outside of webroot

mgrとwebはそれぞれ管理画面とデフォルトのWebサイトの棲み分けでしょう。内部的にはアクセス管理リストなどがコンテキストと対応づけられているようです。

それとNamespaceはbeta3位からContextsと分かれて定義されました。Namespaceはコンポーネント(拡張機能全般を指している模様)、およびLexiconのグループ化に使います。(トピックのフルネームがNamespace:Topicになり、この下に辞書エントリを書き込む形になります)
スニペットやプラグインの中にはライブラリコードを別途持つ物が以前から存在しましたが、Namespaceはこれらのライブラリコードの収納位置を指すためにも使用されます。具体的に言うとDocManagerとかWayFinderはそれぞれ独自のNamespaceを作成します(パッケージの競合の解決もこの仕組みで回避しようといったところでは?)。

Actionは主にメニューの受付を担当するオブジェクトです(従って使用されるのは主に管理画面からだと予想しています)。ActionはNamespaceに関連づけられており、実質的に対応するコンポーネントのコントローラー名と同一です。闇雲にコンポーネントディレクトリをスキャンする代わりにデータベース上でコントローラーの位置を把握しておこうと言うことでしょう。

Menuが具体的にActionを呼び出すためのオブジェクトです。これはActionを呼び出すリンクに変換されて実際に管理画面に表示されます。Menuからはhttp://yoursite.com/manager/index.php?a=50&... みたいなリンクが生成されますが、このa=50の部分がアクションのID,続くクエリパラメーターがコントローラーに渡される追加パラメータに相当します。この組み合わせはCommandパターン(GoF '94)に当たるのではないかと思います。

この辺の挙動は個人で翻訳中です。サイト名で遊びすぎたので引っ越すかも知れませんが。
http://sites.google.com/site/msdnunofficial/

Property SetとForm Customizationは私も扱いかねています。何か分かったら教えて頂けるとありがたいです。

追伸:WebLinkはEvo時代からある機能です。ご想像の通りWayfinderなどと組み合わせると若干面倒(ただしメンテは楽)にリンク集が作れたりしますね。
アバター
yama
管理人
記事: 2830
登録日時: 2009年7月29日(水) 02:50

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by yama » 2009年10月27日(火) 00:05

実際に試して(試せて)ないので想像ですが。ウェブリンク・シムリンク・スタティックリソースの3つは似てて、ウェブリンクはリダイレクト。シムリンクはリダイレクトせずに対象コンテンツを出力(phpのreadfile関数みたいな感じ?)、スタティックリソースは実際のファイルの中身もURLも・・というか、そのまんまという感じでは。という気がします。
neran
メンバー
メンバー
記事: 22
登録日時: 2009年10月23日(金) 00:47

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by neran » 2009年10月27日(火) 03:05

enoguさん、はじめまして。
こんなに面白そうなソフトウェアですが、実務に使わないと中々頭に入らないので、替わりに日本語対応をお手伝いする事にしてみました。
enoguさんのドキュメント翻訳、参考になりそうで、見過ごしていた日本語のリソース嬉しいです。

Context :
なるほど複数サイトですか。想像していませんでした。単一のMODx上で、サブドメイン等で分かれた自社サイトなど、一括して扱った方が良いシーンは、確かにありそうです。ACL関連が切り分けられるという事であれば、部署ごとに「product」と「support」を分けたり、という使い方が想定されているのでしょうか。

Namespace :
Contextのフォークという事は、コンテンツやACLとは別の軸で、拡張機能やLexiconといった、管理の機能側を仕切るという事、かな。Namespaceで機能を区切り、Contextでコンテンツを区切る、ぐらいにスッキリしてると分かりやすいんですが…。Package競合のクッションにもなっていると、そう単純でもないでしょうか。
この辺りの用語は特に念入りに整理しておかないと、言語をまたいでいる分、ユーザーが大きく混乱しそうです。

Action :
コンポーネントのコントローラーをActionとして定義したものが、各メニュー項目のハンドラとなるんでしょうか。GoF本ほとんど読んでいないのでこういう時悲しいですが、MenuオブジェクトがCommandオブジェクトに相当するActionを生成という流れ、かな? とすると、Actionとして登録する各コンポーネントはMenuの実装に合わせる必要がある??

Property SetとForm Customization :
どうにもすんなり動いてくれません。
ユーザー切り替えたりと試してみましたが、いじっている途中でDBが壊れたりしています。ここが一番シンプルな魅力になる筈なので、なんとか早く試す手順を固めたいです。

Weblink :
すみません、Evoの頃からすっぱり無視していました。
本来扱いたいコンテンツと、単なるリンクの粒度の差が気に食わなかったのだと思います。
ただどこかで見かけたように、別の仕組みで構築されたサイトやフォームへのリンクや、リンク先のパスにだけ変更のありそうなケースでは光るかも知れません。
内部のコンテンツではないハイパーリンクもコンテンツの一つとして捉えれば、Web的で分かり良いでしょうか。




yamaさん

Document以外のResourceの種類、ヘッダー見て確認してみます。
Weblinkがいちいちリダイレクトだと、ちょと嫌だなあ。コンテンツの一種としてのリンクなら、実装上仕方ないのかもしれませんが。

前のトピックで示唆いただいた、mb関数の扱いも気になっています。
最近PHPから遠ざかっていて、ほとんどZend Frameworkぐらいしか触っていないんですが、標準のstr系関数は、マルチバイトを考慮していないでしたでしょうか。だとすると、Revoではmb関数は僅かしか使われていないため、相当な置き換えが必要になるのかも知れません。
Evoの時には、どの程度、どういうコンセプトでmb関数の導入を行ったのか、経緯の分かるフォーラムでのやり取りなどありましたら、アドレスだけでも提示いただけると幸いです。
アバター
yama
管理人
記事: 2830
登録日時: 2009年7月29日(水) 02:50

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by yama » 2009年10月27日(火) 08:06

neran さんが書きました:前のトピックで示唆いただいた、mb関数の扱いも気になっています。
最近PHPから遠ざかっていて、ほとんどZend Frameworkぐらいしか触っていないんですが、標準のstr系関数は、マルチバイトを考慮していないでしたでしょうか。だとすると、Revoではmb関数は僅かしか使われていないため、相当な置き換えが必要になるのかも知れません。
Evoの時には、どの程度、どういうコンセプトでmb関数の導入を行ったのか、経緯の分かるフォーラムでのやり取りなどありましたら、アドレスだけでも提示いただけると幸いです。

Evoではとりあえず不具合が確認された箇所だけ対応していて、あまり数はないです。

Dittoのサマリエクステンダー(summary.extender.inc.php)
コア内蔵のmodxmailerクラス(日本語版のみ)
ajaxSearchクラス
TinyMCEのlinklist

コード: 全て選択

$mbStrlen = $this->cfg['mbstring'] ? 'mb_strlen' : 'strlen';

こんなふうにやってたり

コード: 全て選択

if(function_exists('mb_convert_encoding'))

こんなふうにやってたりで。アプローチが統一されてません。日本語版では決め打ちでストレートにmb_書いてますが。

Evoではシステムで利用する基礎関数(API)をdocumentParserに集約しているので、ここにstr系関数をラップする関数を追加していって、今後はそれを使いましょう。というアプローチがすっきりしてよいのではと思ってます。
たぶんRevoはすでにそういう枠組みがあるんじゃないかな?と。

strftime関数も同じようなアプローチが必要だと思います。サーバによっては、たとえば%Y年%m月と書くと「2009年%m月」というふうに、一部が展開されずに出力されたり化けたりすることがよくあると思います。date関数でできるようなゼロサプレスな出力(05月→5月)も必要でしょうし。などです。
アバター
enogu
メンバー
メンバー
記事: 32
登録日時: 2009年9月02日(水) 23:56

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by enogu » 2009年10月27日(火) 12:47

名前空間からアクションにかけての設計は解りやすさより柔軟性重視といった感じで、内容的にもかなり盛りだくさんな印象です。コンポーネント関連の話を含めてまとめ直してみました。

基本構造
まず、アクションの前提条件となるコンポーネントの基本構造からお話しします。アクションを追加するシナリオとして一番あり得るのが管理画面の追加だと思うので、DocManagerを例に取ります。まずPackage ManagementでDocManagerをインストールして下さい。
DocManagerをインストールすると、関連ファイルは/core/components/docmanagerに保存されます。以後の内容は基本的にコンポーネントディレクトリ下の話とお考え下さい。docmanager名前空間のpath値もここを指します。そしてLexiconにもdocmanager名前空間とdefaultトピックが追加されます。
modelディレクトリには主にクラスのコードが入ります。内部にもう一層モデル名のディレクトリが有るのですが、これはxPDOの仕様ではないかと思われます。(コアのmodelディレクトリにもmodxディレクトリがあり、実際のコードはそこに入っています)
processorsディレクトリには処理のコードが入ります。設計方法にもよりますが、本家ではinclude一発で処理が完了するような文字通りのスクリプトが入る形を想定しているようです。プロセッサスクリプトは後述のコネクタと大きく関係します。
templatesはsmartyテンプレートの保存用、lexiconは辞書データの保存用です。controllersには管理画面の出力コードが入っていますが、名前とは裏腹に現在はコントローラーとしては使われていません。コントローラーについてはアクションと併せて説明します。

アクション
docmanagerには最初からindexアクションが登録されています(たぶん)。docmanagerは単一画面で、コントローラーもコンポーネントディレクトリのトップにあるindex.phpだけです。controllersディレクトリは今のところコントローラー置き場としては機能していません(何故かコア側でこのディレクトリをわざわざ回避する仕様になっています)。結局トップのindex.phpからcontrollers/index.phpを呼び出している当り、この辺の仕様はかなり流動的と見ています。

アクションの内容ですが、SystemメニューのActionsを開き、Actionsペインのdocmanager名前空間からindexを右クリックしてみて下さい。コンテキスト・メニューから"Update Action"を選んぶとアクションの編集画面が出ます。

アクションの追加フォームに入力する内容は以下の通りです。
コントローラ: この項目には参照するコントローラーファイルの名前を指定する必要があります。拡張子(.php)を付ける必要はありません。今回は名前空間のトップに配置されているindex.phpを参照するだけなので、"index"だけ入力すればOKです。
名前空間: ここには新しいアクションを所属させる名前空間を指定します。docmanagerのコンテキスト・メニューから開いた場合、デフォルトで入っています。
親コントローラ: この項目はアクションをツリー型に並べるために使えます。今回は空欄です。
ロードヘッダー: このチェックをオンにすると、MODxはマネージャのヘッダーとフッターファイルを読み込みます。このチェックはONにしておいて下さい。
トピックス: ロード時に適用する辞書のトピックスをコンマ区切りで指定します。今回はdocmanager:defaultです。
アセット: 今のところ使えないそうです。空欄です。

メニュー
メニューはアクションを知っている必要がありますが、依存しているわけではありません。呼び出し先のアクション(≒コントローラー)は事由に指定できます。極端な話、Forumsメニューを日本語フォーラムに差し替えたり、Actionsボタンでインポート画面を呼び出したりすることさえ可能です。
アクションもメニューも内部的にはmodActionとmodMenuという二つのクラスで実装された設定格納用のオブジェクトで、両方とも拡張して使うような性質の物ではありません。ちなみに、インストール先のメニューを拡張するためにメニューやアクションのエンティティもパッケージファイルに保存できるそうです。

Docmanagerのメニューはたぶんインストールされていません。新しいメニューを配置したい場所、例えばComponentsメニューを右クリックすると、コンテキスト・メニューに"Place Action Here"という項目があります。これをクリックするとメニューの追加フォームが表示されます。

入力項目は以下の通りです。
テキスト: メニューの表題に対応するLexiconのエントリキーを指定します。Actionsで指定したトピックの中から検索されるようです。今のところ見つからなかった時はこのパラメータがそのまま表示されるようです。
説明: メニューの説明に対応する辞書のエントリキーを指定します。挙動はテキストとだいたい一緒です。
アクション: メニューから起動するアクションを指定します。ドロップダウン形式で呼びだすアクションを選択します。今回は"docmanager - index"みたいな名前の物を選びます。
アイコン: このフィールドは今のRevoのテーマでは使用されていません。
パラメータ: このメニューが選択されたときにリクエストに追加するGETパラメータを必要に応じて指定します。内容は決め打ちのようです。例えば複数の機能を持つアクションなどで重宝すると思います。今回は空欄です。
ハンドラ: "loadPage"アクション(MODExtの機能)を上書きするイベントハンドラを指定できます。ここも空欄です。

これでSaveを押すとメニューが保存されます。リロードして期待した場所にメニューが追加されているか確認してみて下さい。(恥ずかしながら私はこの操作を安定して再現させられるようになるのにえらい苦労したのですが…)

コネクタ
最後にコネクタについて説明します。これは主にWebAPIを実装するファイルで、ルートディレクトリ下の/connectors/に集中して配置するようになっています。/assets/同様、外部から/core/に直接アクセスする形を避けるためと思われます。
MODExtによるAjaxのリクエストもコネクタに送信されます。コネクタはセキュリティーチェック(とConfluenceに書いてありますが実際は良くてサニタイズくらいしかしていない感じです)を行い、適切なプロセッサを呼び出して処理を完了させます。実装の上では単体でモデルを呼び出して処理を完了させられるのですが、わざわざプロセッサを使用しているのはコントローラーと共通する動作をプロセッサに抜き出してコードの重複を防ごうという狙いがあるのでしょう。
アバター
enogu
メンバー
メンバー
記事: 32
登録日時: 2009年9月02日(水) 23:56

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by enogu » 2009年11月05日(木) 19:06

Symlinkの挙動を実験する機会があったので結果をば。

結論から言いますと、IDを指定してリソースの別名を提供するような機能のようです。名前やフレンドリーURLのエイリアスを上書できて、別ディレクトリに同一リソースを表示したりする程度には使えました。なお、現状では機能していませんが画面自体はテンプレートの指定ができるようになっていて、もしかしたら最終的に同一データに別テンプレートを適用できるようになるのではないかとちょっと期待しています。また、試した訳ではないので断言できませんが、たぶん現状でも追加のアクセスポリシーを提供するような使い方が出来るんじゃないかと思います。

ちなみに今のところSymlinkではURLは扱えないようで、絶対アドレス、相対アドレスともに503エラーになりました。外部サイトの内容を読み込むような使い方は想定していないようです。

余談:Symlinkのリンク先アドレスはcontentフィールドに入っています。

Confluenceにある原文は以下の通り。
Symlinks are similar to Weblinks in that they redirect to another Resource or URL; however, symlinks will persist the current URL.
(意訳)SymlinkはWeblinkとよく似た機能です。ただし、Weblinkが他のリソースへのリダイレクトを提供するのに対してSymlinkは自身のURLを維持します。
アバター
yama
管理人
記事: 2830
登録日時: 2009年7月29日(水) 02:50

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by yama » 2009年11月24日(火) 00:03

Revo派がまだまだ少ないのでageときます
アバター
enogu
メンバー
メンバー
記事: 32
登録日時: 2009年9月02日(水) 23:56

Re: MODx Revolutionのコンセプトと概念の整理

投稿記事by enogu » 2009年11月28日(土) 01:41

Property Setの資料を邦訳しました。
http://sites.google.com/site/msdnunoffi ... perty-sets

せっかくなので三行でまとめてみます。
プロパティ:スニペットおよびプラグインのパラメータ定義(デフォルト値もマネージャから見えました)
プロパティセット:定義済みプロパティの集合。スニペットの引数のデフォルト値を上書きしたりできる。
使い方:1.タグに埋め込む, 2:セットにしてタグに埋め込む3:セットにしてエレメント自体に割り当てる

詳しくはまた何か分かりしだいと言うことで。

追記(2009-12-11):

プロパティの詳細な仕様が解りました。modPropertySetオブジェクトというxPDO系のオブジェクトを使用しているものの、このオブジェクトはDBに直接格納されません。toArrayメソッドで配列に変換した上で、スニペットやプラグインのpropertyフィールドにシリアル化文字列として保存されています。スニペットには$scriptProperties配列として渡されるので、おそらくmodPropertySetオブジェクトにせず、そのまま配列として操作しているのでしょう。

上記の通り、デフォルトのプロパティセットはスニペットに直接登録され、スニペットからは配列として使用できます。これはスニペットコールのパラメータのデフォルト値をスクリプト改変なしで変更できるということを意味しています。Toolsメニューから編集できるプロパティセット(仮にカスタムプロパティセットと呼びます)はそれをさらに上書きするために使用されます。[[AnySnippet@PropertySet?property=`value`...]]という呼び出しにすることで、スニペットのデフォルトプロパティセットにカスタムプロパティセットを合成できるようです(試していませんが)。

“開発関連の話題” へ戻る