社内で質問を受けたのですが、例えば「同じカテゴリ内で公開日が前後になる記事を再構築したい」という場合にどうするか?という話です。
単純に日付ベースであれば<mt:entryprev>・<mt:entrynext>タグで記事オブジェクトは取得できますし、環境変数{model_name}_publish_nextprev(記事ならばentry_publish_nextprev)で前後のオブジェクトが再構築されるようになります。しかし「同じカテゴリ内で」と条件が付くとこれらは使えません。
「同じカテゴリ内で公開日が前になる記事」を取得するタグは下記のように書けます。ここでオブジェクトIDが取れますね。後ろの場合はsort_order="ascend"にします。
<mt:entries categories="AI" sort_by="published_on" sort_order="descend" limit="1" offset="1" cols="id,title">
<li><mt:entryid />: <mt:entrytitle /></li>
</mt:entries>
環境変数{model_name}_publish_nextprevの実装をシンプルに言うと、該当するオブジェクトを取得してPrototypeクラスのdelayed_publish_objsプロパティにセットしているだけでした。そこで、<mt:adddelayedpublish ids="1,2">のように再構築をしたいオブジェクトのidを渡すとそれらをdelayed_publish_objsプロパティにセットする独自のファンクションタグを実装しました。下記のような簡単な実装です。
public function function_add_delayed_publish_objs( $args, $ctx ) {
$app = $ctx->app;
// 動的生成やポップアップの再構築の場合は処理しない
if ( $app->id !== 'Prototype' || $app->mode === 'rebuild_phase' ) {
return '';
}
if ( ! array_key_exists( 'ids', $args ) ) {
return '';;
}
$objs = $app->db->model( 'entry' )->load( [ 'id' => [ 'IN' => explode( ',', $args['ids'] ) ] ] );
foreach ( $objs as $obj ) {
$app->delayed_publish_objs[ $obj->_model . '_' . $obj->id ] = $obj;
}
return '';
}
※ファンクションタグは空文字を返した方が良かったハズ。
前後の記事を呼び出すタグと独自タグを記事詳細ページに記述すると、目論見通り記事詳細ページが再構築されるようになりました。お試しあれ。
ちなみにdelayed_publish_objsの処理は下記のようになっているので、編集した記事の前後のページが再構築される時に<mt:adddelayedpublish ids="n">が処理されてさらに前後の記事が再構築される、というようなことはありませんでした。
if ( ! empty ( $this->delayed_publish_objs ) ) {
$delayed_publish_objs = $this->delayed_publish_objs;
foreach ( $delayed_publish_objs as $delayed_obj ) {
$this->publish_obj( $delayed_obj );