movabletypeで特定のカテゴリに含まれる記事に対して処理をする

下記の例ではspecialというベースネームを持つカテゴリに含まれる記事に対して★を出力している。

記事が複数カテゴリのカテゴリに所属していて、かつそれが何番目であるかも未確定なので、まずは所属カテゴリのベースネームをアンダースコアを挟んで繋げておいてからlikeで検索をする。likeの部分には正規表現が使えるので、いろいろ応用ができそう。

<MTIfNonEmpty tag="EntryCategory">

<MTIgnore>//basenameを繋げて出力</MTIgnore>
<MTSetVarBlock name="category_basename">
<MTEntryCategories><$MTCategoryBasename$>_</MTEntryCategories>
</MTSetVarBlock>

<MTIgnore>//特定の文字列が含まれる場合(正規表現可)に出力</MTIgnore>
<MTIf name="category_basename" like="special"><$MTGetVar name="category_basename"$>★</MTIf>

</MTIfNonEmpty>

すぐに忘れそうなので備忘録代わりに。

テンプレートタグリファレンス

MovableType5でインデックスページからアーカイブページの該当箇所へリンクする

MovableType5でインデックスページから「続きはこちら」をクリックした際にページの詳細ではなく、カテゴリ別(月別等)アーカイブページの該当箇所へリンクしたい。

通常であれば、記事のid名がentry-1となるので、ページ内リンクを利用して/archives.php#entry-1などと書けば解決する。しかし「静的ページ用ページ分割プラグイン:PageBute」を利用してページ分割を行っているとファイル名それ自体が異なるためこの方法はそのままでは使用できない。

そこで、記事の番号をmt:Entries内で数え上げて、その記事が分割されたページのうちの何ページ目に含まれるのかを計算する。

PageButeを利用すると、1ページ目はindex.phpとなり、2ページ目はindex_n.php(nはページ数)となるので次のように書く。

[php]

0







index.php


index_.php

<$mt:EntryTitle$>

Movabletypeのカスタムフィールドの並べ替え

テンプレート等で利用するカスタムフィールドの並べ替えが出来ないかと探していたところ下記を見つけた。いったん別のハッシュにキーを付与しながら代入し、あらためて付与したキーによってソートして出力をするよう。備忘録代わりに。

参照元

MovableTypeで「~」が化ける

MTの記事中に「~」を含めると、再構築した際に「?」となって正常に表示されないことがある。これはDBとMTとの文字コード解釈の違いによるものだそうで、根本的にはDBもしくはMTで文字コードをどちらかに合わせてあげれば良いが、そんな時間もないときには数値文字参照で済ます。

[php]
10進数: &#65374;
16進数: &#xff5e;
[/php]

いろいろと解決方法はあるみたい。

MT5を1つのDBへ複数インストールする

レンタルサーバーの都合により、複数(今回は二つ)のMovabletypeを1つのDBへインストールする必要があったので、その作業メモ。

通常のインストール(一つ目)であれば、DBへ登録されるテーブルの名前は接頭辞「mt_」を付けたものとなる(例えばmt_tablename)。そこへ二つ目のMTをインストールしようとするとテーブル名が重複するためにインストールエラーとなる。従って、二つ目以降のインストールを成功させるためには接頭辞の変更がポイントとなる。

しかしながらMTの場合、インストールウィザード上で接頭辞を変更することができないため、ソースファイルに手を加える必要がある。具体的には下記の三つのファイルを編集する。いずれも、「mt_」の部分を「mt2_」へと変更している。

環境は次の通り。

  • MySQL5

  • MovableType5.01

変更するファイル

  • /lib/MT/ObjectDriver/DDL/mysql.pm
  • /lib/MT/ObjectDriver/Driver/DBD/Legacy.pm
  • /lib/MT/ObjectDriver/Driver/DBI.pm

変更点:/lib/MT/ObjectDriver/DDL/mysql.pm

[php]
while (my $row = $sth->fetchrow_hashref) {
my $key = $row->{‘Key_name’};
next unless $key =~ m/^(mt2_)?\Q$field_prefix\E_/;
$key = ‘mt2_’ . $key unless $key =~ m/^mt2_/;
my $type = $row->{‘Index_type’};
# ignore fulltext or other unrecognized indexes for now
next unless $type eq ‘BTREE’;
my $seq = $row->{‘Seq_in_index’};
my $col = $row->{‘Column_name’};
my $non_unique = $row->{‘Non_unique’};
my $null = $row->{‘Null’};
my $size = $row->{‘Sub_part’};
$key =~ s/^mt2_\Q$field_prefix\E_//;
$col =~ s/^\Q$field_prefix\E_//;
$unique->{$key} = 1 unless $non_unique;
$sizes->{$key}->{$col} = $size if defined $size;
my $idx_bag = $bags->{$key} ||= [];
$idx_bag->[$seq – 1] = $col;
}
[/php]

変更点:/lib/MT/ObjectDriver/Driver/DBD/Legacy.pm

