Oct 30, 2004

Il Pizzaioro@三軒茶屋

気が付けばイタリア料理屋に行っていません。嫌いではなくむしろ好きなのですが、イタリア料理がごく一般的なものになり、自宅でも近所のカフェ飯屋でもそれっぽいものがいくらでも食べられるようになってしまうと「わざわざ料理屋に出かけてまでして食べる」という行為から疎遠になってもいたしかたないでしょう。今となってはJolly-Pastaがそれなりのシンボルとして機能していた時代があったなんて到底信じられないわけです。今は「サイゼリヤ=さいぜり屋」が別の意味でシンボルとして通用しているかもしれませんが。

まあそんなわけでオサレでも何でもない普通のイタリア料理屋に行ってみようと思い立ってはみたのですが、考えてみると三軒茶屋にもイタリア料理屋は何軒かあります。というより、数軒どころかおそらくすごく多いはずです。割に当てずっぽうで、去年の春に世田谷線三軒茶屋駅の踏切そばにできたIl Pizzaioroに行ってみました。

ピザ屋なので侮っていましたが少し高いかもしれませんね。学生さんがデートとかでちょっと奮発して来るという感じの価格設定(ピザ・パスタが1500円程度)になってしまっているので、ピザ屋としてはバランスがおかしいように思われます。しかもクレジットカードが使えません。そのせいかどうか定かではありませんが我々が行った時間帯の店内は空席がとても目立ちました。しかし「ピザをちょっと一枚引っかけに来る」感じで来ると思いのほか店内の雰囲気は良いです。味はというとこれも良かったです。Bagna Caudaなんか野菜の高い昨今はうれしいですし、Margherita、Gnocchiもおいしかったです。

Il Pizzaioro
Google マップ - 東京都世田谷区太子堂4-20-7

Oct 29, 2004

dirifyについて考えてみた。

Movable Typeの「dirify」というのは、DIR-ify、すなわち文字列をファイルシステムに適した文字列に変換する操作を提供しています。MT tagに対するグローバルフィルターとして提供されているだけではなく、Movable Typeの内部でさまざまな局面(アーカイブファイルの名前の決定など)で利用されています。

その機能は大まかに言って以下の手続きで実現されています。

  1. [DefaultLanguageがja以外のとき] まず与えられた文字列のHigh ASCII文字(=最上位ビットが有効な文字群)のうち可能なものは7bit ASCII文字に置換する。例えば、ÀÁÂÃÅなどをAに置換する。
  2. 文字列を小文字に変換する。
  3. 文字列からHTMLタグを除去する。
  4. 文字列からHTML Entities (&XXX;というパターン)を除去する。
  5. 空白文字、アルファベット、数字以外を除去する。
  6. 空白文字をアンダースコアに置換する。

この仕様はLatin-1言語圏の人々の一定の支持を勝ち得ているようです。たとえMovable Type Plugin Directory: DirifyPlusのような亜種があるにしても。

しかし、今あえてはっきり言いたいことがあります。それは、「この仕様はクズである」ということです。

そもそも、空白文字は「_」に変換されますが、「!"#$%&'()-=^~\|@`[{;+:*]},<.>/?」はすべてヌル文字に変換されます。つまりこれらは空白文字より区切り文字としての順位が低いということになります。果たしてそうでしょうか? 「:-/,.」は文中、語中で明確に区切りを表す記号ではないでしょうか?

文字実体参照、数値文字参照はこれらの文字より不幸です。&nbsp;や&#160;はやはりヌル文字に変換されますが、意味的に空白文字より弱いのでしょうか。

そうそう忘れていました、Latin-1語圏(西欧諸国)などで普通にUTF-8をPublishCharsetに使っている人々にも不幸は平等に訪れます。High ASCII文字はUTF-8では2バイトに拡張されて表現されますから、dirifyに組み込まれているiso-8859-1用の置換ルールは適用されません。ちなみにこのあたりをうまく扱うMT Stuff: Dirify for Unicodeというプラグインもあります。が、これで何とかなったと思ったそこのフランス人は相当お人よしで、MTの内部では相変わらずオリジナルのdirifyが使われているわけなんですYO!

また、Latin-2,3,...語圏でiso-8859-2,3などをPublishCharsetに使っている場合にもdirifyはiso-8859-1用の置換ルールを適用します(それしかないのですから)。これは望ましい結果をもたらすかもしれないし、そうでないかもしれませんね。あいにくとチェコ語を入力できるキーボードは持っていないので確認できませんが…。

…まったく何も考えられていませんね。

しかし、それより何より気に食わないことがあるのです。それは日本語を含むMultibyte文字がアルファベットに変換されないのはいいとして、ヌル文字列に変換されるために区切りとしてすら機能しないことです。例えば「Movable Type使っててDBを壊したのYO!」の変換結果は「movable_typedbyo」となります。おかしくないですか? 「movable_type_db_yo」の方がまだDBに関する話であることが分かりやすいでしょう。所詮全角スペース「 」はヌル文字に置換され、半角スペースには勝てない存在なのです。

こうして考えてみると、たかがdirifyと言えども奥が深いですよね。このエントリでいずれ日本語ユーザ向けにもう少しましなdirifyを作って公開したいと思いますが、時間がないのでもう少し先になりそうです。

