プログラミングの最近のブログ記事

よくMovable Type (に限らないけど) のどこが面倒って話で画像とかファイルのアップロードがブラウザベースで1つずつってのは面倒だよねって話になるのだけど。

で、結局作っちゃえばいいじゃん、っていう話になるんですけど何でもかんでもJavaScriptとかAjaxとかでやるんじゃなくて、Adobe AIRでやるとか色々考えられるんだけど (それでもブラウザ上にこだわるならAdobe - Flexでやるとか)、ちょっと思い立ってREALbasic落としてきて触ってみた。昔結構使い込んでいたツールだし、手っ取り早いかなって(iPod touch / iPhoneのアプリ吐けるようにならないかなぁ...)。

1時間ほど使いながらリファレンスとか使い方をググってみたりしたけど(メーリングリストの過去ログとかでサンプル探したり)、一時は結構日本のコミュニティも勢いあったんだけどなぁ、という感想。特に日本語で新しい情報がない。

HTTPSocketまわりは昔使っていた頃からかなり変わっていて(もちろん充実していて)、とりあえずサーバーのcgiにユーザー名とパスワードをポストするだけのスクリプトを書いたらちゃんと動いた。

ウィンドウにURLFieldって名前でテキストフィールド作り、Movable Typeのcgiのパスを入力。プッシュボタンに以下のスクリプトを書いてクリック。


Dim form as Dictionary

form = New Dictionary
form.value("username") = "test"
form.value("password") = "test"
  
MTSocket.setFormData form
MTSocket.post URLField.text

ただそれだけ。ちゃんとMTにログインできた。別にMTでなくともXML-RPCクライアントくらいなら簡単に作れそうな気がする。

で、Assetにアイテム放り込むには添付ファイル? を付ける必要があるわけだが、情報としてはこのあたりか。何とかなりそうか?

受け取る側はプラグイン書くかBootstrapでアプリ作って受け取るとか、ファイルブラウザとかも定義してxmlでAssetのデータリストを返してREALbasic側でインターフェイス作るとか...半分くらいやる気になった。とりあえずライセンスアップグレードしておこうか。

Mac OS X Leopard のAppleScriptが密かに面白い。
単なるOS Xネイティブなアプリケーションだけでなく例えば Movable Type 4.1 のようなソフトウェアを扱えるようになっているようだ(用語辞書、誰が書いたんだろう?)。

エントリーをブログに登録して再構築するスクリプトの例


tell application "Movable Type 4.1"
    activate
    set obj to new entry with property
        { title : "Welcome to Movable Type4!",
          text : "New design launched using Movable Type.",
          status : 2,
          author : 1 }
    set blog to item 1 of mt_blog
    set result to save obj in blog
    rebuild result without index archive
end tell

まぁ、ここまでなら素直にPerlで書けよ! ってなことになるけれど、以下の例なんかどうだ?

Excelと連携させる


tell application "Movable Type 4.1"
    activate
    set blog to item 1 of mt_blog
    set entries to get entries of blog
    set i to 1
    repeat with entry in entries
        tell application "Microsoft Excel"
            tell document 1
                set cell1 to "A" & i
                set cell2 to "B" & i
                set text of range cell1 to (title of entry)
                set text of range cell2 to (permalink of entry)
                set i to i + 1
            end tell
        end tell
    end repeat
end tell

エントリーのタイトルとURLをExcelにそのまま渡してセルにセットしている。Excelからエントリーをインポートの方がニーズはありそうだけど。





嘘! 嘘です。すいません、もうしませんって言ったのに...一年に一度だし...また書いてしまいました。あんまり覚えてないや、AppleScript。(てかLeopardのマシンないし!)

それでも、


do shell script "./tools/run-periodic-tasks"

ってのは普通に使えるかもね。Excelから値をひっぱってシェル経由でPerlスクリプトに渡せばいいわけか。いや、できんことないよな。意味があるかどうかわからんけど。

最近、MacのみならずiPod touchとかiPhoneとかApple製品が面白いんだが、昔僕が良く使い捨てアプリを作っていたREALbasicとか、最近どうなんだろう。iPod touch / iPhoneのアプリが作れるとかなったら再び注目を浴びるんじゃないかなと思っていて、久しぶりに触ってみようかと。

で、本格的なデスクトップアプリを作るほどの暇は年度末のこの次期にはないし、ちょっと以前から思っていたアイデアを少し。

