Showing posts with label Category. Show all posts
Showing posts with label Category. Show all posts

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


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

Oct 27, 2005

Entry Category Entries Plugin

現在のエントリーのプライマリカテゴリーに属するエントリーをリストアップするMovable Typeプラグインを公開します。

EntryCategoryEntries_Plugin - ogawa - Google Code

このプラグインは、現在のエントリーのプライマリカテゴリーをカテゴリーに設定しているエントリーをリストアップするMTEntryCategoryEntriesコンテナタグを追加するものです。このコンテナタグは、エントリーコンテキスト、すなわちMTEntriesコンテナの内部、もしくは個別エントリーアーカイブで利用できます。

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自体を変更するという方法です。あまりテストしていませんが、以下のようにコードを追加すればよいでしょう。

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