Showing posts with label MovableType. Show all posts
Showing posts with label MovableType. Show all posts

Jun 20, 2010

MT Hackathon

MTのHackathonに行ってきました。HackathonでもないとMovable Typeを触る機会がほとんどなくなっています。

私がやっていたのは、以下の作業。

  1. SyncAssetプラグインのMT5対応
  2. プラグインの副産物のライブラリを使って、指定ディレクトリの内容をMTのアセットライブラリに同期するコマンドラインツールの実現
  3. 2.で作ったツールとincrondを組み合わせて、WebDAV FSフォルダの中身を自動的にMTのアセットライブラリに同期する仕組みの実現

ソースコードの差分はこれくらいです。

May 8, 2010

Minifier Plugin 0.02

ときどきMinifier PluginでHTMLの圧縮はできないの? って聞いてくる人がいて、たいがい外国人なんだけど、その都度そんなの意味ないよって答えるのが面倒くさくなったので対応した。

Home - mt-plugin-Minifier - GitHub

GitHubの練習的な。

Apr 30, 2010

献本いただきました×2

遅くなってしまいましたが、Movable Type 5関係の図書を頂戴しました。

なになに? 「以前にMovable Typeのパワーユーザーであった小川氏」だって? 蒲生さんはパワーユーザーという言葉が好きなんですよね。

私のことは「Movable Typeの、不活性で怠惰なコミュニティディベロッパー」とか呼んでいただけると幸いです。長いですが。

どちらの本もソフトウェアのディプロイメントに相当ページを割いていますよね。InstaMTのような非標準的な環境まで説明する必要があるのか疑問です。

ここで提案。こんな解説書はどうですか?

まず、Amazon EC2上に(デザイナーからプラグイン開発者から)ヒューマンリソースを注ぎ込んできっちりしたサイトを作ります。4,5個あるとよいでしょう。「おーこれすげぇー、真似してぇー」と思わせることが重要です。そしてそのカスタムAMIを作っておきます(S3上に保存しておきます)。

本の第一章はいつものように適当にごまかすとして、第二章はAMIからEC2インスタンスを作って稼働させる方法を説明します。読者のクラウドサービスへのリテラシーも向上していい感じです。

第三章からは一章ずつ費やして各カスタムAMIの説明をします。このカスタムAMIはどういう目的・コンセプトのものであるかを説明し、次にそれがいかに技術的にあるいはデザイン的にクールなのかをホットに語ってください。最後にカスタムAMIを実現するのに使った技術的な、あるいはそれほど技術的でもない細々したことを説明しましょう。

あとは適当に終章を書きましょう。

かくしてクローンAMIが乱立することになります。幾人かのユーザはきっとこう思うでしょう「このサイトをこのように拡張したい、デザインを変えたい」と。それをうまく収穫するのが著者らのビジネスです。相手はAmazon EC2の課金くらいならものは試しと払ってくれるような人ですよ。

Feb 6, 2010

MT Hackathon

久しぶりにシックス・アパートのHackathonに参加しに赤坂に行ってきました。

もうMTのことをかなり忘れてしまっていたので、リハビリがてらMTとCalDAVの連携ツールをちまちま作りました。

プレゼン資料を置いておきます。

Jun 25, 2009

Melodyについて手短かに

Melody: Community Powered Publishing

一言で言えば、MelodyはMovable Type Open Source (MTOS) からブランチしたオープンソースCMSプロジェクトです。「MTOSはオープンソースなんだからコミュニティが自由に拡張すればいいじゃん、なんでブランチしたプロジェクトでやるの?」という疑問があるかもしれません。

MTOSの問題点は、MTと独立したリリースエンジニアリングがない (つまり、MTOSのリリースはMTと同期している) ことでした。したがって、コミュニティからのコントリビューションは、バグフィックスや機能追加を加速させる一方で、Six Apartが負担することになるQAのコストを押し上げることを意味していました。また、MTOSのロードマップを示すことはMTという製品の将来戦略を開示することと表裏一体であるため、コミュニティによる独自のオープンなロードマップの策定は不可能でした。