WordPressのプラグインをDrag & Dropすると、Movable Typeのプラグインに変換してくれます。β版。

Drag & Drop すると表示されるウィザードに従って必要な情報を入力していくと変換されます。

やっぱり何でも間でもウェブアプリではなくてたまにはこういうデスクトップアプリとかも作ってみたいよね。



















ごめんなさいごめんなさい。忙しかったのでネタをブラッシュアップする暇がなかったんです!

来年こそはもう少しゆとりを持って面白いネタ考えます。

MTOSの姿はまだ見えませんが...そろそろ直前になってきましたので、内容について触れておきます。

日時:11月10日土曜日 16:00〜 (50分) [会場: 南港ATC ITM棟 9F-H6]

内容について

これまでは割とWeb屋さん向けの場所で話すことが多かったのですが、今回はOSS関係のイベントなので、これまでしゃべって来たことやこのブログに書いて来たものも含めて、方向性としては「Webアプリの開発にMTが便利!」という面を中心に話そうと思います。

  • Inside MT (MTの構成)
  • MT Perl APIの基礎
  • データベースアクセスとMT::Objectのサブクラス作成
  • MTのテンプレートエンジン
  • Perlプラグインによる拡張
  • Bootstrap.pmを利用したアプリ開発
  • PHPによるダイナミックパブリッシング
  • オープンソースならではの活用方法を考えよう

*内容は変更になる可能性があります。

特に、テンプレートエンジンについては、MT4になってMTにCMSテンプレートがMTのテンプレートエンジンを使うようになっていることもあり(3.3まではHTML::Template)、管理画面の拡張やWebアプリ開発でも多いに活用できることから、今回はその辺も強調してみたいと思います。

関西で行われる数少ないOSS系のイベントですから、他のセッションもチェックしていただいて、面白そうなものがあれば是非覗いてみてください。

それでは当日、会場でお会いしましょう。

まだやってるし...もうちょっと続くかもしれないけど、皆さんもう飽きました?

ブログ内検索




  

実は検索だけじゃないのだ

ブログにおけるエントリーの関連性や体系付けを行うしくみとして、カテゴリーやタグというものがある。一方、読者が欲しい情報を探す一つの手段として「検索」がある。

カテゴリーもタグも発信者の主観で付けられるものだ。ソーシャルブックマーク等のタグはそうではないけれども。

高速なタグ・アーカイブが欲しい

発信者が主観で付けられるものゆえ、検索語の選択が無限であるのに対してカテゴリーやタグは有限だ。であるならばこれらのアーカイブは静的アーカイブにすることが可能で、MTのカテゴリーアーカイブが静的生成できるのは良いとして、タグ・アーカイブも静的生成できるのが望ましいのではないかと思う。

できないのか? と思ってググってみると、同じようなことを考えて既に行っている方がいらっしゃるわけですね(静的生成ではないけど)...

現在作成中のダイナミックパブリッシングを利用した検索ページではタグ検索ができるようになっている。MT4のデフォルトテンプレートでは、タグ検索はmt-searchに渡される動的ページだから、mt-searchが高速動作できる環境でないと遅い(その仕組み上キーワード検索程遅くはないが)。また、CGIによって動的生成されるページへのリンクには nofollowを付けたいところ。でないとGooglebotが (に限らずロボットが) mt-searchを叩くのだ。MTインストール済みレンタルサーバーとかで、ロボットが多くのmt-search を叩いている状況ってのは何だか恐い。ただでさえスパマーがtrackbackやcommentのCGIを叩きまくっているのだし。

モジュール版PHPで動作しているサーバーの場合、CGI(Not FastCGI)の起動よりも早くレスポンスを返せるからこの(PHP)ダイナミック版タグ検索は一つの選択肢になると思う。但し、MTのダイナミックパブリッシングではパラメータ付きのページをキャッシュしてくれない。ここが何とかなるといんだけど。もう少しダイナミック版のソースを追いかけてみよう。

さすがにキーワード検索は動的生成じゃないと、ってかそれでいいと思うし

話がそれた。一方「検索」は発信者ではなく読者が自由に設定するものだ。一部の読者は発信者の意図しないカテゴリの情報を求めているかもしれない。なので基本的に動的生成で良い。問題はMTのデフォルトテンプレートで「検索結果」フィードへのリンクが表示される点だ。確かに検索結果のフィードがとれるってのは便利かと思う。

