movabletypeテンプレートタグのまとめ
TRANSCRIPT
1/122
テンプレートタグのまとめ
2/122
プロフィール
3/122
テンプレートタグの基礎
4/122
テンプレートタグとは
•MTのテンプレートなどに記述するタグ(MTML)•主にMTに保存したデータを出力•HTML などのマークアップ言語に似たフォーマット•「ファンクションタグ」と「ブロックタグ」の2種類•モディファイアもあり
5/122
テンプレートタグを使った簡単なサンプル1
ブログ名をindex.htmlに出力
インデックステンプレート
First Weblog
ブログ全般設定画面
再構築 index.html
<$mt:BlogName$>
6/122
テンプレートタグを使った簡単なサンプル2投稿記事のタイトル・本文をindex.htmlに出力
インデックステンプレート
ブログ記事投稿画面テスト1テスト1です。テスト2テスト2です。
index.html再構築
<mt:Entries><$mt:EntryTitle$><br /><$mt:EntryBody$><br /></mt:Entries>
7/122
管理画面とテンプレートタグの対応1
記事投稿画面
<$mt:EntryTitle$>
<$mt:EntryBody$>
<mt:EntryTags>
<$mt:EntryExcerpt$>
<$mt:EntryDate$>
<$mt:EntryStatus$>
<$mt:EntryBasename$>
8/122
管理画面とテンプレートタグの対応2
記事一覧画面
<mt:Entries>
9/122
フォーマット
10/122
共通的なフォーマット
<mt:XXXXX>
•ブラケット"<"と">"で括る•"mt:"という接頭辞をつける
<mtXXXXX><MT:XXXXX><MtXXXXX>上記でもOK
11/122
ファンクションタグ
12/122
ファンクションタグとは
•データの属性(ブログID、記事タイトルなど)を出力
•ブロックタグの中に記述しないと動作しないものがある(そうでないものも多数)→詳しくは「コンテキスト」の章で
13/122
ファンクションタグのフォーマット
<$mt:EntryTitle$>
<$mt:XXXXX$>
基本的に名称の前半がオブジェクト、後半が属性
タグの先頭と末尾に$をつける(なしでもOK)
14/122
ファンクションタグのオブジェクト(抜粋)
<$mt:Entryxxxx$><$mt:Pagexxxx$><$mt:Categoryxxxx$><$mt:Assetxxxx$><$mt:Commentxxxx$><$mt:Authorxxxx$><$mt:Blogxxxx$><$mt:Websitexxxx$>
オブジェクト データの属性
15/122
ファンクションタグの属性(抜粋)
<$mt:xxxxName$><$mt:xxxxLabel$><$mt:xxxxTitle$><$mt:xxxxURL$><$mt:xxxxCount$><$mt:xxxxID$><$mt:xxxxLink$><$mt:xxxxDate$>
オブジェクト名 データの属性
名前
ラベル
タイトル
URLカウント
IDリンク
日付
16/122
ブロックタグ
17/122
ブロックタグのフォーマット
<mt:XXXX>:
</mt:XXXX>
•開始タグと終了タグを書く•HTMLと同様、終了タグは"/"をつける
•ブロックに挟まれた部分を処理する
開始タグ
終了タグ
ブロック
18/122
ブロックタグの種類
<mt:Entries>:
</mt:Entries>
主に「繰り返し」「関連オブジェクト」「条件判定」の3種類
<mt:EntryAssets>:
</mt:EntryAssets>
繰り返し 関連オブジェクト
<mt:IfCategory>:
</mt:IfCategory>
条件判定
19/122
ブロックタグ(繰り返し)
<mt:Entries>:
</mt:Entries>
ブログ記事の繰り返し
<mt:Assets>:
</mt:Assets>
アイテムの繰り返し
<mt:Blogs>:
</mt:Blogs>
ブログの繰り返し
•MTのオブジェクト(次スライド)を指定
•必ず複数形で記述
20/122
ブロックタグに書ける主なオブジェクト
ユーザー
トラックバック
フォルダ
タグ
アイテム
ウェブページ
ブログ記事
Websitesウェブサイト
ブロックタグオブジェクト
カテゴリ
ブログ
AuthorsPingsFoldersCategoriesTagsAssetsPagesEntriesBlogs
21/122
ブロックタグ(関連オブジェクト)
<mt:EntryAssets>:
</mt:EntryAssets>
ブログ記事のアイテムの一覧
<mt:AssetTags>:
</mt:AssetTags>
アイテムのタグの一覧
•2つのオブジェクトを併記
•前が親オブジェクト、後が子オブジェクト•ブロック内で子オブジェクトの情報を出力したいとき
22/122
ブロックタグ(条件判定)
<mt:IfCategory name="cat1">:
</mt:IfCategory>
カテゴリ名が"cat1"か判定
<mt:AuthorHasEntry>:
</mt:AuthorHasEntry>
MTユーザーが公開記事を投稿しているか判定
•条件が真であればブロック内を実行•テンプレートタグ名にIs/Hasといったキーワードあり
23/122
ブロックタグ(その他:抜粋)
<mt:EntryNext>:
</mt:EntryNext>
現在の記事のひとつ前の記事を表示
<mt:Entries><mt:EntriesHeader>
:</mt:EntriesHeader>
<mt:Entries>
記事一覧で繰り返しの初回のみブロック内を実行
24/122
ブロックタグとファンクションタグの関係
25/122
ブロックタグとファンクションタグの組み合わせ方(繰り返し)
•ブロックタグを単数形にしたファンクションタグが使える•上の例で、10記事投稿されていれば10回繰り返し
<mt:Entries><$mt:EntryTitle$>
</mt:Entries>
26/122
ブロックタグとファンクションタグの組み合わせ方(関連オブジェクト)
後半のオブジェクト名のファンクションタグが使える
<mt:EntryAssets><$mt:AssetURL$>
</mt:EntryAssets>
27/122
ブロックタグとファンクションタグの組み合わせ方(条件判定)
基本的に前半のオブジェクト名のファンクションタグが使える(はず)
<mt:AuthorHasEntry><$mt:AuthorName$>
</mt:AuthorHasEntry>
28/122
問題:記事のカテゴリを出力したい
<mt:Entries><$mt:CategoryLabel$>
</mt:Entries>
29/122
データベースとテンプレートタグ
30/122
テンプレートタグの役割
MTに保存したDBのデータを出力する
DBのテーブルやフィールドと対応している
つまり
31/122
データベースとブロックタグの関係(1/2)
<mt:Assets>
<mt:Authors>
<mt:Blogs>
<mt:Categories><mt:Comments>
<mt:Entries>
32/122
データベースとブロックタグの関係(2/2)
すべてのオブジェクトがブロックタグになっていない
33/122
データベースとファンクションタグの関係(1/2)
<$mt:EntryID$>
<$mt:EntryBasename$>
<$mt:EntryClass$>
<$mt:EntryExcerpt$>
<$mt:EntryBody$>
<$mt:EntryTitle$>
34/122
データベースとファンクションタグの関係(2/2)
すべてのフィールドがファンクションタグになっていない
35/122
テンプレートタグその他
36/122
WordPressテンプレートタグとの違い
↑のような便利タグはないがMTは前述の規則性を覚えれば
他のオブジェクトへの応用が可能
<?php wp_list_categories( $args );?>
WordPressMovableType
<mt:TopLevelCategories><mt:SubCatIsFirst>
<ul></mt:SubCatIsFirst><mt:if tag="CategoryCount"><li><a href="<$mt:CategoryArchiveLink$>">
<$mt:CategoryLabel$>(<$mt:CategoryCount$>)</a><mt:else><li><$mt:CategoryLabel$></mt:if><$mt:SubCatsRecurse$></li><mt:SubCatIsLast>
</ul></mt:SubCatIsLast>
</mt:TopLevelCategories>
37/122
モディファイア
38/122
モディファイアとは
•データの絞り込み条件を指定(ブロックタグ)•出力データの加工(ファンクションタグ)
39/122
モディファイアのフォーマット
タグ名の後方に「キー="値"」で記述
<mt:Entries xxx="yyy">:
</mt:Entries>
<mt:EntryTitle xxx="yyy">ブロックタグファンクションタグ
40/122
モディファイアの種類
•ローカルモディファイア:テンプレートタグ固有のもの•グローバルモディファイア:全テンプレートタグ共通
グローバルモディファイアhttp://www.movabletype.jp/documentation/appendices/modifiers/
※ローカルモディファイアは各テンプレートタグリファレンスに記載
41/122
グローバルモディファイアの数
いくつでも記述可能
<mt:BlogName cat="a" cat="b" cat="c">
42/122
グローバルモディファイアの処理順序
左側から処理
<mt:BlogName cat="a" cat="b" cat="c">
<mt:BlogName cat="c" cat="b" cat="a">
ブログ名が「First Weblog」の場合、「 First Weblogabc」
ブログ名が「First Weblog」の場合、「 First Weblogcba」
43/122
コンテキスト
44/122
コンテキストの意味
状況文脈
45/122
ポイント
テンプレートタグはコンテキストに支配されている
46/122
コンテキストのイメージ
<body><div><mt:EntryTitle><mt:EntryBody></div></body>
ブログ記事テンプレート
ブログ記事コンテキスト
<body><div><mt:Entries>
:</mt:Entries><mt:Categories>
:<mt:Categories></div></dody>
ブログ記事コンテキスト
インデックステンプレート
テンプレートのコンテキスト テンプレートタグのコンテキスト
カテゴリコンテキスト
47/122
コンテキストエラー
インデックステンプレート
<$mt:EntryTitle$>
48/122
コンテキストの関係
インデックスコンテキスト
アーカイブコンテキスト
テンプレートのコンテキスト
テンプレートタグのコンテキスト
テンプレートタグのコンテキスト
49/122
インデックスコンテキスト
•インデックステンプレートが対象
•ニュートラルなコンテキスト。例えばMTEntriesタグでブロ
グ記事一覧を表示すると、ブログに投稿されたすべてのブログ記事が出力対象。
•コンテキストに依存するデータを出力したい場合、ブロックタグで該当のコンテキストに切り替える。
50/122
アーカイブコンテキスト
•アーカイブテンプレートが対象
•アーカイブの種類でコンテキストが決まる。カテゴリアーカイブはカテゴリコンテキスト。ex. MTCategoryLabelタグをブロックタグなしで利用可能
•トップレベルのテンプレートタグはアーカイブコンテキストに依存。ex. カテゴリアーカイブでMTEntriesタグを使用すると、該当カテ
ゴリの記事に絞られる。
アーカイブテンプレートがテンプレートタグ(MTCategoriesなど)で括られているようなイメージ
51/122
テンプレートタグのコンテキスト(1/2)
•テンプレートの中でブロックタグを記述することでコンテキストが切り替わる。
•インデックステンプレートでMTEntriesタグを記述するとブ
ロック内がブログ記事コンテキストになる。
<mt:Entries>:
</mt:Entries>
ブログ記事コンテキスト
インデックステンプレート
ニュートラル
ニュートラル
52/122
テンプレートタグのコンテキスト(2/2)
<mt:Entries><mt:Comments>
:</mt:Comments>
</mt:Entries>
ただし親コンテキスト(親テンプレートや親テンプレートタグ)に依存。
さらにMTCommentsタグを記述するとブロック内がコメ
ントコンテキストに切り替わる。
コメントコンテキスト
ニュートラル
ニュートラル
ブログ記事コンテキスト
53/122
コンテキストに依存しないテンプレートタグ
•システム系テンプレートタグ→ MTVersionタグ、MTPublishCharsetタグなど
•制御系テンプレートタグ→後述
54/122
制御系テンプレートタグ
55/122
制御系テンプレートタグとは
プログラミング可能な汎用テンプレートタグ
56/122
制御系テンプレートタグの種類
•データを変数※に保持•変数の取得•変数の計算•変数やテンプレートタグの判定•変数などによる繰り返し処理•その他
※値を保持するための箱
57/122
変数タグのサンプル1
<$mt:var name="foo" value="1"$>MTSetVarタグで変数fooに"1"を保持
<$mt:var name="foo"$>MTSetVarタグで変数fooの値を出力
<$mt:EntryTitle setvar="entry_title"$>MTEntryTitleタグの内容を変数entry_titleに設定
58/122
変数タグのサンプル2
変数はモディファイアの値として利用可能
<$mt:var name="sort" value="title"$><mt:Entries sort_by="$sort">
<mt:EntryTitle></mt:Entries>
<mt:Entries sort_by="title"><mt:EntryTitle>
</mt:Entries>
上のマークアップは下と同じ
59/122
変数タグのサンプル3
<mt:SetVarBlock name="foo">1</mt:SetVarBlock>
MTSetVarBlockタグで変数fooに"1"を設定
<mt:SetHashVar name="week"><$mt:SetVar name="mon" value="Monday"$><$mt:SetVar name="tue" value="Tuesday"$><$mt:SetVar name="wed" value="Wednesday"$><$mt:SetVar name="thu" value="Thursday"$><$mt:SetVar name="fri" value="Friday"$><$mt:SetVar name="sat" value="Satday"$><$mt:SetVar name="sun" value="Sunday"$>
</mt:SetHashVar>
MTSetHashVarタグで変数weekにキーと値をまとめて設定
60/122
変数タグのサンプル4
<mt:SetVars>foo=1bar=2entry_title=<$mt:EntryTitle$></mt:SetVars>
MTSetVarsタグで変数と値をまとめて設定
61/122
変数タグのサンプル5
<$mt:var name="foo[0]" value="1"$><$mt:var name="foo[1]" value="2"$><$mt:var name="foo[2]" value="3"$>
配列変数fooに"1","2","3"を設定
<$mt:var name="foo[0]"$><$mt:var name="foo[1]"$><$mt:var name="foo[2]"$>
配列変数fooから値を出力
62/122
変数タグのサンプル6
<$mt:var name="bar{x}" value="a"$><$mt:var name="bar{y}" value="b"$><$mt:var name="bar{z}" value="c"$>
ハッシュ変数barに"a","b","c"を設定
<$mt:var name="bar{x}"$><$mt:var name="bar{y}"$><$mt:var name="bar{z}"$>
ハッシュ変数barから値を出力
63/122
変数タグのサンプル7
<$mt:var name="foo" index="0" value="1"$><$mt:var name="foo" index="1" value="2"$><$mt:var name="foo" index="2" value="3"$>
配列変数fooに"1","2","3"を設定(前述のスライドと同じ)
<$mt:var name="bar" key="x" value="a"$><$mt:var name="bar" key="y" value="b"$><$mt:var name="bar" key="z" value="c"$>
ハッシュ変数barに"a","b","c"を設定(前述のスライドと同じ)
64/122
変数タグのサンプル8
<$mt:SetVar name="foo" op="+" value="5"$><$mt:SetVar name="foo" op="-" value="2"$> <$mt:SetVar name="foo" op="*" value="3"$> <$mt:SetVar name="foo" op="/" value="2"$><$mt:SetVar name="foo" op="%" value="2"$><$mt:SetVar name="foo" op="++"$><$mt:SetVar name="foo" op="--"$>
演算($nameに計算結果を保存)
65/122
変数タグのサンプル9
<$mt:var name="foo" op="+" value="5"$><$mt:var name="foo" op="-" value="2"$> <$mt:var name="foo" op="*" value="3"$> <$mt:var name="foo" op="/" value="2"$><$mt:var name="foo" op="%" value="2"$><$mt:var name="foo" op="++"$><$mt:var name="foo" op="--"$>
演算($nameの値は変わらず、計算結果を出力)
66/122
変数タグのサンプル10
<$mt:var name="count(bar)"$>ハッシュ変数barの要素数を求める
<$mt:var name="delete(bar)" key="x"$>ハッシュ変数barから要素を削除
67/122
変数名のハイフンについて
<$mt:var name="foo-1" value="1"$>変数名にハイフン"-"の使用は控えること
<$mt:var name="foo_1" value="1"$>
<$mt:var name="foo1" value="1"$>
68/122
変数名にハイフンが使用できない理由
<$mt:var name="sort-1" value="title"$><mt:Entries sort_by="$sort-1">
<mt:EntryTitle></mt:Entries>
例:MTEntriesのcategoryモディファイアに変数を利用
※禁止ではない($なしの使い方であればOK)
テンプレートとして期待する動作にならない
69/122
判定文のサンプル1
<mt:if name="foo" eq="1">OK<mt:else>NG</mt:if>
変数fooが"1"であればOKを出力、そうでなければNGを出力
70/122
判定文のサンプル2
<mt:if name="foo" eq="1">OK<mt:elseif name="bar" eq="1">OK<mt:else>NG</mt:if>
変数fooが"1"であればOKを出力、そうでなければ変数barが1であればOKを出力、そうでなければNGを出力
71/122
判定文のサンプル3
<mt:unless name="foo" eq="1">OK<mt:else>NG</mt:unless>
変数fooが"1"でなければOKを出力、そうでなければNGを出力
72/122
判定文のサンプル4
<mt:if name="foo" op="+" value="5" eq="10">:
</mt:if>
演算($nameの値は変わらず、計算結果を判定)
73/122
繰り返し文のサンプル1
<mt:for var="x" from="0" to="2"><$mt:var name="foo[$x]"$>
</mt:for>
MTForタグ+配列変数fooで繰り返して配列変数fooの値を出力
74/122
繰り返し文のサンプル2
<mt:loop name="foo"><$mt:var name="__value__"$>
</mt:loop>
MTLoopタグ+配列変数fooで繰り返し
__value__:配列やハッシュの値を出力する特殊変数
75/122
繰り返し文のサンプル3
<mt:loop name="bar"><$mt:var name="__key__"$><$mt:var name="__value__"$>
</mt:loop>
MTLoopタグ+ハッシュ変数barで繰り返し
__key__:ハッシュのキーを出力する特殊変数
76/122
MTSetVarTemplateタグでテンプレートの共通化
<mt:SetVarTemplate name="entry"><$mt:EntryTitle$>:<$mt:EntryBody$>
</mt:SetVarTemplate>
今日の記事<mt:Entries lastn="1"><mt:var name="entry"></mt:Entries>
近の記事<mt:Entries lastn="5" unique="1"><mt:var name="entry"></mt:Entries>
77/122
Tips
78/122
テンプレートタグやHTMLの一部を出力しない
<mt:ignore><body><mt:Entries>:
</mt:Entries></body></mt:ignore>
再構築時に評価されない
79/122
繰り返し処理でデータの有無を判定する
<mt:Entries>:
<mt:else>:
</mt:Entries>
記事が1件もない場合はelseブロックを実行
80/122
ページの空白を削除
<mt:Unless name="compress" regex_replace="/^¥s*¥n/gm","">:
</mt:Unless>
参考:Movable Type で出力するテンプレートから空行を削除
したいhttp://www.tinybeans.net/blog/2012/10/18-094419.html
空白を削除したい部分を下記で括る
81/122
出力データの加工
<mt:EntryTitle regex_replace="/foo/g","bar">
•記事タイトルの中にあるfooをすべてbarに変更
•正規表現の利用が可能
さらに参考:クォーテーションが含まれたときの書き方http://www.mtcms.jp/movabletype-blog/tech/201104222143.html
82/122
if文の判定でPerlを利用
<$mt:setvar name="bar" value="10"$>
<mt:if test="$bar > 5"><$mt:getvar name="bar"$>
</mt:if>
MTSetVarタグで作った変数 bar の値が5以上であることを判定し、マッチすれば MTIf タグのブロックを実行
83/122
記事本文に記述したテンプレートタグを評価
<mt:EntryBody mteval="1">
記事本文に記述したMTタグを
テンプレートタグとして評価
84/122
テンプレートタグに直接テンプレートタグを設定する
<mt:EntryTitle cat="<$mt:EntryKeywords$>" mteval="1" />
mtevalを使うことで、テンプレートタグのモディファイアに直接テンプレートタグを記述することが可能
<$mt:SetVar name="<$mt:EntryTitle$>" value="<$mt:EntryBody$>" mteval="1"$>
参考:Movable Typeのテンプレートタグの中でテンプレートタグを使う方法http://www.koikikukan.com/archives/2014/07/08-005555.php
85/122
テンプレート上でテンプレートタグを生成する(1/2)
参考:MTQ - mtタグ内でのPHP使用につきましてhttp://communities.movabletype.jp/2012/11/mtphp.html
The blog of H.Fujimoto - 実行するテンプレートタグを変数で指定するhttp://www.h-fj.com/blog/archives/2012/11/13-163510.php
<mt:SetVarBlock name="tag"><$mt:EntryTitle$></mt:SetVarBlock><$mt:GetVar name="tag" decode_html="1" mteval="1"$>
86/122
テンプレート上でテンプレートタグを生成する(2/2)
カスタムフィールドのテンプレートタグを100個生成
MTSample1MTSample2MTSample3
:MTSample100
<mt:Entries><mt:for var="i" from="1" to="100">
<mt:SetVarBlock name="tag"><$mt:Sample<$mt:GetVar name="i"$>$></mt:SetVarBlock><$mt:GetVar name="tag" decode_html="1" mteval="1"$>
</mt:for></mt:Entries>
87/122
ブロックタグの省略記法
<$mt:EntryID setvar="entry_id"$><mt:Entries id="$entry_id" /><mt:Entries unique="1" lastn="10"><$mt:EntryTitle$>
</mt:Entries>
参考:ブログ記事ページでその記事以外のブログ記事一覧を表示する方法http://www.koikikukan.com/archives/2015/07/30-005555.php
88/122
アーカイブページでメインページと同じ内容の「ブログ記事一覧」を表示
アーカイブページで、メインページと同じ内容の「 近のブログ記事一覧」を表示したい場合、アーカイブコンテキストをインデックスコンテキストや別のコンテキストに変更する。
IndexContextプラグイン( http://blog.aklaswad.com/mtplugins/indexcontext.html )を利用する
ArchiveListタグを使用する
Blogsタグにignore_archive_contextモディファイアを利用する<mt:IndexContext>:
</mt:IndexContext>
<mt:ArchiveList type="Individual" lastn="10">
<$mt:EntryTitle$></mt:ArchiveList>
<mt:Blogs blog_id="2" ignore_archive_context="1">
<mt:Entries blog_id="2" lastn="10"><$mt:EntryTitle$>
</mt:Entries></mt:Blogs>
89/122
ハッシュの入れ子
<mt:SetHashVar name="week"><$mt:SetVar name="mon" value="Monday"$><mt:SetHashVar name="ampm">
<$mt:SetVar name="am" value="AM"$><$mt:SetVar name="pm" value="PM"$>
</mt:SetHashVar></mt:SetHashVar>
<mt:GetVar name="week{ampm}" setvar="foo" /><mt:GetVar name="foo{am}" />
MTHashVarタグで入れ子にする
参考:Movable Type の配列とハッシュの入れ子http://www.koikikukan.com/archives/2009/12/15-005555.php
90/122
自作テンプレートタグ関連プラグイン
91/122
Objectプラグイン
http://www.koikikukan.com/archives/2010/11/09-005555.php
<mt:Objects name="log"><mt:Object name="log" property="message" />
</mt:Objects>
テンプレートタグ化されていないオブジェクトデータをテンプレートで取得
例:ログデータを取得
92/122
Splitプラグイン
http://www.koikikukan.com/archives/2009/01/20-015555.php
<mt:setvar name="foo" value="a AND b AND c" /><mt:getVar name="foo" split=" AND " setvar="bar"><mt:loop name="bar"> <mt:getVar name="__value__" /><br />
</mt:loop>
abc
変数の値を配列に変換
93/122
GetArchivesプラグイン
http://www.koikikukan.com/archives/2009/01/20-015555.php
<ul><$mt:GetArchives type="monthly"$></ul>
WordPressの「wp_get_archives」のMT版
94/122
MultiCalendarプラグイン
http://www.koikikukan.com/archives/2009/01/20-015555.php
<mt:MultiCalendar blog_id="1"><mt:CalendarWeekHeader><tr></mt:CalendarWeekHeader>
<td><mt:CalendarIfEntries>
<mt:Entries lastn="1"><a href="<$mt:EntryPermalink$>"><$mt:CalendarDay$></a>
</mt:Entries></mt:CalendarIfEntries><mt:CalendarIfNoEntries>
<$mt:CalendarDay$></mt:CalendarIfNoEntries><mt:CalendarIfBlank> </mt:CalendarIfBlank>
</td> <mt:CalendarWeekFooter></tr></mt:CalendarWeekFooter>
</mt:MultiCalendar>
複数ブログの情報をひとつのカレンダーに表示
95/122
MondayCalendarプラグイン
http://www.koikikukan.com/archives/2011/06/17-005555.php
<mt:MondayCalendar><mt:CalendarWeekHeader><tr></mt:CalendarWeekHeader>
<td><mt:CalendarIfEntries>
<mt:Entries lastn="1"><a href="<$mt:EntryPermalink$>"><$mt:CalendarDay$></a>
</mt:Entries></mt:CalendarIfEntries><mt:CalendarIfNoEntries>
<$mt:CalendarDay$></mt:CalendarIfNoEntries><mt:CalendarIfBlank> </mt:CalendarIfBlank>
</td> <mt:CalendarWeekFooter></tr></mt:CalendarWeekFooter>
</mt:MondayCalendar>
カレンダーを月曜始まりに変更
96/122
DateUsecプラグイン
http://www.koikikukan.com/archives/2014/06/16-015555.php
<$mt:DateUsec format="%Y-%m-%d %H:%m:%S."$>
ミリ秒・マイクロ秒を表示
2014-06-16 01:07:37.580135
97/122
拡張テンプレートタグプラグインの作り方
98/122
プラグインの概要
ブログのテンプレート一覧を出力するMTTemplatesタグとテンプレート名を出力するMTTemplateNameを提供
<mt:Templates><$mt:TemplateName$>
</mt:Templates>
99/122
プラグインファイル構成
plugins/
Templates/
config.yaml
lib/
Templates/
Tags.pm
100/122
config.yaml
name: Templatesid: Templatesdescription: This plugin is an example plugin.version: 0.01tags:
block:Templates: $Templates::Templates::Tags::_hdlr_templates
function:TemplateName: $Templates::Templates::Tags::_hdlr_template_name
テンプレート名 タグハンドラ名
テンプレートタグ定義
ブロックタグ定義
ファンクションタグ定義
101/122
Tags.pm
package Templates::Tags;
use strict;
sub _hdlr_templates {my ($ctx, $args, $cond) = @_;my ($terms, $args);$terms->{ blog_id } = $ctx->stash('blog_id');$args->{ sort } = 'name';my $iter = MT::Template->load_iter( $terms, $args );my $res = '';my $tokens = $ctx->stash('tokens');my $builder = $ctx->stash('builder');while (my $tmpl = $iter->()) {
local $ctx->{__stash}{tmpl} = $tmpl;defined(my $out = $builder->build($ctx, $tokens, $cond)) orreturn $ctx->error( $builder->errstr );$res .= $out;
}$res;
}
sub _hdlr_template_name {my ($ctx, $args) = @_;my $tmpl = $ctx->stash('tmpl')
or return _error($ctx, 'MT'.$ctx->stash('tag'));$tmpl->name;
}
sub _error {my ($ctx, $tag) = @_;$ctx->error(MT->translate('You used an [_1] tag
outside of the proper context.', $tag));}
1;
正直、意味がわからないw
102/122
プログラム
103/122
主な登場人物
MT::WeblogPublisherMT::TemplateMT::Template::ContextMT::Builder
:再構築を司るクラス:テンプレートオブジェクト:タグハンドラの全実装※:テンプレートのパースとインタープリタ
※MT::Template::Tags・アドオン・拡張テンプレートタグなど
104/122
テンプレートが再構築される仕組み(イメージ)
xxテンプレート
テンプレートの中身をパース(MT::Builder->compile())
上から順に評価(MT::Builder->build())トークンリスト
タグハンドラ
・ファンクションタグであればデータを出力・ブロックタグであれば内部でビルド
・テキストはそのまま出力・テンプレートタグがあればタグハンドラ実行
ブロックタグがなくなるまで繰り返される
トークンリスト(DOMのようなもの)生成
105/122
テンプレートが再構築される仕組み(インデックステンプレート)
sub rebuild_indexes { $tmpl->build($ctx); # MT::Template
記事投稿・再構築など
sub build {my $ctx = $tmpl->context; # MT::Template::Context->new;my $tokens = $tmpl->compile(); # MT::Builder->compile($tmpl);my $res = $builder->build( $ctx, $tokens, $cond ); # MT::Builder
MT::WeblogPublisher
sub compile { ... } sub build { ... }
MT::Template
MT::Builder
テンプレートの再構築開始
テンプレートをトークン分割し、トークンリスト生成
トークンリストから出力ページを作成
106/122
トークン分割とは
・プログラムが読みやすい形式に変換・DOMのようなもの
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx, '<$mt:BlogName$>');
トークン分割のサンプルコード(抜粋)
107/122
トークン分割のサンプル1
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx, '<$mt:BlogName$>');
$VAR1 = [bless( [
'BlogName',{},[],undef,[],undef,undef
], 'MT::Template::Node' )];
$tokens
108/122
トークン分割のサンプル2
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<$mt:BlogName$><$mt:BlogID$><$mt:Version$>');
$VAR1 = [bless( [
'BlogName',{},[],undef,[],undef,undef
], 'MT::Template::Node' ),bless( [
'BlogID',{},[],undef,[],undef,undef
], 'MT::Template::Node' ),bless( [
'Version',{},[],undef,[],undef,undef
], 'MT::Template::Node' )];
$tokens
109/122
トークン分割のサンプル3
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<mt:Entries><mt:EntryTitle></mt:Entries>');
$VAR1 = [bless( [
'Entries',{},[bless( [
'EntryTitle',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle$>',[],undef,undef
], 'MT::Template::Node' )];
$tokens
110/122
トークン分割のサンプル4
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<mt:Entries sort="descend"><mt:EntryTitle>
</mt:Entries>');
$VAR1 = [bless( [
'Entries',{'sort' => 'decend'
},[bless( [
'EntryTitle',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle$>',[],undef,undef
], 'MT::Template::Node' )];
$tokens
111/122
トークン分割のサンプル5
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<mt:Entries sort="descend"><mt:EntryTitle cat="foo">
</mt:Entries>');
$VAR1 = [bless( [
'Entries',{
'sort' => 'decend'},[bless( [
'EntryTitle',{
'cat' => 'foo'},[],undef,[['cat', 'foo'
]],$VAR1->[0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle cat="foo"$>',[],undef,undef
], 'MT::Template::Node' )];
$tokens
112/122
トークン分割のサンプル6
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<mt:Entries><mt:EntryTitle><mt:EntryBody>
</mt:Entries>');
$VAR1 = [bless( [
'Entries',{'sort' => 'decend'
},[bless( [
'EntryTitle',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' ),bless( [
'EntryBody',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle cat="foo"$><$mt:EntryBody$>',[],undef,undef
], 'MT::Template::Node' )];
$tokens
113/122
トークン分割のサンプル7
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<mt:Entries><mt:EntryTitle>aaaaa<mt:EntryBody>
</mt:Entries>');
$VAR1 = [bless( [
'Entries',{'sort' => 'decend'
},[bless( [
'EntryTitle',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' ),bless( [
'TEXT','aaaaa',undef,undef,undef,$VAR1->[0][2],undef
], 'MT::Template::Node' ),bless( [
'EntryBody',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle cat="foo"$>aaaaa<$mt:EntryBody$>',[],undef,undef
], 'MT::Template::Node' )];
$tokens
114/122
トークン分割のサンプル8
my $build = MT::Builder->new;my $ctx = MT::Template::Context->new;my $tokens = $build->compile($ctx,
'<$mt:var name="foo" value="1"$><mt:Entries sort="decend">
<mt:if name="foo" eq="1"><$mt:EntryTitle cat="foo"$>
</mt:if>aaaaa<$mt:EntryBody$>
</mt:Entries>');
$VAR1 = [bless( [
'var',{
'value' => '1','name' => 'foo'
},[],undef,[],undef,undef
], 'MT::Template::Node' ),bless( [
'Entries',{
'sort' => 'decend'},[
bless( ['if',{'name' => 'foo','eq' => '1'
},[bless( [
'EntryTitle',{},[],undef,[],$VAR1->[1][2][0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle cat="foo"$>',[],$VAR1->[1],undef
], 'MT::Template::Node' ),bless( [
'TEXT','aaaaa',undef,undef,undef,$VAR1->[1][2],undef
], 'MT::Template::Node' ),bless( [
'EntryBody',{},[],undef,[],$VAR1->[1],undef
], 'MT::Template::Node' )],'<mt:if name="foo" eq="1"><$mt:EntryTitle cat="foo"$></mt:if>aaaaa<$mt:EntryBody$>',[],undef,undef
], 'MT::Template::Node' )];
$tokens
115/122
テンプレートタグはどこで識別されているか
sub compile {:
while ( $text=~ m!(<¥$?(MT:?)((?:<[^>]+?>|"(?:<[^>]+?>|.)*?"|'(?:<[^>]+?>|.)*?'|.)+?)([-]?)[¥$/]?>)!gis)
{my ( $whole_tag, $prefix, $tag, $space_eater ) = ( $1, $2, $3, $4 );
:
MT::Builder
$whole_tag:<mt:Entries sort_by="title">$prefix:mt:$tag:entries sort_by="title"
116/122
トークンのビルドとは
・テキストノードの場合、内容の出力・テンプレートタグの場合、タグハンドラの実行
117/122
sub build {:
for my $t (@$tokens) {:
my $hdlr = $ctx->handler_for( $t->tag );:
my $out = $hdlr->invoke( $ctx, ¥%args, $cond );:
}}
トークンのビルドイメージ
MT::Builder
$VAR1 = [bless( [
'BlogName',{},[],undef,[],undef,undef
], 'MT::Template::Node' ),bless( [
'BlogID',{},[],undef,[],undef,undef
], 'MT::Template::Node' ),bless( [
'Version',{},[],undef,[],undef,undef
], 'MT::Template::Node' )];
繰り返し1回目
繰り返し2回目
繰り返し3回目
③タグハンドラの実行
②タグハンドラ(MT::Template::Handler)を返却。$tは分割したトークン
①$tokensのリスト分繰り返し
118/122
トークンの引き継ぎsub build {
for my $t (@$tokens) {my ( $tokens, $tokens_else, $uncompiled );if ( $childNodes && ref($childNodes) ) {
( $tokens, $tokens_else ) = ( [], [] );for my $sub (@$childNodes) {
my $tag = lc $sub->tag;if ( $tag eq 'else' || $tag eq 'elseif' ) {
push @$tokens_else, $sub;}else {
push @$tokens, $sub;}
}my $hdlr = $ctx->handler_for( $t->tag );my ( $h, $type, $orig ) = $hdlr->values;my $conditional = defined $type && $type == 2;
if ($h) {$timer->pause_partial if $timer;local ( $ctx->{__stash}{tag} ) = $t->tag;local ( $ctx->{__stash}{tokens} )
= ref($tokens)? bless $tokens, 'MT::Template::Tokens': undef;
local ( $ctx->{__stash}{tokens_else} )= ref($tokens_else)? bless $tokens_else, 'MT::Template::Tokens': undef;
local ( $ctx->{__stash}{uncompiled} ) = $uncompiled;
①子ノードがあれば$tokensまたは$tokens_elseにpush
②子ノードの$tokensを$ctx(stash)に保持(=引き継ぎ)
MT::Builder
$VAR1 = [bless( [
'Entries',{},[
bless( ['EntryTitle',{},[],undef,[],$VAR1->[0],undef
], 'MT::Template::Node' )],'<$mt:EntryTitle$>',[],undef,undef
], 'MT::Template::Node' )];
子ノード
親ノード
119/122
ブロックタグのビルド
ブロックタグの場合、タグハンドラ内でさらにビルドを再帰的に実行し、出力結果を積み上げ
sub build {:
for my $t (@$tokens) {:
my $hdlr = $ctx->handler_for( $t->tag );:
my $out = $hdlr->invoke( $ctx, ¥%args, $cond );:
}}
MT::Builder
sub _hdlr_entries {:
my $tok = $ctx->stash('tokens');:
for my $e (@entries) {:
my $out = $builder->build( $ctx, $tok, ... );:
}}
②ブロックタグがあればビルドを再帰的に実行
MT::Template::Tag::Entry
①タグハンドラ実行
120/122
コンテキストエラーの仕組み記事コンテキストの場合
sub _hdlr_entry_title {my ( $ctx, $args ) = @_;my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error();my $title = defined $e->title ? $e->title :
'';:
return $title;}
sub _hdlr_entries {:
for my $e (@entries) {:
local $ctx->{__stash}{entry} = $e;:
my $out = $builder->build( $ctx, $tok, ... );:
}}
<mt:Entries><mt:EntryTitle>
</mt:Entries>
インデックステンプレート
MT::Template::Tag::Entry MT::Template::Tag::Entry
①MTEntriesタグの処理で
記事コンテキストを設定
②MTEntryTitleタグ内のコンテキスト判定OK
121/122
コンテキストエラーの仕組み記事コンテキストでない場合
<mt:EntryTitle>
インデックステンプレート
sub _no_entry_error {my ($ctx) = @_;my $tag_name = $ctx->stash('tag');$tag_name = 'mt' . $tag_name unless $tag_name =~ m/^MT/i;return $_[0]->error(
MT->translate("You used an '[_1]' tag outside of the context of an entry; "
. "Perhaps you mistakenly placed it outside of an 'MTEntries' container tag?",
$tag_name)
);}
MT::Template::Context
①いきなりMTEntryTitleタグ処理のため、記事コンテキスト判定NG
②エラー処理
sub _hdlr_entry_title {my ( $ctx, $args ) = @_;my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error();
my $title = defined $e->title ? $e->title : '';
:return $title;
}
MT::Template::Tag::Entry
122/122
ご静聴ありがとうございました