このことは、当初からのコミュニティ開発者共通のフラストレーションになっていて、MelodyのFounderの一人もかなり早い段階でこうした問題を指摘していたと記憶しています。私自身も修正や機能追加のためのパッチを相当数作りましたが、一部はすんなり受け入れられたものの、受け入れられないものに関しては、それが誰の判断によるものでなぜ受け入れられないのか明確なコメントが得られたことは滅多にありませんでした。というか、皆無だったと思います。

Melodyは、こうした制約なしにコミュニティ主導で(MTOSから派生した)CMSを作って行こうというプロジェクトになります。その「自由」の対価は、ロードマップの策定もリリースエンジニアリングもコード品質の維持もコミュニティの責任で行うこと、です。

この試みがうまく行くかどうかは誰も分かりません。MTOSと独立性の高いリリースが本当に可能かどうか分かりませんし、日本人のコミットが不十分なら国際化が不十分なリリースになる可能性もあります。MTOSへのアップデートをMelodyに取り込むのは比較的容易ですが、その逆を行うのは (原理的には透過に相互に利用できるはずですが) MT/MTOSのコードベースに新しいコードを加えることになるため必ずしも容易ではありません。

Melodyがうまく行くかどうかはさておき、私自身はMTOSではなく、Melodyにコミットすることになると思います。


追記: Six Apartの名誉のために付け加えておくと、Melodyというプロジェクトは、別にMTOSの枠組みで実現不可能だったことを実現しようとしているわけではありません。これまでだって、MTOSのブランチをSix Apartのリポジトリに置きつつ、Six Apartと独立のバグトラッキングシステムを用意し、独立のリリースすることは可能でした。単に以前は旗を振る人がいなかったが今はいるというだけです。

May 18, 2009

Bloggerへの移行を完了しました

Movable TypeからBloggerへの移行を開始して約三週間、ようやくすべてのエントリーを移行し終わりました。一日50件ずつですから、18,000件もあれば一年かかってしまう計算です。mt2bloggerの実用性は限定的ですね。

早いとこGoogleにインデックスしてもらうために、Google ウェブマスター ツールにサイトマップを登録してみました。

Bloggerでは、以下のようにフィードURLにパラメータを与えると、投稿日順に500件ずつAtomフィードを取り出すことができます。

  • http://hoge.blogspot.com/feeds/posts/default?orderby=published&max-results=500&redirect=false
  • http://hoge.blogspot.com/feeds/posts/default?orderby=published&max-results=500&start-index=501&redirect=false
  • http://hoge.blogspot.com/feeds/posts/default?orderby=published&max-results=500&start-index=1001&redirect=false
  • ...

なのでこれを必要なだけサイトマップとして登録してやれば、すべてのエントリをクロール対象として登録することができます。

Apr 28, 2009

Bloggerへの移行を開始しました