それでもやっぱり読者がRSSリーダーに mt-search が生成する動的ページのフィードを登録するってのもやっぱり勇気がいるなぁ (サーバーへの負担という点で)。パワーに余裕の無いサーバーではRSSリーダーが取得に失敗するってことも多いのではないだろうか。

ということで、高速・軽量な検索ってのは単なる検索ではなくて、タグ・アーカイブや検索結果のフィード配信の代替プログラムでもあり、カテゴリ+タグでの絞り込みとか、カテゴリ+キーワードの絞り込みとかを実現するためのものなのです。 キーワードはともかく、このあたりを柔軟に指定できて且つ静的に吐き出すことができれば、関連性, 体系付けの選択肢も広がるのではないかな?

分かち書き+MySQL FULLTEXTインデックス検索 VS LIKE検索

両方とも実装してみたのだが、400エントリー弱(実際にはテスト用ブログ等でDBにはその倍くらいが登録されている)のこのブログで、現状のサーバーでは2倍程度の差が出ている。とはいえ20件表示であれば0.08秒前後と0.16秒前後、体感速度に大して差はない。

フィードの生成はもっと高速。各々約半分くらいの時間で検索と構築が終わる。これは検索結果ページではトータルヒット件数を取得してページ送りを実現するためにSQLを2回発行しているからだ(まず全てのヒット件数をカウントしてからoffset, limitを指定して表示すべきエントリーを得ている)。フィードではページ送りが不要だからこの分のSQLが不要。

FULLTEXTインデックス検索には速度以外にもメリットがあって、関連性の高い順に表示することができることだ。また、インデックス作成の際に画像のALTを展開した上でHTMLタグを削除しているから、「タグの中」がひっかからない。
LIKE検索ではたとえば「HTML」について書かれたエントリーを検索したい場合に、アンカータグの中の foo.html とかにもマッチしてしまう。

逆にこれを逆手に取れば、特定のエントリーにリンクしているエントリーの検索とかにはLIKE検索使えるね。例えば、「音声ブラウザと相性の良いHTMLを作る(1)。」にリンクしているエントリーはページのパスをクエリーとして指定してやれば良いわけだ。

ということでね、色々活用法が考えられて 夢がひろがりんぐ でしょ?

ウチの会社で作成したサイトは全部MTで作ってんじゃねぇの? と思われているかもしれませんが、もちろんそんなこたぁありません。

但し昔っからCMS的なサイトの制作を行っていて、「よくこんな小世帯でこんだけのボリュームのサイト作ってんね!?」と言われる答えの一つは「自動化」なわけです。徹夜でガシガシHTMLコーディングってのがWeb屋のイメージなのかもしれませんが、ウチは徹夜はしません。

面接の際に意外によく聞かれるんですけど「徹夜はありますか?」って、世間のWeb屋はどんなんやねん、って思いますよ。

あ、一応答えは「年2回」って答えてます。実際は2回ないけどね。まぁ1回あるかないか。ただ、徹夜になるってことは誰かが何かミスした時しかあり得ないですが、まぁ人間だもの、ミスもあるさっ。

のっけから話それまくりですが、来月こんなイベントがあるそうなのでちょっと前フリというか、ウチでよくやる方法についてちょっと晒してみる(わりと普通なのかなぁ)。

まぁ実際はMTのAPIでもって詳細なカテゴリの関連づけとかブログの切り分けとかテンプレートのインポートとか色々やるわけですが、MT4でエクスポート/インポート形式がちょっとだけ進化したので(ファイル名なんかを引き継げるようになった)、Excelで作成したデータをもとにMTのエクスポート形式のファイルを生成して読み込むって方法が簡単なので紹介したい(もちろん、MT4のバックアップのフォーマットのXMLを気合いを入れて作るって方法もあるよ)。

まず、ExcelとかOpenOfficeとか何でもいいけれどスプレッドシートを作成できるソフトウェアでマスターデータを作る。構造は何でもいいけど、この例ではページのタイトル, カテゴリ, ファイル名, テキスト, 追記なんかを各セルに入力。

Excelでマスタデータを作る

保存形式を「テキスト(タブ区切り)」にして保存。

スクリプトはこんな感じ


#!/usr/bin/perl -w

$fp = $ARGV[0];

open(FH, $fp);
while(<FH>){
    my $line = $_;
    my @datas = split(/¥t/, $line);
    my $html = &_read_tmpl($datas[0], $datas[1], $datas[2], $datas[3], $datas[3]);
    print $html;
}
close(FH);