2005-06-13追記:
私が普段使っているdirifyアルゴリズムを公開しておきます。MT3.17以降用のdirifyです。HTML Entitiesを除去するまではMTオリジナルのものと共通で、その後以下の変換を行っています。

  • 数字・アルファベットを除く文字を「_」に変換する。
  • 先頭および末尾の「_」を除去する。
  • 連続する「_」を一個の「_」に変換する。
sub iso_dirify {
    my $s = $_[0];
    require MT;
    if (MT::ConfigMgr->instance->DefaultLanguage eq 'ja') {
        $s = MT::I18N::encode_text($s, undef, 'euc-jp');
    } else {
        $s = convert_high_ascii($s);  ## convert high-ASCII chars to 7bit.
    }
 
    $s = lc $s;                   ## lower-case.
    $s = remove_html($s);         ## remove HTML tags.
    $s =~ s!&[^;\s]+;!!g;         ## remove HTML entities.
    $s =~ s![^\w\s]!!g;           ## remove non-word/space chars.
    $s =~ tr! !_!s;               ## change space chars to underscores.
    $s =~ s![^\w]!_!g;
    $s =~ s/(^_+|_+$)//g;
    $s =~ s!_+!_!g;
    $s;
}
 
sub utf8_dirify {
    my $s = $_[0];
    $s = xliterate_utf8($s);      ## convert two-byte UTF-8 chars to 7bit ASCII
    $s = lc $s;                   ## lower-case.
    $s = remove_html($s);         ## remove HTML tags.
    $s =~ s!&[^;\s]+;!!g;         ## remove HTML entities.
    $s =~ s![^\w\s-]!!g;           ## remove non-word/space chars.
    $s =~ tr! !_!s;               ## change space chars to underscores.
    $s =~ s![^\w]!_!g;
    $s =~ s/(^_+|_+$)//g;
    $s =~ s!_+!_!g;
    $s;
}

Oct 26, 2004

すぐに納得してしまう名古屋人

19年間岐阜県(の愛知県との県境地域)に生まれ育った私はもちろん中日ドラゴンズファンである。

また日本一を逃したわけだが、そんな私の口から出たのは「やっぱりねー。」という言葉でしかない。なぜだか悔しいとは思わない。74年、82年、88年、99年に優勝した後日本一を逃した時も、オリンピックをソウルにかっさらわれたときも、「やっぱりねー。」とちょっと残念がった後、「しゃーないがねー。まぁえーがねー。」とすぐに納得してしまうのが名古屋人なのである。名古屋商法を挙げるまでもなく、名古屋の人はおまけのないものには興味がない。「○○になれなかった」ことで逃した利益に拘るよりは次の獲物(例えば、開店するレストランの景品や生花)を狙うというまことに前向きかつ賢明な人々なのである。

そもそも名古屋の人は、プロ野球は6チームでやるのだから6年に一度優勝すれば十分と考えている。今回の優勝(30年で5回優勝ということは平均を達成しとるってことだがねー。横浜をみてみー。)だけで十分満足、満腹なのである。選手の名前だってそれほど熱心に覚えるわけではないし(ゲーリー・レーシッチがゲーリーの本名であることをわざわざ覚えている人の方が稀、その代わりに藤王康晴やら高橋尚子やらと同じ高校を卒業した従兄弟がいるなどという益体もないことは案外話したがる)、5点差がつけばそれが3回裏であってもそれ以上野球中継を見ることもない。日本シリーズ第2戦の逆転勝利を見逃した人も当然、非常に多い。事実、私自身見逃した。

しかも今回はこの名古屋人気質を補強する強い要因もある。それは「たとえ日本一になったとしても新潟中越地震による自粛で優勝セールがない、あったとしても著しく規模が縮小するだろう」ということ。日本一になっても「しゃーないがねー」ということなのである。バリバリ負け惜しみのような気もするが、これが名古屋近辺の正しい「負け惜しみ方」なのである。

そんな私は、今回は新潟中越地震に(名古屋人の嫌いな)寄付をしようと思う。

Oct 22, 2004

サブカテゴリー機能について考えてみた。

「MT 3.1では、エントリの存在するカテゴリーしか再構築しません。」

何というか、実に合理的な仕様のように思えます。ところがサブカテゴリー機能が絡むと実に複雑な状況が発生します。つまり、「あるカテゴリーに属するサブカテゴリにエントリが追加されたとき、再構築されるのはサブカテゴリーのみでその親カテゴリーは再構築されない」のです。

この問題は標準のテンプレートでは顕在化しません。しないと言わないまでも少なくとも顕在化しにくいです。

問題点の説明

ここではこの問題がどのような事態を引き起こすかということをもう少し考えてみたいと思います。

標準のカテゴリーアーカイブでは、MTEntriesというコンテナタグでカレントカテゴリーに属するエントリーのリストアップを行っています。MT 3.1ではこれに加えてMTEntriesWithSubCategoriesというコンテナタグが用意されており、その機能はカレントカテゴリに加えてそのサブカテゴリーに属するエントリーをリストアップするというなかなか便利なものです。このタグと前述の再構築規則を組み合わせると、サブカテゴリーにエントリーが追加され、そのサブカテゴリーのアーカイブの再構築は行われますが、それを包含するはずの親カテゴリーのアーカイブの方には反映されない(再構築されない)ということが起きます。

