picoで、サブカテゴリーを含めた最新文書を表示する

●やりたいこと

picoモジュールに、このようなカテゴリーと文書があるとする。

(トップ)
└ミニ書評・リンク集
 └ミニ書評
  └分類A
   └文書X
 └リンク集
  └分類A
   └文書Y

任意のカテゴリーのトップページで、そのカテゴリーおよびその下のサブカテゴリーすべての中で最新の文書を表示したい。

●現状

picoではカテゴリごとに、カテゴリートップのページをどう表示するかを選択できます。モジュール単位のデフォルト設定として、管理画面の「一般設定」ページに次のような項目があります。

カテゴリートップでリストを表示する
「はい」の場合、カテゴリートップではサブカテゴリーと直下のコンテンツがリスト式に表示されます。「いいえ」の場合、そのカテゴリー内で最も表示優先度の高いコンテンツが表示されます。

この指定は、各カテゴリーの編集画面で show_listasindex:1すなわち「はい」あるいは0すなわち「いいえ」を指定することで、上書きできます。

当サイトでは多くの文書系モジュールを1つのpicoモジュールに統合したためにカテゴリー階層が深くなっています。そのためshow_listasindex:1とすると、文書に行き着くまでにカテゴリ一覧を何回もクリックしなければならず、無味乾燥です。

show_listasindex:0にして新着文書を見せたいたいところですが、問題は「そのカテゴリー内で最も表示優先度の高いコンテンツが表示されます」というところ。当サイトでは、たとえばミニ書評は「ミニ書評・リンク集」→「ミニ書評」→「分類A」というカテゴリーに投稿しているので、「ミニ書評・リンク集」カテゴリーの直下には文書がありません。そこで、サブカテゴリーまでを含めて最新の(=作成日が最も新しい)コンテンツを表示する方法を模索しました。

●解決策:Smartyプラグインを利用した(1+α)ファイルハック

picoのソースコードに手を入れずにこの要件を実現するため、新しいSmartyプラグインを作りました。渡されたカテゴリーとサブカテゴリーのすべてを取得して、pico_listプラグインに渡せる形にして返します。

<?php
/* Arch-it
Get category ids from given category and its subcategories

$params['dirname']: Required: dirname (of html side)
$params['cat_id']: Required: category
$params['limit']: Optional: the number of records to get
$params['item']: Optional: the name of variable that contains the result
*/

require_once XOOPS_TRUST_PATH.'/modules/pico/class/PicoModelCategory.class.php' ;

function 
smarty_function_archit_subcats$params , &$smarty )
{
    
// Required parameters
    
if( !isset($params['dirname']) ) {
        
$mydirname $smarty->get_template_vars'mydirname' ) ;
        if( empty( 
$mydirname ) ) {
            echo 
'error '.__FUNCTION__.' [specify dirname]';
            return ;
        }
    } else {
        
$mydirname $params['dirname'];
    }
    if( !isset(
$params['cat_id']) ) {
        echo 
'error '.__FUNCTION__.' [specify cat_id]';
        return ;
    }
    
$cat_id $params['cat_id'];

    
// Optional parameters -- set assigned or default values 
    
$limit = (isset($params['limit'])) ? $params['limit'] : 1;
    
$item = (isset($params['item'])) ? $params['item'] : 'item';

    
// Obtain categories under assigned category
    
$cat_handler = new PicoCategoryHandler($mydirname);
    
$cat_obj $cat_handler->get($cat_id);
    
// Include the assigned category itself
    
$cat_ids implode(','array_merge((array)$cat_id$cat_obj->getChildIds()) );
    
$smarty->assign$item $cat_ids ) ;
}
?>

このプラグインを、show_listasindex:1 のときに呼び出されるテンプレートファイル docs_main_listcontents.html の中から、次のように呼び出しました。場所は、サブカテゴリの一覧と、当該カテゴリに属する文書一覧の間です。文字定数(日本語)のハードコードはご愛敬ということで……。

<{archit_subcats dirname='docs' cat_id="`$category.id`" item='subcats'}>
<{pico_list dir='docs' cat_id="$subcats" item='newestitem' order='o.created_time DESC' limit='1'}>
<{if $newestitem.contents|@count}>
  <{assign var='newest' value="`$newestitem.contents`"|@current}>
  <h3>このカテゴリー(とサブカテゴリー)の最新文書</h3>
  <h5 style="margin-bottom:1em;"><a href="<{$mod_url}>/<{$newest.link}>"><{$newest.subject}></a> (<{$newest.created_time_formatted|strtok:' '}>)</h5>
  <{pico dir='docs' id="`$newest.id`"}>
  <br />
<{/if}>

あるカテゴリツリー中の最新文書のcontent_idを取得するため(だけ)にpico_listプラグインを使い、得られたcontent_idをpicoプラグインに渡して表示させるという豪華な(重量級の)処理です。両プラグインでやっていることをarchit_subcatsプラグインの中でやればずっと軽く済むと思いつつ、面倒なのでこんなかたちで落ち着いてしまいました。

{assign}文について補足します。$newestitem.contentsは、文書のcontent_idをキーとした配列になっています。たとえばcontent_id=2795のこの文書であれば、文書タイトルは $newestitem.contents.2795.subject です。しかし悩ましいことに、content_idは$newestitem.contents.2795.idに格納されています。つまり、content_idを知らなければcontent_idを取り出せないのです。

通常なら{foreach}で要素を取り出しますから問題ないのですが、配列が1つしかないのがわかっているのに{foreach}を通すのも美しくないので、current()を修飾子として使って$newestitem.contents.2795を$newestに割り当てました。


友達に伝える
タグ: XOOPS pico smarty
作成: 2013/9/18 by:webmaster
更新: 2013/9/18 by:webmaster


picoで、サブカテゴリーを含めた最新文書を表示する(ブロック編)

Tech

picoのカテゴリ内の記事を新しい順に並べる

新規ユーザー登録(無料)

  • メールニュース[週刊起-動線]の購読
  • コメントなどの投稿
  • ココロミの利用
  • 一部コンテンツの購読

ログイン

コメント

タグ(キーワード)