sub _read_tmpl {
    my ($title, $cat, $basename, $excerpt, $text, $text_more) = @_;
return <<"MT_TMPL_HTML";

--------
AUTHOR: junnama
TITLE: $title
BASENAME: $basename
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: __default__
ALLOW PINGS: 0
PRIMARY CATEGORY: $cat
CATEGORY: $cat
DATE: 08/30/2007 00:00:00 PM
-----
BODY:
$text
-----
EXTENDED BODY:
$text_more
-----
EXCERPT:

-----
KEYWORDS:

-----

MT_TMPL_HTML
}

Macだったらターミナルから引数にマスタ、出力をファイルに指定して実行。WindowsだとActivePerlを入れておく必要があるけど。


perl ./tsv2mt.pl master.tsv > mt_html.txt

生成されたテキストをMTからインポートすればOK。ね、簡単でしょ? コツ、という程じゃないけど、カテゴリは英数文字で指定しておくとカテゴリーのbasenameがこれになってくれる(インポートした後にカテゴリー名とbasenameの関連づけを行う必要があるのだけど、これこそMTのAPIを使えばチョチョイと作れる)。

つまり、ここで書いたことのひとつの具体的な事例ね。

ということで、このエントリーをよく読んでから、以下のエントリーを読むと幸せになれるかも(笑)。

Nakedがじわじわ?来てるので改めて紹介。というか何をやっているかが分かりやすいようにサンプルページを作ってみた(CSSと画像をオフにする以外特別なことをするのかな? とかいう反応もあったことだし)。オリジナル変換後を具体的にHPRとかに読ませてみて欲しい(誰か音声ファイルとか作ってくれないかな?)。読み上げ向けと他のモードの違いとかも是非試してみてください。単に画像切ってるだけじゃないので。

じわじわ...

サンプルページ

実は、このプログラムを書いた僕自身は本職のプログラマではないしどっちかと言えばマークアップとかアートディレクションとかが本来の立ち位置である人間なのでして、このエントリーに書いた(5は別にして)「正規表現」とか「Perl」とかを覚えるとこんなものが作れるのです。

でも、むしろこれを作るのに必要な知識ってのは、Perlや正規表現よりも「どんなHTMLが読み上げにくくて、音声ブラウザユーザーやスクリーンリーダー利用者はどんなところに困るのか」という部分の知識です。で、この知識に強い人たちこそウェブアクセシビリティとかに配慮してHTMLを正しく書こうと思っている人とかウェブ標準とか大切と思っている「マークアップエンジニア」の人たちなのではないかなぁ。プログラムなんて実現のための手段でしかないし。

Nakedのコンセプトというか何をやっているかは以下のエントリーに殆ど書いてます。イケてないところも沢山あると思うけれど、「ここがイケてない」と思うそこのあなた! 有用なアイデアや確かにイケてないところがあったらまだまだ改良して行こうと思うのでひとつ宜しく。

* 一応言い訳しておきますが、このブログは駄目です。汚いし、突っ込まれるところ沢山あるのでそこはまぁ大目に見ていただけると幸い。

関連エントリー

ちなみに、ウチの会社でリニューアルなんかの仕事を受けた時には、まずこんな感じで既存のコンテンツをてきるだけらくちんな方法でクリーンアップして再利用できないか考えます。あとはうまくMTに放り込む方法を探ります。

と、まぁこんなことやってる制作会社やってます。だから、ね、ヲチはこちらね。宜しく。

Naked (Beta)について

「音声ブラウザと相性の良いHTMLをつくる」というコンセプトで開発を始めた「ウェブコンテンツ・テキストバージョン・ジェネレーター(ゲートウェイ)」です。

以前にも紹介しましたが、その後色々と調整を行い実用レベルになったと思うので、このブログの各ページに各モード(スキン)変換のためのリンクを設置したついでにブックマークレットを作りました。宜しければご利用ください。

これは何?

  • HTMLからCSSや装飾部分, JavaScript等を削除します。
  • 一定サイズ以下の画像はALT属性の文字列に置き換え、一定サイズ以上の画像は外部リンクに変換します。*
  • 音声読み上げの際に問題になることの多いいくつかの問題 (日付のフォーマット、機種依存文字、DEL要素,INS要素、スペースによる日本語の分割等) の解決 (読み上げやすい、あるいは読み上げて意味の通りやすいフォーマットへの変換) を試みます。
  • レイアウト用のテーブル要素 (らしきもの) を削除してできるだけプレーンなHTMLに変換します。
  • PDFをテキスト化します。
  • 上記の変換を行った上で、各スキンの適用やルビ振り処理を行います。