また、エントリーの存在しないカテゴリーも当然存在し得ます。あるカテゴリーにサブカテゴリーを用意し、サブカテゴリーにのみエントリーを追加したとします。そうすると前述の規則に従って親カテゴリーのアーカイブがそもそも生成されない()という現象が観測されるはずです。

このことは例えば、以下のようにカテゴリーアーカイブごとにカテゴリーナビゲーション機能を付加させたいユーザには不評でしょう。

<div class="content">
 
<h2>Parent Categories</h2>
<ul>
<MTParentCategories exclude_current="1">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>">
<MTCategoryLabel></a></li>
</MTParentCategories>
</ul>
 
<h2>Sub Categories</h2>
<MTSubCategories>
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>">
<MTCategoryLabel></a>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
 
<MTEntries>
<$MTEntryTrackbackData$>
 
...
 
</MTEntries>
</div>

解決方法

まず、こうした瑕疵というか仕様が目立ちにくいようにエントリーの存在しないカテゴリーへのリンクを作らない、MTEntriesWithSubCategoriesを使わない、という後ろ向きの解決方法があります。例えば、上記のParent Categoriesの例だと以下のように修正することで少なくとも存在しないアーカイブへのリンクを避けられます。

<h2>Parent Categories</h2>
<ul>
<MTParentCategories exclude_current="1">
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>">
<MTCategoryLabel></a></li>
<MTElse>
<li><MTCategoryLabel></li>
</MTElse>
</MTIfNonZero>
</MTParentCategories>
</ul>

もうひとつはカテゴリーアーカイブの再構築時にその親カテゴリーを遡って再構築するようにMT自体を変更するという方法です。あまりテストしていませんが、以下のようにコードを追加すればよいでしょう。

どうも微妙に不具合がある様子なので公開停止。

Oct 20, 2004

Movable Type 3.11 日本語版・修正案

このエントリでは、Movable Type 3.11 日本語版の修正案と未解決の問題点をリストアップしていきます。

今のところ、以下の点に気が付いています。他にも気が付いた問題点やその解決法があったらコメントやトラックバックしていただけると幸いです。

ユーザーインタフェース関連の問題

  1. 管理画面の左上のロゴのリンク先がAdminScriptの指定に関わらず、mt.cgiに固定されている。
  2. 管理画面のMovable Typeニュースのリンクが「http:///?v=3.11-ja」となる(CHOU-FLEURさんからTrackbackいただきました)。

スタティック・ページ(Perl)関連の問題

  1. MTSubCategoriesの中でMTCategoryCountを用いると公開状態でないエントリーも数え上げてしまう。
  2. mt-comments.cgiが生成するプレビューページでMTIfAllowCommentHTMLが常に真になる。

ダイナミック・パブリッシング(PHP)関連の問題

  1. コメントの設定で「TypeKeyからメールアドレスを取得する」にチェックを入れても有効にならない。
  2. CGIPathの末尾に「/」がない場合、MTRemoteSignInLink、MTRemoteSignOutLinkが不正なものになる。
  3. MTIncludeを使ってファイルをインクルードする場合、フルパスを指定する必要がある。
  4. MTArchiveLinkでarchive_typeオプションが無視される
  5. MTEntryLink、MTEntryPermaLinkがアーカイブの設定によっては不正なURLを返す
  6. MTCalendarIfTodayが機能しない。
  7. コメントの設定で「URLを自動的にリンクにする」にチェックを入れても有効にならない。
  8. 日付アーカイブでMTEntryCategoryが不正なものになる。
  9. 「改行を変換する」がエントリやコメントなどに設定されているとき、<dl>~</dl>まわりに余分な改行が入る。

仕様・振る舞いの改善に関する提案

  1. 前々から気が付いてはいたが、dirifyの振る舞いが日本語環境に適していない。
  2. 子カテゴリーにエントリーを追加しても親カテゴリーアーカイブが再構築されない。親カテゴリーにエントリーが一個もないと親カテゴリーアーカイブが生成されない。

以下はそれぞれの問題の説明と(可能であれば)修正方法を述べます。

ユーザーインタフェース関連の問題

管理画面の左上のロゴのリンク先がAdminScriptの指定に関わらず、mt.cgiに固定されている

これは本家のバグトラックシステムで何度か指摘していますが、直してもらえない問題の一つです。lib/MT/App.pmのsub mt_uriがリンク先のURLを生成していますが、「mt.cgi」という名前がhard-codedされています。そのため、mt.cgiの名前を変更すると、mt.cfgでAdminScriptにそのファイル名を指定してあっても、管理画面の左上のロゴのリンク先がmt.cgiのままになります。

以下のように修正すれば、AdminScriptで指定した名前が使われます。

--- lib/MT/App.pm.bak 2004-10-13 18:00:46.000000000 +0900
+++ lib/MT/App.pm 2004-10-20 18:20:30.977192296 +0900
@@ -543,7 +543,7 @@
 
 sub uri { $_[0]->path . $_[0]->script }
 