[php]
sub db_column_name {
my $dbd = shift;
my ($table, $col) = @_;
$table =~ s{ \A mt2_ }{}xms;
return join(‘_’, $table, $col);
}
[/php]

変更点:/lib/MT/ObjectDriver/Driver/DBI.pm

[php]
sub init {
my $driver = shift;
my (%param) = @_;
$param{prefix} ||= ‘mt2_’;
$driver->SUPER::init(%param);
my $opts = $driver->connect_options || {};
require MT;
my $mt = MT->instance;
my $cfg = $mt->config;
$opts->{RaiseError} = $cfg->DBIRaiseError;
$driver->connect_options($opts);
$driver;
}
[/php]

※/lib/MT/ObjectDriver/DDL/mysql.pmについては必要かどうかは疑わしいが、とりあえず。。。

参考

MT5でCan’t load error templateエラー

Movabletype5のインストール時に下記のエラーに遭遇する。インストール作業なんて何度もしているのでおかしいな、おかしいなといろいろ調べたところ、単純にtmplディレクトリがアップされていないだけだった。10分は無駄にした。。。

Can't load error template; got error 'テンプレート「error.tmpl」のロードに失敗しました。
'. Giving up. Original error was:テンプレート「start.tmpl」のロードに失敗しました。

MovableTypeにてカテゴリの一括登録をしたい

タイトルの必要に迫られ便利なプラグインを探してみるも、なかなか見つからなかったのでDB(PostgreSQL)への直接入力を行ってみた。MTのバージョンは4.27。

まずはカテゴリテーブルの調査から。カテゴリ関連で使用されているのは「mt_category」テーブル。登録後に運用をしてみたところ、ユーザーID等がある時点において正しく設定がされていれば特に問題はなさそうなので、このテーブルに絞って設定を行う。

category_id カテゴリID ※1
category_allow_pings トラックバックの許可 0(未許可)
category_author_id 作成者 1(管理者)
category_basename 識別名 ※2
category_blog_id 所属ブログのID ※3
category_class カテゴリのクラス category
category_created_by 作成者ID 1(管理者)
category_created_on 作成日 2010-01-01 00:00:00
category_description カテゴリの説明 空白
category_label カテゴリのラベル ※4
category_modified_by 更新者 1(管理者)
category_modified_on 更新日 2010-01-01 00:00:00
category_parent 親のカテゴリID ※5
category_ping_urls トラックバックURL 空白
category_order_number カテゴリの並び順 ※6

この中で、気をつけなければならないのは※1~※6の項目。

※1 カテゴリID
キーなので、テーブル内で重複しないような番号を設定する。
※2 識別名
同一のcategory_blog_id内で重複しないよう設定する。category_blog_idが違えば同じ名前でも問題ない。
※3 所属ブログのID
所属するブログのIDを設定する。
※4 カテゴリのラベル
自由に設定して構わない。
※5 親のカテゴリID
ここに設定したIDが親のIDとなる。存在するcategory_idを設定するか、0を設定してトップカテゴリとする。
※6 カテゴリID
同一のcategory_blog_id内で重複しないよう設定する。category_blog_idが違えば同じ名前でも問題ない。

次に、上記の情報を元にSQL文を作成する。サンプルとして、次のようなカテゴリを考える。

  • 野菜
    • じゃがいも
    • にんじん
    • きゅうり
  • 果物
    • りんご
    • すいか
    • みかん
  • 穀物
    • いね
    • まめ
    • とうもろこし

SQL文は次のようにする。

INSERT INTO mt_category VALUES (1,0,1,'yasai',1,'category'::character varying,1,'2010-01-01 00:00:00','','野菜',1,'2010-01-01 00:00:00',0,'',1);
INSERT INTO mt_category VALUES (2,0,1,'kudamono',1,'category'::character varying,1,'2010-01-01 00:00:00','','果物',1,'2010-01-01 00:00:00',0,'',2);
INSERT INTO mt_category VALUES (3,0,1,'kokumotsu',1,'category'::character varying,1,'2010-01-01 00:00:00','','穀物',1,'2010-01-01 00:00:00',0,'',3);
INSERT INTO mt_category VALUES (4,0,1,'yasai1',1,'category'::character varying,1,'2010-01-01 00:00:00','','じゃがいも',1,'2010-01-01 00:00:00',1,'',1);
INSERT INTO mt_category VALUES (5,0,1,'yasai2',1,'category'::character varying,1,'2010-01-01 00:00:00','','にんじん',1,'2010-01-01 00:00:00',1,'',2);
INSERT INTO mt_category VALUES (6,0,1,'yasai3',1,'category'::character varying,1,'2010-01-01 00:00:00','','きゅうり',1,'2010-01-01 00:00:00',1,'',3);
INSERT INTO mt_category VALUES (7,0,1,'kudamono1',1,'category'::character varying,1,'2010-01-01 00:00:00','','りんご',1,'2010-01-01 00:00:00',2,'',1);
INSERT INTO mt_category VALUES (8,0,1,'kudamono2',1,'category'::character varying,1,'2010-01-01 00:00:00','','すいか',1,'2010-01-01 00:00:00',2,'',2);
INSERT INTO mt_category VALUES (9,0,1,'kudamono3',1,'category'::character varying,1,'2010-01-01 00:00:00','','みかん',1,'2010-01-01 00:00:00',2,'',3);
INSERT INTO mt_category VALUES (10,0,1,'kokumotsu1',1,'category'::character varying,1,'2010-01-01 00:00:00','','いね',1,'2010-01-01 00:00:00',3,'',1);
INSERT INTO mt_category VALUES (11,0,1,'kokumotsu2',1,'category'::character varying,1,'2010-01-01 00:00:00','','まめ',1,'2010-01-01 00:00:00',3,'',2);
INSERT INTO mt_category VALUES (12,0,1,'kokumotsu3',1,'category'::character varying,1,'2010-01-01 00:00:00','','とうもろこし',1,'2010-01-01 00:00:00',3,'',3);