* 画像については実際はもう少しインテリジェントな? 処理を行っています。見出し要素の中の画像は「テキストが画像化されたものだろう」、とかアンカーの中の画像は「ボタン」だろうとか。詳しく知りたい方は関連エントリーをご覧ください。

ブックマークレット

サイト貼付け用JavaScript

このブログに貼っているJavaScript↓そのまま使っていただいても構いません。


<script type="text/javascript" src="http://junnama.alfasado.net/online/naked.js"></script>

H3要素で「スタイル:」というラベル、各リンクはUL, LI要素によるリストです(このブログではCSSで一行に並べています)。

より詳細な仕様について

関連エントリーをご覧ください。実装の課程で書いたものです。どういうコンセプトでどのような処理を行っているかを書き連ねています。

関連エントリー

制限事項

  • httpsからはじまるURLのページには対応していません。
  • クッキーが必要なページやログインが必要なページには対応していません (ブログのコメント程度であれば問題ないと思います)。
  • HTMLやPDF文書の容量は4MBまで対応しています (実際に視覚障害者の方に要望をいただいたため、1MBから4MBに制限をゆるめましたが、サーバー負荷の問題もありますので暫く様子を見たいと思います)。
  • サービスは予告なく停止する場合があります。

プライバシーについて

  • フォームからポストされたデータ等は運営側では一切保持しません。
  • ゲートウェイから実際のサーバーへのHTTPリクエストヘッダ (UserAgent情報) にIPアドレスが付加されます(匿名プロキシとしての利用対策)。
  • IPアドレスと閲覧ページのURLについてはログに保存しています。

ちょっと宣伝

CMS製品への組み込みや企業や自治体様のサイトへの導入やカスタマイズについてはご相談ください。

また、Nakedと共通(一部のみ)のテキスト変換ルーチンを組み込んだMovableTypeのプラグイン(MovableType Jaccessibilityプラグイン)を提供しています。

がいよう。

「TrackBackはもうなかったことにしてはどうか?」とは? - Ogawa::Memorandaに反応してGoogleに買われる妄想を膨らませてみるエントリー。

実はこのモデルはユーザの負荷を外部サーバにオフロードすることによって利便性を提供しているという点でFeedBurnerと似通っている。誰か立ち上げてGoogleに買われるまで頑張ってみては(嘘)!!

例えばこのエントリからこのエントリへトラックバックを打つとして。

しようしょ。

http://example.com/ping.fcgi/http://as-is.net/blog/archives/001257.html へ以下のようにPOSTする(トラックバックの仕様通り)。

my $url = 'http://example.com/ping.fcgi/http://as-is.net/blog/archives/001257.html;
my %TBdata = (
	'url' => 'http://junnama.alfasado.net/online/2007/07/trackback_google.html',
	'blog_name' => 'Junnama Online(Mirror)',
	'title' => 'TrackBackをなかったことにしてGoogleに買われるまで頑張ってみたりして。',
	'excerpt'=> '「TrackBackはもうなかったことにしてはどうか?」とは? - Ogawa::Memoranda に反応してGoogleに買われる妄想を膨らませてみるエントリー。');
my $request  = POST($url, [%TBdata]);
my $ua = LWP::UserAgent->new;
my $res = $ua->request($request);
print $res->as_string;

受け取ったデータをスパムフィルターにかけてからHyperEstraierの文書ドラフト形式に変換してデータベースへputする。

@uri=http://example.com/ping.fcgi?__mode=get&to=http%3A%2F%2Fas-is.net%2Fblog%2Farchives%2F001257.html&rf=http%3A%2F%2Fjunnama.alfasado.net%2Fonline%2F2007%2F07%2Ftrackback_google.html
@title=TrackBackをなかったことにしてGoogleに買われるまで頑張ってみたりして。
@author=Junnama Online(Mirror)
@cdate=2007-07-05T12:00:00+09:00
@mdate=2007-07-05T12:00:00+09:00
rf=http://junnama.alfasado.net/online/2007/07/trackback_google.html
to=http://as-is.net/blog/archives/001257.html