-sub mt_uri { $_[0]->path . 'mt.cgi' }
+sub mt_uri { $_[0]->path . MT::ConfigMgr->instance->AdminScript }
         # mt_uri refers to mt's script even if we're in a plugin.
 
 sub path_info {

管理画面のMovable Typeニュースのリンクが「http:///?v=3.11-ja」となる

CHOU-FLEUR-DESIGN BLOG : MT3.11のバグ?で解決方法が示されています。

スタティック・ページ(Perl)関連の問題

以下ではスタティック・ページに限らず、Movable TypeのPerlモジュールが引き起こす問題について述べます。

MTSubCategoriesの中でMTCategoryCountを用いると公開状態でないエントリーも数え上げてしまう

静的に生成されるアーカイブにおいて、MTCategoryCountをMTSubCategoriesの中で用いると、「公開」状態でない「下書き」、「指定日」のエントリーも含めた値を返してしまいます。以下のように修正することで公開状態のエントリーのみの個数を正しく返すようになります。

--- lib/MT/Template/Context.pm.bak 2004-10-18 14:50:43.000000000 +0900
+++ lib/MT/Template/Context.pm 2004-10-24 13:12:40.075911264 +0900
@@ -2284,8 +2284,11 @@
             '<$MTCategoryCount$>' ));
     my($count);
     unless ($count = $ctx->stash('category_count')) {
-        require MT::Placement;
-        $count = MT::Placement->count({ category_id => $cat->id });
+ my @args = ({ blog_id => $ctx->stash ('blog_id'),
+        status => MT::Entry::RELEASE() },
+      { 'join' => [ 'MT::Placement', 'entry_id',
+      { category_id => $cat->id } ] });
+ $count = scalar MT::Entry->count(@args);
     }
     $count;
 }

mt-comments.cgiが生成するプレビューページでMTIfAllowCommentHTMLが常に真になる。

コメント・プレビュー画面などmt-comments.cgiが生成するページでMTIfAllowCommentHTMLがコメントの設定に関わらず常に真になります。コメント・プレビュー、コメント・エラーなどのテンプレートでMTCommentFieldsタグを使っている場合には顕在化しません。

以下の修正を行うとこの不具合が直ります。

--- lib/MT/App/Comments.pm.bak 2004-10-19 17:36:02.000000000 +0900
+++ lib/MT/App/Comments.pm 2004-11-24 18:43:21.756357136 +0900
@@ -924,7 +924,8 @@
     }
     require MT::Blog;
     my $blog = MT::Blog->load($entry->blog_id);
-    my %cond = (IfRegistrationRequired => !$blog->allow_unreg_comments,
+    my %cond = (IfAllowCommentHTML => $blog->allow_comment_html,
+                IfRegistrationRequired => !$blog->allow_unreg_comments,
                 IfCommentsAllowed => $blog->allow_reg_comments
                                        || $blog->allow_unreg_comments,
                 IfNeedEmail => $blog->require_comment_emails);

ダイナミック・パブリッシング(PHP)関連の問題

以下ではダイナミック・パブリッシング時に発生する問題を述べています。機能の不具合やスタティック・ページとの動作の(不適切な)相違を取り上げています。

コメントの設定で「TypeKeyからメールアドレスを取得する」にチェックを入れても有効にならない

コメントの設定で「TypeKeyからメールアドレスを取得する」にチェックを入れても、ダイナミック・パブリッシング時にはRemoteSignInLinkの生成するTypeKeyサインイン用のURLに「&need_email=1」が追加されません。このため、「TypeKeyからメールアドレスを取得する」ことができません。

以下のように修正するとよいでしょう。

--- php/lib/function.MTRemoteSignInLink.php.bak 2004-09-22 15:40:55.000000000 +0900
+++ php/lib/function.MTRemoteSignInLink.php 2004-10-20 18:25:29.976737456 +0900
@@ -25,7 +25,7 @@
               ($args['static'] ? 'static=1' : 'static=0') .
               '%26entry_id=' . $entry['entry_id'];
     return $ctx->mt->config['SignOnURL'] .
-        ((isset($blog['require_comment_emails']) && $blog['require_comment_emails']) ? '&need_email=1' : '') .
+        ((isset($blog['blog_require_comment_emails']) && $blog['blog_require_comment_emails']) ? '&need_email=1' : '') .
         '&t=' . $token .
         '&v=' . $ctx->mt->config['TypeKeyVersion'] .
         '&_return=' . $return;

CGIPathの末尾に「/」がない場合、MTRemoteSignInLink、MTRemoteSignOutLinkが不正なものになる

mt.cfgで設定しているCGIPathの末尾に「/」がない場合、ほとんどのMTタグでは「/」を補って処理してくれます。しかし、例外的にダイナミック・パブリッシング時のMTRemoteSignInLinkとMTRemoteSignOutLinkでは補ってくれません。以下のように修正するとよいでしょう。

--- php/lib/function.MTRemoteSignInLink.php.bak 2004-09-22 15:40:55.000000000 +0900
+++ php/lib/function.MTRemoteSignInLink.php 2004-10-24 00:47:48.954994344 +0900
@@ -20,7 +20,11 @@
         }
     }
     $entry = $ctx->stash('entry');
-    $return = $ctx->mt->config['CGIPath'] . $ctx->mt->config['CommentScript'] .
+    $path = $ctx->mt->config['CGIPath'];
+    if (!preg_match('!/$!', $path)) {
+        $path .= '/';
+    }
+    $return = $path . $ctx->mt->config['CommentScript'] .
               '%3f__mode=handle_sign_in%26' .
               ($args['static'] ? 'static=1' : 'static=0') .
               '%26entry_id=' . $entry['entry_id'];
--- php/lib/function.MTRemoteSignOutLink.php.bak 2004-09-22 15:40:55.000000000 +0900
+++ php/lib/function.MTRemoteSignOutLink.php 2004-10-24 00:47:47.094277216 +0900
@@ -3,7 +3,11 @@
     // status: complete
     // parameters: none
     $entry = $ctx->stash('entry');