Bloggerへの移行を開始しました。旧URL (http://as-is.net/blog/) にアクセスするとこのブログにリダイレクトされるはずです。

「開始しましたって?」と疑問に思われるかもしれません。実は面倒くさいことに巻き込まれています。

基本的には下の記事で書いたmt2bloggerを使って移行します。

Ogawa::Buzz: MTからBloggerへの移行についての覚え書き(2)

が。

スパムブログ対策のため、Blogger Data APIはスロットリングされており、一日あたり50件までしかポストできません。しかもこの制限に2回引っかかるとアカウントがロックされます。ロックされてもWeb UI経由ならCAPTCHAコードを入力することでポストできます(そうじゃないとこの記事自体ポストできませんよね)。

「ロック解除の確認をリクエスト」というところからリクエストすれば2営業日くらいで解除されます。一旦解除されれば、それ以降アカウントロックされることはなくなりますが、一日あたり50件という制限は残ります。残りのすべてのエントリをBloggerに移行するにはひと月近くかかることになります。

そういうわけで気長に移行するつもりです。

Apr 25, 2009

Movable Type逆引きデザイン事典

小粋空間の荒木さんらの共著による「Movable Type逆引きデザイン事典」の献本をいただきました。

この本は、とりあえずMovable Typeをセットアップしてブログを始めてみたけど自力でカスタマイズしてみたい人、Web制作の仕事をしていてカスタマイズする必要に迫られている人に向けた、辞典風に使う本です。頭から読もうとすると挫折します。4部を斜め読みした限りでは、MultiBlogとかMotionとかActionStreamとか私がもう把握していない(笑)事柄について書かれていて勉強になりました(正直に言うと、mt:Entriesにuniqueという引数ができてたのも知りませんでした)。

Apr 17, 2009

MTからBloggerへの移行についての覚え書き(2)

Ogawa::Buzz: MTからBloggerへの移行についての覚え書き(1)の続き。

Blogger Data APIを使ってMTからBloggerにデータを移行することもできます。

ひとまず、Blogger Data APIを使った簡単な移行ツールをPerlで書いてみました。

mt2blogger - Google Code

以下のように実行します。

$ ./mt2blogger --blog_id=1 --username=foo@gmail.com --password=passwd \
  --postURI=http://www.blogger.com/feeds/<blogger_blog_id>/posts/default

postURIに指定するのは、Bloggerブログのヘッダの<link rel="service.post">に書いてあるURLです。

このスクリプトを実行すると、公開状態のMTエントリをBloggerに一件ずつポストした上で、各MTエントリのkeywordsフィールドにポストされたエントリのEditURIを格納します(keywordsフィールドに何か格納されていた場合上書きします)。EditURIは下のような形式になっているはずです。

http://www.blogger.com/feeds/<blogger_blog_id>/posts/default/<blogger_post_id>

このEditURIを使うことで、MTエントリとBloggerポストの間のリンケージを実現できます。例えば、下のような簡単なプログラムで移動前後のURLを表示できます。

#!/usr/bin/perl -w
use strict;
use warnings;
use lib qw( lib extlib );

use MT;
my $mt      = MT->new;
my $blog_id = 1;

use MT::Entry;
my $iter = MT::Entry->load_iter(
    {
        blog_id => $blog_id,
        status  => MT::Entry::RELEASE(),
    },
    {
        sort      => 'authored_on',
        direction => 'ascend',
    }
);

use LWP::Simple;
use XML::Atom::Entry;
while ( my $entry = $iter->() ) {
    my $editURI = $entry->keywords or next;
    my $content = get($editURI);
    my $gentry  = XML::Atom::Entry->new( Stream => \$content );
    my @link =
      grep { $_->rel eq 'alternate' && $_->type eq 'text/html' } $gentry->link;
    print $entry->permalink . ' -> ' . $link[0]->href . "\n";
}

1;

いいじゃん、できるじゃんと言いたいところですが、現状のBlogger Data APIは完全なものではありません。コメントを追加するAPIは存在するのですが、生成されたコメントのオーナーがAPIのauthenticated userになってしまいます。mt2bloggerでコメントの移行を実装していないのはそのためです。この点に関してはいずれAPIが修正されるのを待って、実装しようと思っています。

MTからBloggerへの移行についての覚え書き(1)

MTからBloggerにデータを移行する方法はおおまかに言って2つあります。一つは「設定」→「基本」→「ブログツール」の「ブログをインポート」を使う方法、もう一つは言わずもがなですが、Blogger Data APIを使う方法です。この覚え書きでは前者について説明します。

何らかの方法でMTデータをBloggerのインポートファイル形式(Atomフィード形式)で書き出しておき、「設定」→「基本」→「ブログツール」の「ブログをインポート」でインポートすれば、MTからBloggerにデータを移行できます。MTのエクスポートファイルをBloggerのインポートファイルに変換するPythonスクリプトもあります。

google-blog-converters-appengine - Google Code

ただし、このスクリプトはまだまだ品質が低いです。多言語の取り扱いが不完全、コメントデータがインポートできない、すべてのエントリのフォーマッタとしてconvert_breaksを使うことを前提にしている、などの問題があります。コメントデータを無視して良いなら、わざわざこのツールを使わなくてもMTのインデックステンプレートとして以下のものを使っても同じ効果が得られます。

<?xml version="1.0" encoding="<$mt:PublishCharset$>"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title><$mt:BlogName remove_html="1" encode_xml="1"$></title>
    <link rel="alternate" type="text/html" href="<$mt:BlogURL encode_xml="1"$>" />
    <link rel="self" type="application/atom+xml" href="<$mt:Link template="feed_recent"$>" />
    <id>tag:<$mt:BlogHost exclude_port="1" encode_xml="1"$>,<$mt:TemplateCreatedOn format="%Y-%m-%d"$>:<$mt:BlogRelativeURL encode_xml="1"$>/<$mt:BlogID$></id>
    <updated><mt:Entries lastn="1"><$mt:EntryModifiedDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></mt:Entries></updated>
    <mt:If tag="BlogDescription"><subtitle><$mt:BlogDescription remove_html="1" encode_xml="1"$></subtitle></mt:If>
    <generator>Blogger</generator>
<mt:Entries lastn="2000">
<entry>
    <title><$mt:EntryTitle remove_html="1" encode_xml="1"$></title>
    <link rel="alternate" type="text/html" href="<$mt:EntryPermalink encode_xml="1"$>" />
    <id><$mt:EntryAtomID$></id>
    <published><$mt:EntryDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></published>
    <updated><$mt:EntryModifiedDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></updated>
    <author>
        <name><$mt:EntryAuthorDisplayName encode_xml="1"$></name>
        <mt:If tag="EntryAuthorURL"><uri><$mt:EntryAuthorURL encode_xml="1"$></uri></mt:If>
    </author>
    <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/blogger/2008/kind#post" />
    <mt:EntryCategories><category term="<$mt:CategoryLabel encode_xml="1"$>" scheme="http://www.blogger.com/atom/ns#" /></mt:EntryCategories>
    <mt:EntryIfTagged><mt:EntryTags><category term="<$mt:TagName normalize="1" encode_xml="1"$>" scheme="http://www.blogger.com/atom/ns#" /></mt:EntryTags></mt:EntryIfTagged>
    <content type="html" xml:lang="<$mt:BlogLanguage ietf="1"$>" xml:base="<$mt:BlogURL encode_xml="1"$>"><$mt:EntryBody encode_xml="1"$><$mt:EntryMore encode_xml="1"$></content>
</entry>
</mt:Entries>
</feed>

この方法には致命的な問題があります。それは(まとめてインポートしてしまうので)後からMTの元のエントリとBloggerのエントリを対応づける方法がなくなってしまうことです。古いURLから新しいURLへリダイレクトすることができませんし、後からコメントをインポートする方法が見つかったとしても、どのBloggerのエントリに対応づければよいのか分からなくなってしまいます。個人的にはお勧めできません。

Apr 14, 2009

Line Breaksの取り扱いに悩む

Google Bloggerの問題の一つは改行の取り扱い。

How are line breaks treated? - Blogger Help

「設定」→「フォーマット設定」→「改行の変換」で改行を<br />に展開できるかどうか制御できます。ここで問題があります。

  • 変換規則が貧弱。Movable Typeのconvert_breaksが提供しているフォーマット規則よりかなり貧弱です。例えば、MTでは<pre>〜</pre>内の改行を変換しないなどといった除外規則がありますし、改行文字が2文字続くと直前の文を<p>〜</p>で囲むなどといった比較的インテリジェントな処理規則もあります。それに比べて、Google Bloggerの「改行を変換」はかなりnaiiveです。
  • 改行の変換の設定がグローバル。つまり、エントリごとに変換するかどうかを制御できません。言い換えると、MTから持ってくるデータは「改行を変換しない」、Bloggerで書くエントリは「改行を変換する」といった使い分けはできません。

平たく言うと、2つのアプローチがあります。

  • 改行を変換する。MTから持ってくるデータは正常にフォーマットされませんが、諦めることになります。
  • 改行を変換しない。その代わり、MTから持ってくるデータは、convert_breaksフォーマッタでフォーマット(他のフォーマッタを使っている場合にはそのフォーマッタでフォーマット)してからインポートし、Google Bloggerでエントリを書くときに手でマークアップすることになります。後者の作業は致命的に煩雑ですが、適当なアプリケーションを使ってエントリを書けば済む問題でもあります。

というわけで、後者のアプローチを採るのが私にとっては正着でしょう。

Apr 13, 2009

Movable TypeからGoogle Bloggerへの移行をこっそり目指すブログ、始めました。

こっそりですが、Movable TypeからGoogle Bloggerへの移行を目論んでいます。ここのところレンタルサーバの信頼性の低さに苦労させられていて、それならばいっそreliableでpersistentなストレージとしてBloggerを使ってしまえと思ったからです。いろいろあって連休明けくらいまでに移行を完了する、もしくは移行を諦める、予定です。

私のブログのMTの記事を楽しみにされている読者がいることは十分理解しています。MTのユーザを辞めるわけではないので今後もプラグインなどの記事も書くつもりです。さしあたっては、MTからBloggerへのtransparentな移行を実現するためのツールをどんどん作っては公開していく予定です。

ちなみに私は、MTやWordpressがユーザをロックインしてしまうことを結構問題視しています。

こうしたAll-in-oneシステムでは、ユーザインタフェース、バックエンドのデータストア、アクセスサーバなどの構成要素の一部に機能や性能や信頼性上の問題があったとしても、それぞれを独立の問題として解決することができません。例えば、アクセス数が異常に増加したとき、必要なのはアクセスサーバの性能向上であって、データストアに投資するのは無駄です。また、気の利いたユーザインタフェースが使いたいだけなのに、データストアが共有できないのなら一方のシステムから他方のシステムに移行しなくてはなりません。

Google(や他の企業)が信頼性があって高速なデータストアやCDNを提供するのであれば、そうしたインフラを有効に使ったブログシステム・CMSとしてMTを再設計するのが今後の方向性かなと思っています。もちろん、AppEngine上にMTを移植するというstraightforwardな解もありだと思いますけどね。

Apr 2, 2009

TagSupplementals Plugin 0.22公開

TagSupplementalsプラグインをアップデートしました。

今年の一月になってからMT 3.21から4.2にアップデートして以来、タグ検索をmt-search.cgiに依存していたのですが、やはり全然使い物にならないです。検索ワードをいちいちログに書き出すせいで気がつくとログが数万件に達していたり、検索処理自体が遅いせいでCGIプロセスが貯まりすぎてOOM Killerが発動してmysqldを殺してしまったり。

「お話にならない」

というわけで3.21時代から慣れ親しんできたMT-XSearchを使ったタグ検索に戻りました。その過程でいくつかの問題を見つけ、修正したのが0.22です。

TagSupplementals - ogawa - 「タグ」機能を追加・拡張するプラグイン。 - Google Code

具体的には以下のバグを修正してあります。

  • そもそもMT-XSearchとの組み合わせで動かない。
  • mt:RelatedTagsブロックタグが正常に動作しない。

どちらも動作確認すらしていなかったせいです。

TagSupplementalsとMT-XSearchを使ってタグ検索を実現する方法については以下を参考にしてください。

Ogawa::Buzz: Tagwire とMT-XSearchによる動的タグアーカイブ

基本的にはTagwireのときとまったく一緒です。異なるのは、テンプレートモジュールの名前を「XSearch TagSupplementals」にする点だけです。

Mar 31, 2009

HatenaBookmarker 0.11公開

一年半くらい前、Movable Typeのブログ記事やウェブページをはてなブックマークにポストするプラグインを作って公開していたのですが、そのまま自分でも使わず、そうこうするうちにはてなのAPIが微妙に変更になり、正常に動作しなくなっていました。修正したバージョンを公開しておきます。MT 4.2専用(それ以前のバージョンでは動作確認しません)。はてな大好きな人専用。

HatenaBookmarker - ogawa - ブログ記事やウェブページをはてなブックマークにブックマークするためのプラグイン。 - Google Code

あ、はてなのAPIの変更というのは、Edit URIをGETした結果に含まれるカテゴリーの表現が変更されたという点です。以前はdc:subject要素としてカテゴリーが一個ずつ格納されていたと思うのですが、今はsummary要素にブックマークコメントと一緒に(例: "[cat1][cat2]bookmark comment")格納されているようです。

動作確認は...今からします。このエントリーがブックマークされていたら成功です(笑)

Feb 26, 2009

MTテンプレートのアトリビュートをモディファイアと呼ぶのは止めちまえ

ちょっと前から気になっていたことなのだが、MTテンプレートタグのアトリビュートないしオプションを「モディファイア」と呼ぶのは、最近始まった悪しき慣習だ。

テンプレートタグリファレンス | MovableType.jp

そもそもアトリビュート(オプション)とモディファイアでは言葉の「クラス」が異なる。

アトリビュート(オプション)は、そのファンクションの振る舞いを制御するための情報を与える手段であろう。それに対して、モディファイアはアトリビュートの一サブクラスであって、ファンクションの出力への修飾(フィルタの適用)を指示するものであろう。

確かにmt:Entriesにlastnを指定したとき、「mt:Entriesに最新のN件を取り出すように指示」しても「mt:Entriesが生成した全リストから最新のN件をフィルタして出力」しても同じ結果が得られるのだからどちらでも構わないという見解は理解できる。だが、実際にやっているのは前者であり、glueのような反例(フィルタではないアトリビュート)もすぐ見つかる。glueでは分かりにくければ、アトリビュートに計算式を与えると計算してくれるファンクションタグを想定すればよい。

シックス・アパート担当者の意図は、説明に使う術語を減らした方が分かりやすいだろうというところにあるのだと思う。そうした事情は理解できる。でもだとしたらモディファイアなどという特殊な術語を場当たり的に使わなくてもいいはずで、全部アトリビュートと呼べばいい。実際、英語版のページを見ると、「グローバル・モディファイア」のことをtemplate tag modifierあるいは単にmodifier、「(アトリビュートとしての)モディファイア」のことをattributeと呼んでいるようだ。

MTテンプレートのアトリビュートをモディファイアと呼ぶのは止めちまえ。

Feb 25, 2009

ダイナミックパブリッシングでsort_methodを使えるようにするパッチ

ダイナミックパブリッシング時には、MTSubCategoriesMTTopLevelCategoriesなどでsort_methodオプションが無視されてしまいます。この問題を解決するパッチを作りました。sockfish用ですが、MT 4.23などにもそのまま適用できると思います。

mtos-r3457-sort_method-php-support.patch

sort_methodには"FooClass::barMethod"のようにPerlのパッケージ名を含んだ関数名を指定することになっています。ダイナミック用には、これを全部小文字にして"::"を"_"に置き換えた名前のPHP関数を利用します。

以下はダイナミックパブリッシング用にsort_methodを定義した例。

plugins/SortableCategories/php/init.SortableCategories.php

Feb 20, 2009

SortableCategories 0.01改め0.02公開

カテゴリやフォルダをユーザの好きなようにソートするプラグイン、SortableCategoriesを作りました。

SortableCategories - ogawa - A plugin for realizing Sortable Categories and Folders. - Google Code

同様の目的のプラグインがいくつかありますが、SortableCategoriesが特徴的なのは以下の点です。

  • Drop & Drop操作でのカテゴリーツリーの編集の実現。script.aculo.usのSortableツリーを利用しています。
  • 最小限のコンストラクトのみでの実現。このプラグインでは、新しいブロックタグやファンクションタグを一切導入しません。言い換えると、できることは限られていますが「これで十分」。

カテゴリツリーを編集するには

  1. まず、「カテゴリの管理」に行きます(「一覧」ドロップダウンメニューから「カテゴリ」を選択します)。
  2. 「カテゴリの管理」の右側に「カテゴリツリーの管理」というリンクが表示されているので、クリックします。
  3. 「カテゴリツリーの管理」画面では、カテゴリツリーを好きなように編集できます。カテゴリまたはサブツリーをつかんで適当な場所に移動させることができます。
  4. 思う存分編集したら「保存」ボタンをクリックすることで現在のツリーの状態を保存することができます。

フォルダツリーも同様にして編集できます。

カテゴリツリーを出力するには

えーと、まずいろいろ誤解があると思うので整理しておきますが、MTのカテゴリ関連のタグ(全37個)は、カテゴリリストに関わるものと、カテゴリツリーに関わるもの、それ以外のものの三種類に分類できます。

SortableCategoriesは順序付きのカテゴリツリーを操作するツールなのですから、関係あるのはカテゴリーツリーに関連するものだけです。このクラスに分類できるタグをざっと挙げると、SubCatIsFirst, SubCatIsLast, HasSubCategories, HasNoSubCategories, HasParentCategory, HasNoParentCategory, IfIsAncestor, IfIsDescendant, SubCategories, TopLevelCategories, ParentCategory, ParentCategories, TopLevelParent, SubCatsRecurse, SubCategoryPathの15個。

このうち、カテゴリツリーのノードの出現順に関係するものとなると、SubCatIsFirst, SubCatIsLast, SubCategories, TopLevelCategories, SubCatsRecurseの5個だけ。

さらに、SubCatIsFirst, SubCatIsLastが使えるのはSubCatsRecurseの中だけですし、TopLevelCategoriesはSubCategoriesにtop="1"という引数を渡しただけのシンタクティックシュガーでしかありません。つまり、SubCategoriesとSubCatsRecurseだけ何とかすればいいわけです(37→15→5→2)。

好都合なことにSubCategoriesにはsort_methodというオプションがあり、カテゴリの階層ごとにカテゴリリストをソートするPerlのメソッドを指定できるようになっています。

つまりは適切なメソッドだけプラグインで提供してやれば用は足りるってことです。それ以外のユーザ定義タグは一切不要だってことです。はぁはぁ。

SortableCategoriesプラグインは、SortableCategories::sorterというsort_method用メソッドを提供しています。これをうまく使うことで「カテゴリツリーの管理」画面で設定した通りにカテゴリーツリーをレンダリングできます。

よく分からないなという人は、「カテゴリアーカイブ」ウィジェットを以下で置き換えれば済みます。

<mt:IfArchiveTypeEnabled archive_type="Category">
<div class="widget-archive widget-archive-category widget">
    <h3 class="widget-header">カテゴリ</h3>
    <div class="widget-content">
    <mt:TopLevelCategories sort_method="SortableCategories::sorter">
        <mt:SubCatIsFirst>
        <ul>
        </mt:SubCatIsFirst>
        <mt:If tag="CategoryCount">
            <li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription remove_html="1" encode_html="1"$>"</mt:If>><$mt:CategoryLabel$> (<$mt:CategoryCount$>)</a>
        <mt:Else>
            <li><$mt:CategoryLabel$>
        </mt:If>
        <$mt:SubCatsRecurse$>
            </li>
        <mt:SubCatIsLast>
        </ul>
        </mt:SubCatIsLast>
    </mt:TopLevelCategories>
    </div>
</div>
</mt:IfArchiveTypeEnabled>

mt:TopLevelCategoriesにsort_method="SortableCategories::sorter"というオプションを与えているだけです。

mt:Categoriesなどで表示されるカテゴリリストはソートされません。それは(小さい文字で長々と説明したように)必要ないからであり、仕様だからです。


まだクオリティ的にアレかもしれませんが、興味がある方は使ってみてください。

Feb 12, 2009

プラグインでMT::Objectのインタフェースを拡張する

リコメンデーションエンジンを実装するためのフレームワークをMTに組み込もうかと思って、少しだけ手を動かしている。

ogawa - Revision 640: /trunk/Recommendable

でもって気がついたのは、ドキュメントされていないけど、プラグインを使ってMT::Objectのインタフェースを拡張できるということだ。

MT::Entryは、デフォルトでMT::Object、MT::Taggable、MT::Scorableを継承している。3つのスーパークラスは論理的には(ディスパッチ順はあるけれども)等価だが、便宜上MT::EntryはMT::Objectのサブクラスで、MT::TaggableとMT::Scorableというインタフェース(Mixin)を使えるように宣言されていると考えると分かりやすい。

ここでは、プラグインを使って、MT::EntryをMT::Taggable、MT::Scorableインタフェースだけでなく、ユーザ定義のLibbleRabbleインタフェースを持つクラスにすることを考える。

まず、plugins/LibbleRabble/config.yaml(プラグイン本体)を用意する。

name: Libble Rabble
id: LibbleRabble
version: 0.01
object_types:
  entry: LibbleRabble

このように書いておくと、entryを定義しているMT::EntryクラスがLibbleRabbleインタフェースを継承するようになる。内部的にはMT::Entryパッケージの@ISA配列の末尾に"LibbleRabble"という文字列が追加されるだけ、これはPerl Mixinの代表的な実現方法の一つ。

LibbleRabbleクラスも用意しておこう。plugins/LibbleRabble/lib/LibbleRabble.pmというファイルを作って中身は適当に書いておけばいい。

package LibbleRabble;
sub libble { print "<\n" }
sub rabble { print ">\n" }
1;

テストコードはこんな感じに書いておけばおk。

#!/usr/bin/perl
use lib 'lib';
use MT::Bootstrap;
use MT;
use MT::Entry;
my $mt = MT->new;
my $e = MT::Entry->load(2);
if ($e->isa('LibbleRabble')) {
  $e->libble();
  $e->rabble();
}

制限事項は、

  • 一つのプラグインで一つのインタフェースしか追加できないよ。
  • ドキュメントされていない仕様(ユーザ定義の新しいデータモデルを追加するための仕組みを流用しているだけ)なのでいつか使えなくなってもしらないよ。
  • リブルラブルに深い意味はないよ。

Jan 27, 2009

I18N Helper Plugin

ついでなんでOgawa::Buzz: MT-I18N PluginをMT 4.2用に書き直したプラグイン。

I18NHelper-0.10.zip

TagSupplementals Plugin 0.20公開

いろいろあって(?)、TagSupplementalsプラグインをアップデートしました。今回のアップデートは、MT3時代から引き摺ってきたコードを改めてモダンな(MT4の)プラグイン構成に準拠させることを主な目的としています。したがって機能追加はありません。今回のバージョンからMT 4.2以降のみをサポートします。

TagSupplementals - ogawa - Google Code

また、このバージョンではMemcachedを利用したときにmt:RelatedEntriesのレンダリング処理を高速化する機構が実装されています。具体的には共起行列をMemcached上にキャッシュして再利用するようにしています。この最適化による効果は以下の通り。

青と赤が以前のバージョンをMemcachedなし・ありで実行した場合の再構築時間、オレンジが今回のバージョンをMemcachedありで実行した場合の再構築時間です。13%くらい速くなっていることが分かります。もちろん、mt:RelatedEntriesのレンダリング単体だけ測ればもっとずっと速くなっているはずです。

mt:RelatedEntriesのレンダリング時間のみ計測したところによると、Memcachedを使わない場合は31.6秒、Memcachedを使う場合は25.7秒(旧バージョン)、16.0秒(新バージョン)。

他にも、ブログ記事を更新したり削除したりすることによってキャッシュに載っている共起行列の再計算が必要になった場合には、自動的に関連ブログ記事(つまり、タグを共有している記事)に対応するキャッシュを無効化するようにしています。

今後はこのコードベースを元に実用的な性能を実現に向けブラッシュアップしていきます。

ところで、このプラグインのmt:RelatedEntriesでやろうとしているのは、結局ものすごく単純で、オンラインで計算可能なRecommendation Engineなんですよね。本当はMT::Recommendableみたいなインタフェースだけ切っておいて、再構築時に計算してしまえるようなlight & poorなengineも、バッチジョブとして実行されるheavy & richなengineも実装できるようにするのがよいかもしれませんね。