あと味

たくさん情報を食べて、たくさん発信すると、あとになって味わい深い。

Movable TypeのextlibディレクトリのCPANモジュールカタログ

Movable Type Advent Calender 2012の5日目です。

Movable Typeのプラグイン開発は、ダイナミック・パブリッシング対応のためにPHPを書くのを除いて、主にPerlのプログラムを書くことになります。

Perlのプログラムは、標準のモジュールだけで開発できることは少なく、様々なCPANモジュールを組み合わせて書いていくことが多いです。

プラグインの開発をする際、プラグインにCPANモジュールを同梱することもできますが、すでに同機能を実現できるモジュールが標準で用意されているのであれば、そちらをまずは使った方が、依存モジュール等でややこしくなくて済むので、まず、MT_HOME/extlibディレクトリの中にあるモジュールをいろいろと調べることがあります。

この機会に自分の備忘録も兼ねて、デフォルトのextlibディレクトリにある、CPANモジュールのカタログを作ってみました。

調査したバージョン

Movable Type 5.2(MTOS)

モジュールカタログ(アルファベット順)

以下、モジュールをアルファベット順に並べています。MT本体で利用されていない単なる依存モジュールかつ、個人的に使わなさそうなものは独断と偏見で省く可能性があります。ご了承下さい。

A

Algorithm::Diff
2つのファイル、リストの差違を求める関数を含んだモジュール。

MT本体では利用されていませんが、HTML::Diffの依存モジュールです。他に使えることもありそう。

Apache::*
mod_perl絡み。

MT5以降では、mod_perlをサポートしていないようなので、今後使わないのかもしれない。プラグイン開発には必要ないのかな。

Archive::Extract
圧縮ファイルの展開をする時に使うモジュール。

MT本体では使われていないようですが、Archive::ZipやArchive::ExtractのPODを見ると、解凍だけなら、こちらを使った方がメモリ消費量を節約できるっぽいです。(unzip等のコマンドが利用できる前提)

Attribute::Params::Validate
Params::Validateを属性を使って利用するモジュール。

特に使われているところは無さそうだけど。

AutoLoader.pm
AUTOLOADで呼ばれるメソッドをファイルに書きだしておけるモジュール。

Image::Sizeで使われてる。

C

CGI::*
言わずと知れたモジュールですね。

MT::Appで使われています。直接使うことは無さそう。

Cache::*
キャッシュのインターフェイス。

Data::ObjectDriverのサンプル・コードに出てくる程度。標準のextlibには入っていない、推奨モジュールのCache::Fileとか、Cache::Memcachedの方が有用そう。

Class::Accessor::*
アクセサの定義を簡単にするためのモジュール。

MT内でも使われているし、クラス作る時に有用。

Class::Data::Inheritable
アクセサの定義を簡単にするためのモジュール。Class::Accessorとの違いは、インスタンス変数へのアクセサか、クラス変数へのアクセサかです。

Data::ObjectDriver::Driver::BaseCacheでは、両方をClass::Accessor::FastとClass::Data::Inheritableとを使い分けています。

Class::Inspector
クラスについていろいろ検査するモジュール。

SOAP::Liteの依存モジュールのようです。とあるクラスをロード済みかどうか調べるのに使ってました。

Class::ErrorHandler
クラスのエラーメソッドを簡単に定義するためのモジュール。

URL::Fetchの依存モジュールのようです。

Class::Trigger
クラスにトリガーを設定するためのモジュール。

MTのフック・コールバックはこの仕組で実装してるっぽい。

Crypt::DH
DH法のためのモジュール。

Net::OpenID::Association等の依存モジュール。鍵作るのに必要みたい。

D

Data::ObjectDriver::*

ORマッパー。

MTで独自オブジェクト作る時は間接的にお世話になる。

F

File::Copy::Recursive

再帰的にファイルのコピーや移動をするためのモジュール。

MTでは、MT::CMS::Themeでエクスポートする時に使われている。