-    return $ctx->mt->config['CGIPath'] . $ctx->mt->config['CommentScript'] .
+    $path = $ctx->mt->config['CGIPath'];
+    if (!preg_match('!/$!', $path)) {
+        $path .= '/';
+    }
+    return $path . $ctx->mt->config['CommentScript'] .
         '?__mode=handle_sign_in&' .
         ($args['static'] ? 'static=1' : 'static=0') .
         '&entry_id=' . $entry['entry_id'] . '&logout=1';

MTIncludeを使ってファイルをインクルードする場合、フルパスを指定する必要がある

テンプレートの中で<$MTInclude file="filename"$>のように書いていたとします。

スタティック・ページの場合、(1) 絶対パスで指定されたfilename、(2) ローカル・サイト・パス/filename、(3) ローカル・アーカイブ・パス/filename、の順に探して最初に見つかったものをインクルードします。一方、ダイナミック・パブリッシングの場合には(1)しか探しません。したがって、(2)や(3)のファイルがインクルードされることを期待してもうまくいきません。

以下のように変更すると、ダイナミック・パブリッシング時にまず(1)を探し、なければ(2)を探すようになります。ダイナミック・パブリッシングでは現状ローカル・アーカイブ・パスの情報を内部的に保持していないので、スタティック・ページとまったく同じ機能にすることはできません。おそらくその必要もないでしょう。

--- php/lib/function.MTInclude.php.bak 2004-09-22 15:40:55.000000000 +0900
+++ php/lib/function.MTInclude.php 2004-10-22 16:30:38.303009000 +0900
@@ -25,7 +25,18 @@
                 $contents = @file($file);
                 $tmpl = implode('', $contents);
             } else {
-                return $ctx->error("Could not open file '$file'");
+                $blog = $ctx->stash('blog');
+                $path = $blog['blog_site_path'];
+                if (!preg_match('!/$!', $path))
+                    $path .= '/';
+                $path .= $file;
+                if (is_file($path) && is_readable($path)) {
+                    $contents = @file($path);
+                    $tmpl = implode('', $contents);
+                }
+                else {
+                    return $ctx->error("Could not open file '$file'");
+                }
             }
             if ($ctx->_compile_source('evaluated template', $tmpl, $_var_compiled)) {
                 $_include_cache['file:'.$file] = $_var_compiled;

MTArchiveLinkでarchive_typeオプションが無視される

スタティック・ページでは、MTArchiveLinkは、archive_typeオプションがあればその指定に従ったアーカイブのURL、なければカレントコンテキストのarchive_typeに従ったアーカイブのURLを生成します。一方、ダイナミック・パブリッシングでは、archive_typeオプションが無視され、カレントコンテキストのarchive_typeに従ったアーカイブのURLしか生成されません。

以下のように修正することで正常に動作するようになります。

--- php/lib/function.MTArchiveLink.php.bak 2004-09-22 15:40:55.000000000 +0900
+++ php/lib/function.MTArchiveLink.php 2004-11-02 21:35:17.260184600 +0900
@@ -6,7 +6,7 @@
     }
 
     $blog = $ctx->stash('blog');
-    $at = $ctx->stash('current_archive_type');
+    $at = isset($args['archive_type']) ? $args['archive_type'] : $ctx->stash('current_archive_type');
     $ts = $ctx->stash('current_timestamp');
     if ($at == 'Monthly') {
          $ts = substr($ts, 0, 6) . '01000000';

MTEntryLink、MTEntryPermaLinkがアーカイブの設定によっては不正なURLを返す

ダイナミック・パブリッシングにすると、MTCalendarに囲まれたMTEntryLinkが特定のすべて同じ日付のアーカイブのURLを「誤って」生成する、という問題だと思っていましたが、もっと一般的な問題があるようです。MTCalendarの中で使われるMTEntryLinkに関しては、tentativeな回避方法をOgawa::Buzz: ダイナミック・パブリッシング時のカレンダーの不具合をアレする。で述べています。

(1) archive_typeオプションにIndividual, Category以外が指定されている場合、または (2) archive_typeオプションを設定せず、かつアーカイブの設定の「優先するアーカイブのタイプ」でIndividual、Category以外を選択している場合にMTEntryLink、MTEntryPermaLinkが誤ったURLを返す可能性があります。php/lib/mtdb_base.phpのentry_linkという関数がまともに実装されていないのが原因です。

以下のように変更すれば、期待される動作になります。

--- php/lib/mtdb_base.php.bak 2004-10-12 18:57:57.000000000 +0900
+++ php/lib/mtdb_base.php 2004-11-03 06:06:32.474843144 +0900
@@ -177,9 +177,23 @@
                            and templatemap_archive_type='Category'
                            and templatemap_is_preferred = 1";
             } else {
+                $entry = $this->fetch_entry($eid);
+                $ts = $entry['entry_created_on'];
+                if ($at == 'Monthly') {
+                    $ts = substr($ts, 0, 6) . '01000000';
+                } elseif ($at == 'Daily') {
+                    $ts = substr($ts, 0, 8) . '000000';
+                } elseif ($at == 'Weekly') {
+                    require_once("MTUtil.php");
+                    list($ws, $we) = start_end_week($ts);
+                    $ts = $ws;
+                } elseif ($at == 'Yearly') {
+                    $ts = substr($ts, 0, 4) . '0101000000';
+                }
                 $sql = "select fileinfo_url, fileinfo_blog_id
                           from mt_fileinfo, mt_templatemap
                          where fileinfo_templatemap_id = templatemap_id
+                           and fileinfo_startdate = '$ts'
                            and templatemap_archive_type='".$this->escape($at)."'
                            and templatemap_is_preferred = 1";
             }