「TrackBackはもうなかったことにしてはどうか?」とは? - Ogawa::Memorandaに反応してGoogleに買われる妄想を膨らませてみるエントリー。
estcmd search -vx -sn 300 100 200 -attr 'to STREQ http://as-is.net/blog/archives/001257.html' casket

とするとXMLで帰ってくる(一応ちゃんとやってみたからね)。

<?xml version="1.0" encoding="UTF-8"?>
<estresult xmlns="http://hyperestraier.sourceforge.net/xmlns/search" version="1.4.9">
<meta>
<hit number="1" auxiliary="off"/>
<hit key="[UVSET]" number="3" auxiliary="off"/>
<time time="0.000896"/>
<total docnum="3" wordnum="92"/>
</meta>
<document id="1" uri="http://example.com/ping.fcgi?__mode=get&to=http%3A%2F%2Fas-is.net%2Fblog%2Farchives%2F001257.html&rf=http%3A%2F%2Fjunnama.alfasado.net%2Fonline%2F2007%2F07%2Ftrackback_google.html">
<attribute name="@author" value="Junnama Online(Mirror)"/>
<attribute name="@cdate" value="2007-07-05T12:00:00+09:00"/>
<attribute name="@digest" value="ae74279b347acb5284ddbb66d6a92a15"/>
<attribute name="@mdate" value="2007-07-05T12:00:00+09:00"/>
<attribute name="@title" value="TrackBackをなかったことにしてGoogleに買われるまで頑張ってみたりして。"/>
<attribute name="rf" value="http://junnama.alfasado.net/online/2007/07/trackback_google.html"/>
<attribute name="to" value="http://as-is.net/blog/archives/001257.html"/>
<snippet>「TrackBackはもうなかったことにしてはどうか?」とは? - Ogawa::Memoranda に反応してGoogleに買われる妄想を膨らませてみるエントリー。<delimiter/></snippet>
</document>
</estresult>

なので、http://example.com/ping.fcgi?__mode=get&to=http%3A%2F%2Fas-is.net%2Fblog%2Farchives%2F001257.html へリクエストを送るとこのXMLをそのまま返すようにして...あとはAjaxでごにょごにょと...

めも。

スパム判別の部分がキモになるわけですが各ブログのオーナーが自分のブログのエントリーに対する公開・非公開・スパムといった判定を反映できる管理画面を提供して、そのデータを共有するようにすればいいかな。他にもスパム判別のアルゴリズムはあれこれあるからそのあたりを組み込んで。あとはスパムデータの共有とトラックバックデータの検索をノードサーバーでP2Pで処理させて負荷分散が図れるように最初から考えておくわけだな。

おまけ。

HyperEstraierのトップページの見出しにいつも密かに笑っているのだが、さっき覗いたら「超超超超イイ感じ迷子: コードも書かない人に言われたくはない。」だった(笑)。コード書くから言わせてね。虎苦罰区検索系夜露死苦!

Googleに買われるまで頑張ってみては(嘘)!!って...よく見たら(嘘)!!って書いてあったのに今気づいた(嘘)。

追記(2007年7月2日):
一連のエントリーで作成したものを取りまとめて公開しました。


驚くのはまだ早い!(なんて言ったりして)

そして、今回頂いた反応の中で、一番驚いたのがこれ。

* ↑トラックバックがHTTP error: 403 Throttledで弾かれる...

ここまで来たら...やっちゃえ!

MovableType10分間Cooking!(Part4)

まぁ10分で出来るのはこれまでに書きためたプラグインの各種パターンがあるからですが、テストやドキュメント、設定のUIとかそのあたりは手抜きで。

関連エントリー

静的生成されたファイルの全削除

今回の件でいえば「再構築」の代わりが「全削除」です。全削除しておくとあとは各ページが最初に閲覧された段階でそれぞれ再構築されます。リクエストのないページに対する無駄な再構築もありません。

my $plugin = new MT::Plugin::RebuildAt1stView({
	name => 'RebuildAt1stView',
	app_methods => {
		'MT::App::CMS' => {
			'remove_all_entry_archive' => ¥&_remove_all_entry_archive
		},
	},
});

MT->add_plugin($plugin);

MT->add_plugin_action('blog',
	'../'.MT->config('AdminScript').'?__mode=remove_all_entry_archive',
	'Remove All Entry Archives'
);

MT->add_plugin_action('list_entries',
	'../'.MT->config('AdminScript').'?__mode=remove_all_entry_archive',
	'Remove All Entry Archives'
);