File::Listing

ファイルやディレクトリの一覧を出したい時などに使うモジュール。

LWP::Protocol::FTPで、ファイルの一覧をHTMLで返す時にファイル一覧ページを作るために使われている。

File::Tmp

TempファイルやTempディレクトリを作りたい時に使うモジュール。

MTでは、ファイルのアップロードで重複したファイル名の場合、上書きする時などに使われる。

H

HTML::Diff

二つのHTMLのdiffを取るモジュール。

MTでは、MT::Revisableで使われてますね。リビジョンの機能を使う時にお世話になってるってことです。

HTML::Form
HTMLのform要素をオブジェクトとしてパースするモジュール。

どこでも使われていなっぽいけど、LWP::UserAgentなんかと組み合わせて使うみたい。

HTML::Template
HTMLのテンプレートエンジン。

かつてのバージョンでは、MTの管理画面はHTML::Templateで書かれていたようで、その名残りだと思われます。MT::Builderには、HTML::Template形式のテンプレートをMTタグに変換するコードが入ってました。

H

HTTP::*
HTTPプロトコル周りのインターフェイス。

依存モジュールが大半で、MTでは、HTTP::RequestとHTTP::Response、HTTP::Dateあたりが実際に使われています。

Heap::Fibonacci
フィボナッチヒープを取り扱うモジュール。

MT内では使われていなくて、Cache::Memoryの依存モジュール。

フィボナッチヒープ自体、何が良いのか一度作ってみないと理解不能な感じなので、よくわかりません。

I

I18N::LangTags::*
RFC3066形式の言語タグを取り扱う関数をエクスポートするモジュール。

Locale::Maketextの依存モジュールで、MT::L10Nでも使われてます。言語タグから言語名を取得するのに使ってるだけかな。

IO::Scalar
スカラ変数をファイルハンドルっぽく扱うためのモジュール。

MTでも依存モジュールでも使ってなさそう。

IO::WrapTie
IO::Handleインターフェイスでtieされたオブジェクトを扱うためのモジュール。

IO:Scalarの依存モジュール。

IPC::Cmd
外部コマンドをPerlから簡単に実行するためのモジュール。

MTでは直接利用していない。Archive::Extractの依存モジュール。tarコマンドやらzipコマンドやらを使う時に利用されている。

Image::Size
画像のサイズを取得するためのモジュール。

MT内でも、MT::Imageや、MT::Asset::Image等、画像サイズの取得が必要な場面で利用されている。

J

JSON::*
PerlでJSONを取り扱うためのモジュール。

MT内でもJSONを取り扱う箇所でいろいろ使われています。

L

LWP::*
PerlのWWWクライアントツール群。

MTでは、主に、LWP::UserAgentが外部サイトへのアクセス等で背面化でいろいろ働いてます。MT->new_uaで、MT用にカスタマイズされたUserAgentが作れるようになっています。

Locale::Maketext
ローカライゼーションのためのフレームワーク

MTのローカライゼーションの基盤です。プラグイン開発で使う、translate関数の元です。

Lucene::QueryParser
全文検索ソフトLuceneののクエリパーサ。

MTでは、MT::App::Search等で使っていて、検索クエリの解析に使ってるみたい。

M

MIME::Charset
MIMEのためのCharset情報を扱うモジュール。

MTでは直接使っていなくて、MIME::EncWordsの依存モジュール。

MIME::EncWords
RFC2047形式でエンコードされた文字を扱うためのモジュール。

MT::Mailでメールのヘッダをエンコードするのに使われている。

Math::BigInt
BigIntを扱うためのモジュール。

MT::Utilのdsa_verifyで、Crypt::DSAがない時に、これを使ってなんとかしている。

Module::Load
モジュールローダー。

Module::Load::Conditonalの依存モジュール。

Module::Load::Conditional
モジュールの情報によってロードするモジュールローダー。