このSQL文を発行してデータを登録し、さらにシーケンスのmt_category_idの値を最終値(今回であれば12)に設定する。MySQLの場合にはcategory_idにauto_incrementを付けておけばいいのかな。

以上で、カテゴリの一括登録ができる。あとはSQL文を上手に複製していけば良い。ちなみに、この方法にてブログ1つあたり1,000以上、全体で数千のカテゴリを登録してみたが、今のところは正常に動いている様子。ただ、再構築に非常に時間がかかるので、せめてアーカイブだけでもダイナミック・パブリッシングにしたほうが良いと思われる。

mt_dpcacheに関するエラー

H.FujimotoさんのPerl版ダイナミック・パブリッシング(MT4用)を利用した際にキャッシュを有効にしてページにアクセスをすると次のエラーが出力された。つまるところ、キャッシュが動いていない。

キャッシュの検索に失敗しました sql = select * from mt_dpcache where dpcache_uri・・・

まずはテーブルの中身を、と思いphpPgAdminにてDBを調べてみたところ、なんと「mt_dpcache」テーブルがない。インストール時に作られなかったのか、何らかのエラーにより消失したのかは不明だけれど、DBに登録がないことにはどうしようもない。

いろいろと調べた結果、「せんむの技術ブログ」さまの記事にてに該当テーブルを作成すると動くとの情報を見つける。そちらを参考にさせていただき、PostgreSQL用のSQLを実行してテーブルを作成したところ、無事に動くようになった。

実行したSQLは下記の通り。

CREATE TABLE mt_dpcache (
"dpcache_id" INTEGER NOT NULL PRIMARY KEY,
"dpcache_blog_id" INTEGER NOT NULL,
"dpcache_modified_on" timestamp without time zone NOT NULL,
"dpcache_pagefile" VARCHAR(20) NOT NULL,
"dpcache_pagesize" INTEGER NOT NULL,
"dpcache_uri" VARCHAR(255) NOT NULL
)

上記の問題とは直接の関係はないけれど、PostgreSQLのINTEGERには引数は必要ない(?)様子。しばらく悩みました。PostgreSQLを使うのは初めてで。。。

MTで管理画面の記事のソート順を変える

MovableType4.2のブログ一覧ページで、その並び順を変更したいという要望があった。通常はauthored_on、つまり作成日なのだが、それを編集日でソートしたいとのこと。

タグを頼りに、ソースコードをひっくり返すと、それっぽい箇所を発見。次のように修正したところ、編集日によってソートすることができた。

修正箇所は/lib/MT/CMS/Entry.pmの500行目付近。

修正前

sub list {
略
my %arg;
$arg{'sort'} = $type eq 'page' ? 'modified_on' : 'authored_on';
$arg{direction} = 'descend';
my $filter_key = $q->param('filter_key') || '';
my $filter_col = $q->param('filter')     || '';
my $filter_val = $q->param('filter_val');
my $iter_method;
my $total;
略

修正後

sub list {
略
my %arg;
#$arg{'sort'} = $type eq 'page' ? 'modified_on' : 'authored_on';#コメントアウト
$arg{'sort'} = 'modified_on';#追加
$arg{direction} = 'descend';
my $filter_key = $q->param('filter_key') || '';
my $filter_col = $q->param('filter')     || '';
my $filter_val = $q->param('filter_val');
my $iter_method;
my $total;
略

あわせてテンプレートも修正する。場所は/tmpl/cms/include/entry_table.tmplの79行目付近。

テンプレートの変更にはCMSContextを使うと安全です。

修正前

<th class="date">
<mt:if name="object_type" eq="page">
<__trans phrase="Last Modified">
<mt:else>
<__trans phrase="Created">
</mt:if>
</th>

修正後

<th class="date">
<__trans phrase="Last Modified">
</th>

この変更による影響が他の箇所へ出るのかどうかについては未検証。後ほど調べよう。

ちなみにソートに使えそうな値にはこんなのがありそうだけど、動くのかな。。。

  • created_on
  • created_by
  • modified_on
  • modified_by
  • authored_on
  • author_id
  • pinged_urls
  • tangent_cache
  • template_id
  • class
  • meta
  • comment_count
  • ping_count