Movable Typeのカレンダーに複数カテゴリのリンクを表示する方法を紹介します。
1.基本
Movable Typeでカレンダーを作るためのMTCalendarタグにはcategoryモディファイアが用意されており、これを利用すれば特定の1つのカテゴリだけに絞ったカレンダーを作成することができます。
例えば「ニュース」カテゴリに属しているブログ記事のカレンダーを作るには次のようにすればOKです。
<mt:Calendar category="ニュース">
…中略…
</mt:Calendar>
ただし複数のカテゴリを指定することはできません。
2.やりたいこと
ここでは、次のようなカテゴリ構成があると想定します。
日記
├ 食事
├ 旅行
└ 趣味
ニュース
├ イベント
├ お知らせ
└ その他
各ブログ記事はサブカテゴリにのみ属しています。
この状態で「ニュース」カテゴリのサブカテゴリに属するブログ記事だけをカレンダーのリンクとして表示します。リンク先は日別アーカイブにします。
カテゴリが「ニュース」カテゴリとその配下のカテゴリだけであれば、MTCalendarタグをそのまま利用すればいいのですが、このケースでは「日記」カテゴリ配下のブログ記事までカレンダーに表示されてしまいます。
実現イメージを下図に示します。
例えば「イベントカレンダーを作りたいけど、イベントに関係ないブログ記事をカレンダーのリンクに混ぜたくない」といった場合に有効です。
3.テンプレート
次のテンプレートを利用します。
<mt:SetVar name="undef(calendar_data)" />
<mt:SetVar name="counter" value="1" />
<mt:Calendar month="this">
<mt:CalendarIfEntries>
<$mt:SetVar name="flag" value="0"$>
<mt:Entries>
<mt:if tag="EntryCategory" like="イベント|お知らせ|その他">
<$mt:EntryLink archive_type="Daily" setvar="entry_date"$>
<$mt:SetVar name="flag" value="1"$>
</mt:if>
</mt:Entries>
<mt:if name="flag">
<mt:SetVarBlock name="calendar_data[$counter]"><a href="<$mt:GetVar name="entry_date"$>"><$mt:GetVar name="counter"$></a></mt:SetVarBlock>
<mt:else>
<mt:SetVarBlock name="calendar_data[$counter]"><$mt:GetVar name="counter"$></mt:SetVarBlock>
</mt:if>
<mt:SetVar name="counter" op="++" />
</mt:CalendarIfEntries>
<mt:CalendarIfNoEntries>
<mt:SetVar name="calendar_data[$counter]" value="$counter" />
<mt:SetVar name="counter" op="++" />
</mt:CalendarIfNoEntries>
</mt:Calendar>
<table>
<thead>
<tr>
<th abbr="Sunday">日</th>
<th abbr="Monday">月</th>
<th abbr="Tuesday">火</th>
<th abbr="Wednesday">水</th>
<th abbr="Thursday">木</th>
<th abbr="Friday">金</th>
<th abbr="Saturday">土</th>
</tr>
</thead>
<tbody>
<mt:Calendar month="this">
<mt:CalendarWeekHeader><tr></mt:CalendarWeekHeader>
<td>
<mt:CalendarIfEntries>
<$mt:CalendarDay setvar="day"$>
<mt:getVar name="calendar_data[$day]" />
</mt:CalendarIfEntries>
<mt:CalendarIfNoEntries>
<$mt:CalendarDay setvar="day"$>
<mt:getVar name="calendar_data[$day]" />
</mt:CalendarIfNoEntries>
<mt:CalendarIfBlank> </mt:CalendarIfBlank>
</td>
<mt:CalendarWeekFooter></tr></mt:CalendarWeekFooter>
</mt:Calendar>
</tbody>
</table>
4.テンプレートの解説
まず、変数calendar_dataと変数counterを初期化します。
<mt:SetVar name="undef(calendar_data)" />
<mt:SetVar name="counter" value="1" />
calendar_dataは日別にブログ記事のリンクを設定する配列変数です。counterは配列変数のインデックス(=日付)にするための変数です。
最初のMTCalendarタグは次のような構造になっています。
<mt:Calendar month="this">
<mt:CalendarIfEntries>
[配列変数calendar_dataにリンク付きの日付を設定]
<mt:SetVar name="counter" op="++" />
</mt:CalendarIfEntries>
<mt:CalendarIfNoEntries>
[配列変数calendar_dataに日付のみ設定]
<mt:SetVar name="counter" op="++" />
</mt:CalendarIfNoEntries>
</mt:Calendar>
MTCalendarIfEntriesタグの中では配列変数calendar_dataにリンク付きの日付を設定します(赤色部分)。MTCalendarIfNoEntriesタグの中ではブログ記事が存在しないので、日付のみ設定します(青色部分)。それぞれのタグの中で変数counterをインクリメントして日付と対応させています。
次に、赤色で示した[配列変数calendar_dataにリンク付きの日付を設定]の制御を解説します。
MTCalendarタグはすべてのサブカテゴリのブログ記事を対象にしてしまうため、MTCalendarIfEntriesタグの中で、該当カテゴリのブログ記事のみを取得するために、次の制御を行います。
<mt:CalendarIfEntries>
<$mt:SetVar name="flag" value="0"$>
<mt:Entries>
<mt:if tag="EntryCategory" like="イベント|お知らせ|その他">
<$mt:EntryLink archive_type="Daily" setvar="entry_date"$>
<$mt:SetVar name="flag" value="1"$>
</mt:if>
</mt:Entries>
まず、変数flagを初期化しておき、MTEntriesタグでブログ記事情報を取得します。その中でMTIfタグにtagモディファイアとlikeモディファイアを組み合わせてMTEntryCategoryタグの値を判定し、取得したいカテゴリの場合のみ、MTEntryLinkタグでブログ記事の日別アーカイブのリンクを変数entry_dateに設定し、変数flagに「1」を設定します。
そしてさらに次の制御を行います。
<mt:if name="flag">
<mt:SetVarBlock name="calendar_data[$counter]"><a href="<$mt:GetVar name="entry_date"$>"><$mt:GetVar name="counter"$></a></mt:SetVarBlock>
<mt:else>
<mt:SetVarBlock name="calendar_data[$counter]"><$mt:GetVar name="counter"$></mt:SetVarBlock>
</mt:if>
</mt:CalendarIfEntries>
変数flagに「1」が設定された場合のみ、配列変数calendar_dataの該当の日付のインデックス($counter)の位置に変数entry_dateの内容を設定します。変数flagに「1」が設定されていない場合は「ニュース」カテゴリのサブカテゴリに属するブログ記事がないので、配列変数calendar_dataの日付のインデックス($counter)の位置には日付情報だけを設定します。
青色で示した[配列変数calendar_dataに日付のみ設定]の処理は、次のように配列変数calendar_dataに日付情報のみ設定します。
<mt:SetVar name="calendar_data[$counter]" value="$counter" />
2回目のMTCalendarタグで変数calendar_dataを出力する制御を行います。ポイントとなる部分のみ赤色で示しています。
<mt:Calendar month="this">
<mt:CalendarWeekHeader><tr></mt:CalendarWeekHeader>
<td>
<mt:CalendarIfEntries>
<$mt:CalendarDay setvar="day"$>
<mt:GetVar name="calendar_data[$day]" />
</mt:CalendarIfEntries>
<mt:CalendarIfNoEntries>
<$mt:CalendarDay setvar="day"$>
<mt:GetVar name="calendar_data[$day]" />
</mt:CalendarIfNoEntries>
<mt:CalendarIfBlank> </mt:CalendarIfBlank>
</td>
<mt:CalendarWeekFooter></tr></mt:CalendarWeekFooter>
</mt:Calendar>
MTCalendarIfEntriesタグまたはMTCalendarIfNoEntriesタグの中でMTCalendarDayタグの値、つまり日付を変数dayに設定し、その値を変数calendar_dataのインデックスに使ってさきほど設定したデータを出力します。これで不要なカテゴリのブログ記事がリンクされずに、カレンダーデータを生成できます。
MTCalendarタグの「month="this"」は月別アーカイブで利用する場合のみ付与し、それ以外の場合は削除してください。
5.注意事項
本エントリーで紹介したカレンダーはAjax月送りカレンダーなどでも利用することは可能ですが、前後月のリンクについてはすべてのブログ記事を対象にするため、完全な制御を行うことはできません。
具体的には、2012年2月に「ニュース」カテゴリのサブカテゴリに属する記事があれば、2012年2月のカレンダーには2項に示した方法でリンクを表示できますが、2012年1月や2012年3月に「日記」カテゴリのサブカテゴリに属する記事しかない場合、2012年2月の前後月の月送り用のリンクは2012年1月や2012年3月になります(リンク先には記事リンクがひとつもない状態になります)。
6.その他
本題とはそれますが、類似の事例として、複数のブログのブログ記事のカレンダーを作りたい場合は以下の記事を参照してください。