MTCalendarIfTodayが機能しない

ダイナミック・パブリッシング時に、MTCalendar内で使用できるはずのMTCalendarIfTodayが正常に機能しません。また、カレンダーのパディング部分(MTCalendarIfBlankがTrueになる)で必ずMTIfCalendarTodayがTrueになるという現象が起きます。

以下のように修正するとよいでしょう。

--- php/lib/block.MTCalendar.php.bak 2004-09-22 15:40:54.000000000 +0900
+++ php/lib/block.MTCalendar.php 2004-11-02 15:30:13.888003304 +0900
@@ -49,6 +49,7 @@
         $ctx->stash('cal_pad_end', $pad_end);
         $ctx->stash('cal_days_in_month', $days_in_month);
         $ctx->stash('cal_prefix', $prefix);
+        $ctx->stash('cal_today', $today);
     } else {
         # subseqent iterations:
         $prefix = $ctx->stash('cal_prefix');
@@ -58,6 +59,7 @@
         $days_in_month = $ctx->stash('cal_days_in_month');
         $iter = $ctx->stash('cal_entries');
         $left = $ctx->stash('cal_left');
+        $today = $ctx->stash('cal_today');
     }
     $left or $left = array();
     if ($day <= $pad_start + $days_in_month + $pad_end) {

コメントの設定で「URLを自動的にリンクにする」にチェックを入れても有効にならない。

コメントの設定で「URLを自動的にリンクにする」にチェックを入れても、ダイナミック・パブリッシング時にはMTCommentBodyの生成するコメント本体に含まれるURLをリンクに変換してくれません。

以下のように修正するとよいでしょう。

--- php/lib/function.MTCommentBody.php.bak 2004-09-22 15:40:55.000000000 +0900
+++ php/lib/function.MTCommentBody.php 2004-11-20 23:34:04.530682576 +0900
@@ -4,6 +4,12 @@
     $text = $comment['comment_text'];
 
     $blog = $ctx->stash('blog');
+    if (!$blog['blog_allow_comment_html']) {
+        $text = strip_tags($text);
+        if ($blog['blog_autolink_urls']) {
+            $text = preg_replace('!(http://\S+)!', '<a href="$1">$1</a>', $text);
+        }
+    }
     $cb = $blog['blog_convert_paras_comments'];
     if ($cb == '1' || $cb == '__default__') {
         $cb = 'convert_breaks';

日付アーカイブでMTEntryCategoryが不正なものになる。

日付アーカイブでMTEntryCategoryタグ(エントリのプライマリカテゴリーの名前を返す)を使用すると、すべてのエントリのカテゴリーが同一のものになるという不具合があります。典型的にはテンプレートに以下のように書いていると不具合が確認できます。

<a href="<$MTEntryLink archive_type="Category"$>"><$MTEntryCategory$></a>

修正方法を見つけていません。が、上記のような記述の代わりに下記のように記述すれば問題を回避できます。当然のことですが、この場合はエントリーに付与されているプライマリカテゴリー以外のカテゴリーも列挙されますから、上記とまったく同じ出力結果が得られるわけではありません。

<MTEntryCategories glue=", ">
<a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
</MTEntryCategories>

「改行を変換する」がエントリやコメントなどに設定されているとき、<dl>~</dl>まわりに余分な改行が入る。

以下をエントリ本文に保存したとします。

<dl>
<dt>DDBJ</dt>
<dd>DNA Data Bank of Japan</dd>
</dl>

スタティック・ページではこのまま表示されますが、ダイナミック・パブリッシング時には以下のようにマークアップされるため余分な改行が入ります。

<p><dl><br />
<dt>DDBJ</dt><br />
<dd>DNA Data Bank of Japan</dd><br />
</dl></p>

以下の修正でスタティック・ページと同様のマークアップがなされるようになります。

--- php/lib/MTUtil.php.bak 2004-10-13 14:27:46.000000000 +0900
+++ php/lib/MTUtil.php 2004-11-29 11:41:25.099006392 +0900
@@ -513,7 +513,7 @@
         return '';
     }
     foreach ($paras as $k => $p) {
-        if (!preg_match('/^<\/?(?:h1|h2|h3|h4|h5|h6|table|ol|ul|menu|dir|p|pre|center|form|select|fieldset|blockquote|address|div|hr)/', $p)) {
+        if (!preg_match('/^<\/?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|select|fieldset|blockquote|address|div|hr)/', $p)) {
             $p = preg_replace('/\r?\n/', "<br />\n", $p);
             $p = "<p>$p</p>";
             $paras[$k] = $p;

仕様・振る舞いの改善に関する提案

前々から気が付いてはいたが、dirifyの振る舞いが日本語環境に適していない。

Ogawa::Buzz: dirifyについて考えてみた。に分離して書きました。

子カテゴリーにエントリーを追加しても親カテゴリーアーカイブが再構築されない。親カテゴリーにエントリーが一個もないと親カテゴリーアーカイブが生成されない。

Ogawa::Buzz: サブカテゴリー機能について考えてみた。に分離して書きました。

Movable Type 3.11 日本語版

Movable Type 3.11 日本語版が出ていたようです。最近、日付が変わる前には寝て5時過ぎには起きる、しかも日本シリーズもあるという生活になっているので、見逃していました。

Movable Type 日本語版サイト: Movable Type 3.1日本語版の提供を開始

まずはおめでとうございます。PHP版を含めて日本語化されているようで、まだ全貌はつかめていないのですが、いろいろと試してみようと思います。mtchanges - Movable Typeの更新履歴に名前が載せられていたので何となく恐縮しています。

…などとしおらしいことを言った舌の根も乾かぬうちに突っ込んでおきますが、Six Apart Japanはバージョンストリングをいったいどのように考えているのでしょうか。上記公式サイトでは「3.1日本語版」という表記ですが、システムのバージョンは「3.11-ja」です。しかも、その中身はオリジナル版の「3.12 Release Candidate」より新しいものになっています。おそらくオリジナル版の「3.12」はすぐ出ますが、それは「3.1日本語版」のベースバージョンより多少更新されたものになるでしょう。3.12のコードフィックスを待って日本語版をリリースすればよいのにどうしてこのようなことになるのでしょうか。3.0のときも同じような状況になっていました。

というか3.12も早速出ましたね。「3.1日本語版」のベースバージョン(とおぼしきバージョン)とはほんのわずかの差しかありません。というわけで3.1日本語版は実質3.12の日本語版です。

Movable Type Publishing Platform: Movable Type 3.12 released

さて、3.11英語版に私の暫定日本語化パッチ(Ogawa::Buzz: Movable Type 3.1 and a temporary Japanized patch)を当てて使っていたみなさま、日本語版への移行は簡単です。単純にファイルの入れ替えだけで済みます。どうしてもテンプレートを日本語版と完全に一致させたい場合にはそれなりの手続きが必要になります。

Oct 16, 2004

豪快な祭りが起きているらしい

Web屋さん(Livedoor)が本当にミッションクリティカルなシステムを組むことが可能か、という貴重なproof-of-concept実験。

livedoor FX
livedoorFX辞めたの?
【無稼動】livedoorFX辞めたの?Part2【バグ付】
Apache Tomcat/5.0.28

なぜニュースにならないのかは不明ですが、したらばやblogと違って、現金の動くシステムのトラブルは業務改善、業務停止命令が出るから怖いですね。

でも...とちょっと思うのです。外為の証拠金取引業者は先物取引業なので金融庁の管轄じゃなくて経産省の管轄になるはずで、にも拘らずlivedoor FXをやっているライブドア証券は金融庁の管轄下にあります。とすると、この業者に行政処分を下すのはいったい誰なんでしょうか。

なんだかここにも役所間の綱引きの目がここにもありそうです。先物業者の預託金に欠損がある場合ならともかく、円滑な取引が阻害されていることに対して経産省が注意以上のことができるのでしょうか。今後の動きに注目したいと思います。

Oct 15, 2004

今更ながら流石だよな、陳建一


鉄人 陳建一(本人直筆) 四川担々麺 ドリームファミリー・ケンにトライしてみました。日頃カップ麺に払うべき敬意を持ち合わせていない私でしたがこれからは改めることします。
第一印象は「特製スープ・具入り」って当たり前やんけと突っ込みたくなる陰鬱なパッケージです。ドリームファミリー・ケンは建ちゃんファミリーの会社のようです。普通に中華鍋とか売ってる会社ですね。


うっかり見落としがちなラベルの裏側に詳しい作り方が載っています。湯切り方式・湯切り不要方式の両対応の画期的なシステムが新しいです。乾麺なのに湯切りする意味が本当にあるのかどうかは中国四千年の謎です。


パッケージを開いてみれば中身はこんなに盛り沢山。乾燥具材、特製スープ、芝麻醤、レトルトの具にラー油。数はともかく量がおかしい気がします。四川屋台(大岡山)じゃあるまいし、芝麻醤はこんなにいらないと…。しかし、これも鉄人の心づくしでしょう。


もちろん蓋の上で温めろと言われても、この有様。まったく温まる気配なし。ちなみにラー油とソースはカップの底で温めるのが通と言えましょう。


出来上がり。素晴らしい。芝麻醤もラー油もカップ麺にはあるまじき分量が奢られています。ちゃんとした担々麺になっていて普通にうまいです。カップ麺に多くは求めませんが花椒があればなお良かったに違いありません。

まんまと四川飯店(六本木)に行きたくなった。

MTSetVarBlock Plugin

MT 3.1以降で加わった機能にOn-the-spot Rebuild(と今私が勝手に名前を付けた)機能があります。これは、インデックステンプレートを編集・保存すると、再構築を促す表示がなされ、「その場で」ポップアップウィンドウなしに再構築することができる機能のことです。再構築忘れもないし、それほど手間でもないという、地味ですが...絶妙な機能と言えましょう。

MT 3.0以前では、ポップアップウィンドウが開き、さらに「再構築」を選択しないと再構築できないはずです。この面倒さゆえ、滅多に再構築することのないテンプレート、例えばスタイルシート、に「このテンプレートにリンクするファイル」を指定することで再構築なしに保存だけで済ますという方法がよく知られています。

[the girlie matters] tips and tricks: link that stylesheet

しかし、この方法はad hocなことこの上ありません。なぜならこの方法を使ったテンプレートではMT Tagが使えないからです。もしあなたが「プログラマ」で、かつこんな安易な方法で簡単に対称性を喪失しても構わない、後ろめたさも感じないのでしたら、すぐに廃業をお勧めしますよ。

一方、MT 3.11ではOn-the-spot Rebuild(仮称)が使えますから再構築するのも以前ほど手間ではなくなりました。言い換えると、上の方法に拠ってまでして得る利得が(MT Tagが使えることによる利得に比べて)相対的に小さなものになってしまった、MT Tagが使えないことによる損失が(On-the-spot Rebuildのわずかな手間という損失に比べて)相対的に大きなものになってしまった、と言えます。

というわけで、これからは絶賛On-the-spot Rebuild推進派なのです。スタイルシートのように自動的に更新される必要のないインデックステンプレートに対しては「自動で再構築」オプションをOffにしておくだけで十分です。「ファイルにリンク」するのは止めましょう。

久々のエントリで前置きが長かったですが、ここからが本論です。

スタイルシートでMT Tagが使えるのは意外に便利です。HINAGATA:CSSの@charsetをご確認ください で上ノ郷谷さんが書かれているようにスタイルシートのcharsetの設定に使えるのは言わずもがなですが、例えば以下のようにフォントセットをマクロ変数として定義することでスタイルシートに散らばりがちなfont-familyを統一的に指定することができます。

<$MTSetVar name="defaultFont" value="Verdana, Arial, sans-serif"$>
<$MTSetVar name="headingsFont" value="Georgia, Times, serif"$>
 
body {
 font-family: <$MTGetVar name="defaultFont"$>
 ...
}

同様にfont-size、background-colorなどの指定にも使えるでしょう。特に「色」の指定は「数値による表現」より意味を表す「文字列による表現」の方が分かりやすいような気がするのですが...(それは私がデザイナーではない証左かもしれません)。

ところでこのMTSetVarはVariable TagであってContainer Tagではありません。したがって、定義済みのマクロ変数の値を別のマクロ変数に設定したい(例えば、serifFontに設定したフォントセットをdefaultFontに設定したい)とか、他のMT Tagで生成した文字列をマクロ変数に設定したいとか、そういう当然の需要には応えない半端な仕様になっています。

ではというわけで作ってみました(所要時間約1分)、MTSetVarBlock Plug-in。

mt-setvarblock.pl

0.01(2004.10.15): First Release

下のような感じで使えます。

<$MTSetVar name="defaultFont" value="Georgia, Times, serif"$>
<MTSetVarBlock name="bodyFont">
 <$MTGetVar name="defaultFont"$>
</MTSetVarBlock>
 
body {
 font-family: <$MTGetVar name="bodyFont"$>
 ...
}

もちろん、MTSetVarBlockのcontentには何でも書けますから、他にも用途は色々考えられます。例えば、しばしば複雑になりがちなテンプレートを構成要素に分解してテンプレートモジュール化し、MTIncludeしているような人にも役に立つでしょう。MTSetVarBlockでモジュールをwrapしてマクロ化しておけば、いちいちモジュールごとにテンプレートにする必要はなく、単一のグローバルテンプレートだけを管理すればよいことになります。

具体的には、以下のようなテンプレートモジュールを作っておきます。名前は仮にGlobalTemplateとしておきます。

<MTSetVarBlock name="module1">
... the content of module1 ...
</MTSetVarBlock>
<MTSetVarBlock name="module2">
... the content of module2 ...
</MTSetVarBlock>
...

これを利用するインデックステンプレート、アーカイブテンプレートでは以下のようにすればよいでしょう。

<!--まず最初にGlobalTemplateを読み込む-->
<$MTInclude module="GlobalTemplate"$>
...
<!--module1の定義を展開する-->
<$MTGetVar name="module1"$>
...
<!--module2の定義を展開する-->
<$MTGetVar name="module2"$>
...

念のため、この方法ではマクロの中身は定義時にEagerに評価されます(上記の例ではMTIncludeの時点)。したがって定義時に「式」とそれを計算するための「環境(値の束縛)」が必要になり、一般的な意味での(展開された先の環境を用いて式の値が計算される)マクロとは異なります。この(プログラミング言語を大学で教わった人向けの、不親切な)説明が理解できない場合には、例えばMTEntriesの中身だけをこの方法でマクロ化することはできないけれども、MTEntriesごとマクロ化することはできる、ということだけは何となく覚えておいてください。

Oct 7, 2004

ネコ温度計、イイッ!

いいね。和むよね。
FLASH版をスクリーンセーバー代わりに使ってみています。
さらにMusashimaru(こうさぎ)をShockwave版にリプレースしてみました。

ネコ温度計
oshige index: ネコ温度計HP

今私の生活は、深夜TWENTY-FOUR(もう爆弾は処理されてしまったのでどうでもいいって言えばどうでもいいわけですが。Kiefer SutherlandとSimon Le Bonは似ている、ということに我が家では…なっています。)を観ながらプログラミングというパターンに嵌っていて、とても荒んでいます。PHP Programmingを三年ぶりくらいにやってみているわけですが、完全に忘れてます…。まあじき思い出しますが。

About Me

My Photo

つくばで働く研究者LV15

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com