MT内では使われていませんが、Archive::ExtractやIPC::Cmdの依存モジュールで、can_loadメソッドが使われています。

N

Net::HTTP
HTTPクライアント。

MT内では使われていません。LWP::Protocol::httpやNet::HTTPSの依存モジュール。

Net::HTTPS
HTTPSクライアント。

Net::HTTPと同じく、LWP::Protocol::httpsの依存モジュール。

Net::OAuth
PerlでOAuthを扱うためのモジュール。

もしかしたらコマーシャルパックでは利用するのかもしれませんが、MTOSでは利用してなさそう。

Net::OpenID::*
PerlOpenIDを扱うためのモジュール。

MTでは、MT::Auth::OpenIDで使われています。コメント投稿時にOpenID使う時とか。

P

Parms::Check
関数の引数をチェックするモジュール。

MT内では使われていません。Archive::Extractや、Module::Load::Conditional等で引数チェックに使われています。

Params::Validate
関数の引数をバリデートするためのモジュール。

MT内でも、何かの依存モジュールでもなさそう。

S

SOAP::*
SOAP関連のモジュール群。

MTでは、MT::XMLRPCServer等で使われている。

T

TheSchwartz::*
ジョブキューシステムTheSchwartz関連モジュール。

SixApart製ということもあり、MTのジョブキューシステムはこれで管理されている。

U

UDDI::Lite
UDDIクライアント。

MT内で使われてなさそう。

UNIVERSAL::require
モジュールローダーのひとつ。

Net::OAuthで使われている。

URI::*
URIPerlのインターフェイス。

MT内では、MT::App::Wizard、MT::AtomServer等、URIを分解する時等に利用されている。

W

WWW::RobotRules

MT内では直接使われてません。LWP::RobotUAの依存モジュール。

X

XML::Atom
ATOMのインターフェイス。

MTでも、MT::AtomやMT::AtomServer等、ATOM関連で使われている。

XMl::Elemental
XMLPerlオブジェクトにパースするモジュール。

XMl::Parser::Style::Elementalの依存モジュール。1

XML::Parser::Lite
正規表現ベースのXMLパーサ。

特に使われていない。

XML::NamespaceSupport
XMLのnamespaceのインターフェイス。

XML::SAXやXML::Simpleの依存モジュール。

XML::SAX
SAXパーサ。

MT::Utilで使われていて、MT::BackupRestoreに必要なモジュールになるので、ブログのバックアップと復元機能が使えなくなる。

XML::Simple
簡単に使えるXMLインターフェイス。

MT内では直接使われてないけど、XML扱う時には使えそう。

XML::XPath
XPathに基づくXMLパーサ。

MT内では、MT::AtomServerとMT::Auth::OpenIDで使われている。

XMLRPC::Lite
XMLRPCのPerl実装。

MT内では直接使われていませんが、XMLRPC::Transport::*の依存モジュール。

XMLRPC::Transport::*
XMLRPC::Liteの様々なプロトコルの実装。

mt-xmlrpc.cgiで、XMLRPC::Transport::HTTPが使われている。

Y

YAML::Tiny

YAMLファイルを読んだり書いたりするモジュール。

MTでは、MT::Util::YAML::Tinyという名で再定義されている。

V

version::*

バージョンオブジェクトを扱うためのモジュール。

まとめ

思ったより、必要最小限のモジュールしか使ってないなという印象がありました。やはりいろんな環境で動かそうと思うと、依存多すぎてもいけないってのがあるのかもしれませんね。extlib配下のモジュールのものでも、Perlのバージョンによっては標準モジュールになっているものもたくさんあります。

toolsの中に突如Web::Scraper依存のコードがあったり、コード書く人によって、違うのかもしれませんが。

どこで使われているかよくわからないものもありましたが、今回調べたバージョンで使われていなかったり、MTOSでは使われていないものもあったのかもしれません。

Tips