プラグイン・アクション

全削除の場合はプログラム書くだけじゃなくて管理画面へのインターフェイスが必要です。add_plugin_action を使うと簡単です。

mt.cgi?__mode=remove_all_entry_archive;from=blog_home;blog_id=3

上記のように呼び出して動作させます。app_methods についてはこちらのエントリーに少し書いていますのでそちらも参考にしてください。

全削除は以下の通り。たかだか250程度のエントリーですが、感覚的には1秒以内で全削除できます(本当はちゃんとHTML組み立てて結果を返した方が良いですしエラーも拾った方がいいですけど)。

*ちょっと修正。is_superuserでスーパーユーザーかどうかチェックするようにした。


sub _remove_all_entry_archive {
	my $app = shift;
	my $user = $app->user;
	if ($user->is_superuser) {
		my $blog_id = $app->param('blog_id');
		my $iter = MT::Entry->load_iter({
			blog_id => $blog_id},{
			sort => 'modified_on',
			direction => 'descend',
		});
		if (defined $iter) {
			while (my $entry = $iter->()) {
				$app->publisher->remove_entry_archive_file(Entry => $entry, ArchiveType => 'Individual');
			}
			return 'エントリーアーカイブを削除しました!';
		} else {
			return 'エントリーが見つかりません。';		
		}
	} else {
		return '権限がありません。';		
	}
}

あとは各エントリーの保存や削除時に前々回のエントリーで作成した mt_permalink テーブルの更新が必要ですが、CMSPostSave.entry, CMSPostDelete_entryコールバックが呼ばれたタイミングで処理させます(MT4ではコールバック名が変更になっているかもしれませんがおそらく同等のコールバックは用意されていると思います)。


MT->add_callback('CMSPostSave.entry', 10, $plugin, ¥&_post_save_entry);
MT->add_callback('CMSPostDelete_entry', 10, $plugin, ¥&_delete_entry);

sub _post_save_entry {
	my ($eh, $app, $entry, $original) = @_;
	my $permalink = MT::Permalink->load({id => $entry->id});
	if ($entry->status != 2) {
		$app->publisher->remove_entry_archive_file(Entry => $entry, ArchiveType => 'Individual');
		if (defined $permalink) {
			$permalink->remove or die "Removing permalink failed: ", $permalink->errstr;
		}
	} else {
		if (defined $permalink) {
			$permalink->permalink($entry->permalink);
			$permalink->modified_on($entry->modified_on);
			$permalink->save or die "Saving permalink failed: ", $permalink->errstr;
		} else {
			$permalink = MT::Permalink->new;
			$permalink->id($entry->id);
			$permalink->blog_id($entry->blog_id);
			$permalink->permalink($entry->permalink);
			$permalink->modified_on($entry->modified_on);
			$permalink->save or die "Saving permalink failed: ", $permalink->errstr;
		}
	}
}

sub _delete_entry {
	my ($eh, $app, $entry) = @_;
	my $permalink = MT::Permalink->load({permalink => $entry->permalink});
	if (defined $permalink) {
		$permalink->remove or die "Removing permalink failed: ", $permalink->errstr;
	}
	$app->publisher->remove_entry_archive_file(Entry => $entry, ArchiveType => 'Individual');
}

残りタスク

ということで、ソースはこちらに晒しておきます。一旦削除します。後ほどアーカイブとして最新のものをアップします。ライセンスはGPLです! (しつこい?)
っていうか誰か完成させてください。以下残りタスクを挙げておきます。

追記:ソース一式を以下のページからダウンロードできます。
  • (何よりもまず)動作の検証・テスト
  • コメント・トラックバック反映時の再構築(というかページの削除)対応済み
  • Googlebot以外のロボット対策取り急ぎYahoo! とmsnbot対応
  • データベーステーブル mt_permalink 作成, 初期データ登録のインターフェイス(ウィザード?)
  • mtview.cgiをFastCGI対応させる(Bootstrap.pm を使ったアプリケーションにする)
  • 各処理の中のエラー処理
  • 全削除後の表示画面対応済み
  • ブログ毎の設定(オン・オフできるようにする、等)対応済み

このアーカイブについて

このページには、過去に書かれたブログ記事のうちプログラミングカテゴリに属しているものが含まれています。

前のカテゴリはアクセシビリティです。

次のカテゴリはモブログです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。