特定のモジュールが特定のPerlのバージョンの標準モジュールかどうかを調べるには、Module::CoreListが便利です。corelistというコマンドがインストールされるので、それを使えば標準モジュールを調べられます。

$ cpanm install Module::Corelist
$ corelist --help
$ corelist -a Module::Load

また、依存モジュールも含めてローカル領域にCPANモジュールをインストールするには、cpanmコマンドの方が楽でしょう。XS依存の部分はサーバーに単純に上げても使えませんが、*::PPとか書いてあるモジュール探すとか、metacpanでpure perlと検索して探して解決するとかで対処する感じですね。

$ cpanm -h
$ cpanm -L ./extlib Plack

cpanmのインストール等、Perlの環境構築については、あと味の[Perlの環境構築 - あと味などを参考にしていただければと思います。

最後に

来年はMovable Typeに本気で取り組みます。

MovableTypeのモジュールのPODのViewerプラグイン作った

MovableTypeを触っていると、MTのモジュールのPODを見る機会が多くなります。MTタグの使い方とかも該当モジュールのPOD見れば解決することもあるので、とりあえずアイデアレベルですが、昨日作ってみたのでエントリー起こしました。

MTPodViewerという名前を付けました。

20121004112532

デモサイト

MTPodViewer

インストール

リポジトリにあるplugins/MTPodViewerをサイトのpluginsにコピーします。加えて、リポジトリにあるmt-static/plugins/MTPodViewermt-static/pluginsにコピーします。

依存モジュールはextlibに同梱したつもりですが、動かなかったらごめんなさい。cpanコマンドかcpanmコマンドでインストールしてください。依存モジュールは、plugins/MTPodViewer/Makefile.PLに書いてあります。

プラグイン設定

システムのプラグインに進むと1箇所だけ設定があります。

ログイン必須にするかしないかの選択です。Yesならログイン必須、Noならログイン不要です。

検索方法

たとえば、MTのディレクトリで、perldocする場合、以下のような感じになると思います。

$ perldoc lib/MT/App.pm

MTPodViewerでは、以下の様なキーワードで検索することになります。

app

MT::Template::Tags::Entryを検索したい場合は、

template-tags-entry

と検索します。

MTというプレフィクスは省略して、「/」や「::」の区切り文字を「-」にして、全部小文字にしているということです。

bootstrapのtypeaheadがある程度面倒見てくれるので、これで充分な気がしてます。

感想

最初はCSSとか自分で書いてたんですけど、途中からbootstrapに変更しました。bootstrap-typeaheadのスタイル作るの面倒だったので...。というか基本的にbootstrapは何かと楽でマジ助かります。

見出しのフォントはHelvetica、本文のフォントはGoogle Web Fontsにある、OpenSansにしました。すごく読みやすいですね、このフォント。

速度的にはちょっと微妙なので、モジュール一覧をキャッシュしておくなりした方がいいと思いますが、また気が向いたら対応します。

リンクの部分とかは、Pod::Simple::XHTMLの吐き出すソースをちょっとカスタマイズしたらうまくできるのかもしれませんが、ページ内リンクと別モジュールへのリンクがうまく場合分けできなさそうなので、リンクをすべて外すって対応を取っています。

MTアプリケーションはMTをWAFと思えば、普通に使えますね。クライアントワークだったら、依存モジュールの解決もそんなに面倒じゃないですし、最近は、MTアプリケーション作る機会もあって、いろんなCPANモジュールと組み合わせて使ってます。

あと、英語のドキュメント書けない。深刻。

MovableTypeのプラグインを書いてみた

必要に迫られて、今までぼんやりとしか把握していなかったMovableTypeを触りはじめました。

Flickrの写真をサイトの中に埋め込みたかったんですが、せっかくなのでスクラッチでプラグインを書いてみようということで、「Flickr photos List」というプラグインを作ってみました。

※MTOS 5.02を使ってます。

MovableType(MT)のプラグインの練習

MovableTypeのプラグインは、MTタグを自作するもんだというあやふやな理解でいて、過去に買った以下の書籍を参考にコードを書いてみました。(最新バージョンじゃないのでご注意)

Movable Type プロフェッショナル・スタイル MT4.1対応 (Style for professional)

Movable Type プロフェッショナル・スタイル MT4.1対応 (Style for professional)

cheebowさんこと、関根さんの「プラグイン開発と応用」の章でまさに、プラグインの開発方法が載っていたので、ここを見ながらサンプル通りの簡単なMTテンプレートを作りました。

本番

今回作るFlickrの写真をサイトに埋め込むプラグインに似たようなのを、Plugin Directoryを使って探してみると、FlickrPhotosというプラグインがあり、詳細を見てみると、Requirementsという項目に、Flickr::APIが必要とあります。

サードパーティのモジュールってどうやって使うの?

サードパーティのモジュールをMTで使う方法がわからなかったので調べてみると、mt/extlibというディレクトリにサードパーティCPANモジュールをインストールすれば使えるということがわかりました。

よくよく見ると、mt/extlibの中には、よく使うCPANモジュールがたくさんあって、今回作りたいプラグインは、元々入っているLWP::SimpleとXML::Simpleで十分と判断しました。

実際作ってみて

書籍やWebを見ると作り方がいろいろあって混乱してきました。

書籍では、テンプレートタグの定義をinit_registryというサブルーチンで定義しているし、元々入っているMultiBlogやTypePadAntiSpamでは、MT::Pluginコンストラクタのregistryというプロパティで定義しているし、SixApartの技術情報提供ブログでは、MT::Template::Contextのaddtagメソッドで定義してるし。

これが俗に言うTMTOWTDIってやつかorz...

最終的に、MovableType.orgのチュートリアルにある、YAMLで設定を記述する方法に行き着きました。

Movabletype.orgのドキュメント

Movabletype.orgには、Movabletype.jpでは見つからなかったDeveloper's Guideがあり、非常に丁寧なチュートリアルがあります。

このチュートリアルは、Makefiile.PLを作ったり、PODを書いたりなど、Plugin Directoryへの登録まで指南してくれます。新参者はここのドキュメント見るのが良いのかなと思ったりしました。

作ったプラグイン

管理画面のテンプレートの作り方は書籍を参考に、後はDeveloper's Guideを参考にして、簡単なFlickrのプラグインができました。

taiju/MT-Flickr-photos-list · GitHub

使い方
  • 展開したフォルダの中にある/plugins/FlickrPhotosList/を/mt/plugins/の中にコピーもしくは移動。
  • プラグイン(システム)の設定で各種項目を入力。

f:id:jdg:20100722160700p:image

  • テンプレートに<$MTFlickrPL$>を埋める。(ulかolで写真リストが表示されます)

モディファイアを指定して、そのテンプレート上でプラグインの設定を上書きできます。

<$MTFlickrPL user_id=".....@N.." per_page="20" extras="url_t" list_type="ol"$>

まとめ

自分を含めて、今からプラグイン開発に取り組もうとする始める新参者*1にとって、どこを見れば作れるのかが提示されていないような気がするので、Movable.jpにもデベロッパー向けのガイドが欲しいなと思いました。

TMTOWTDIはいいんですけど、すべての作り方を網羅的に載せて、開発者がどの実装方法を使うか選べるようなドキュメントも欲しいなと思います。

個人的には、Movabletype.orgのドキュメントが一番詳しくてわかりやすかったです。

mt/extlibの中には、Perlでよく使うモジュールがいくつもあるので、モジュールの追加インストールをしない状態でも、いろいろ遊べそうな気配があります。ディレクトリの中を覗いてみて、「おぉ、いいじゃん。」となりました。

なにはともあれ、Perlの勉強にもなりそうだし、MTのプラグインの開発は楽しいかもと思った次第であります。

*1:俺が時代遅れなの?世の中はWordpressなの?