picoの特定カテゴリをxoopsfaq化する

xoopsfaqモジュールで作っていたFAQも、picoに押し込むことにしました。それも、別モジュールではなくて文書モジュールの1カテゴリとして実現します。

xoopsfaqモジュールの仕様
  1. カテゴリは1階層のみ
  2. カテゴリ内の記事の順番は並べ替え可能
  3. モジュールトップですべてのカテゴリと記事タイトルが一覧できる
  4. カテゴリトップでは記事一覧と記事本文がまとめて読める

特徴的なのは4で、picoでいえば編集は記事単位で、閲覧はカテゴリ単位で行うという感じです。xoopsfaqで同じカテゴリに属する記事をまとめて一つのpico文書にしてしまう手もありますが、16カテゴリ80文書?くらいあるし、もうpico文書として移行してしまったので、なんとかこのまま押し切りたい……。

picoの特定カテゴリをxoopsfaqとして実現するイメージをメモしておきます。

picoトップ ← 文書モジュールのトップ(cat_id = 0)
└FAQトップカテゴリ ← FAQカテゴリ一覧+各カテゴリ内記事一覧
 └FAQカテゴリ ← FAQ記事(タイトル&内容)の一覧
  ├FAQ記事1 ← 単一のpico文書だが、直接はアクセスされない
  └FAQ記事2 ← 単一のpico文書だが、直接はアクセスされない
FAQトップカテゴリ

FAQトップカテゴリである XOOPS_URL/docs/cat/152 にアクセスすると、(オプション show_listasindex:0 の効果で)このカテゴリの直下にある唯一の文書 XOOPS_URL/docs/content/2788 にリダイレクトされます。その文書の内容は、

<{pico dir=$mydirname id="2788" item="faqtop"}>
<pre><{$faqtop.content.body_raw|escape}></pre>

等とするとダイナミックに引用できるのですが、将来内容を変えてしまうかもしれないので、コピー&ペーストしておきます。

<{* Obtain subcategories *}>
<{pico_subcattree dirname=$mydirname id=$content.cat_id item="faqcats"}>

<{foreach from=$faqcats.subcattree_raw item="fcat"}>
  <h5><a href="<{$smarty.server.PHP_SELF}>?cat_id=<{$fcat.cat_id}>"><{$fcat.cat_title}></a></h5>

  <{* Obtain documents under current category *}>
  <{pico_list id=$fcat.cat_id order="o.weight" item="faqitems"}>
  <ul>
    <{* List document subjects *}>
    <{foreach from=$faqitems.contents item="fitem"}>

    <{* Skip category TOC file (it must be titled "INDEX") *}>
    <{if $fitem.subject != "INDEX"}>
      <li><{$fitem.subject}></li>
    <{/if}>
  <{/foreach}>
  </ul>
<{/foreach}>

pico_subcattreeプラグインでカテゴリの一覧を取り出し、pico_listプラグインでカテゴリ毎に文書の一覧を取り出すことでFAQの目次を作ります。いや-、欲しい用途にぴったりのSmartyプラグインが既に用意されていて、ありがたいかぎりです。特にpico_listプラグインは、様々なフィールドをキーにして文書を並べ替えられるので重宝しそうです。INDEXという件名の文書をスキップしている箇所については後述。

FAQカテゴリ

こちらはFAQトップカテゴリに比べると少々工夫が必要でした。結局、FAQトップカテゴリと同じように各カテゴリに毎にオプション show_listasindex:0 を付け、目次となるファイルを用意しました。そのファイルが同じカテゴリにある他の文書を読み込み、一文書として表示します。その目次文書はこんな感じ:

<{* Obtain documents under current category *}>
<{pico_list dir=$mydirname cat_id=$content.cat_id item="list" order="o.weight"}>

<{* Table of contents *}>
<ul>
<{foreach from=$list.contents item=doc key=key name=toc}>
  <{* Remove myself *}>
  <{if $content.content_id != $key}>
    <li><a href="#a<{$doc.content_id}>"><{$doc.subject}></a></li>
  <{/if}>
<{/foreach}>
</ul>

<{* Contents *}>
<{foreach from=$list.contents item=doc key=key name=contents}>
  <{* Remove myself *}>
  <{if $content.content_id != $key}>
    <a name="a<{$doc.content_id}>"></a><h4><{$doc.subject}></h4>
    <div class="kdfaq_body"><{$doc.body_cached}></div>
  <{/if}>
<{/foreach}>

まずpico_listプラグインで自分が属するカテゴリの文書一覧を取得した上で、ページの先頭に置く目次と本文を作るためにループを2回回しています。pico_listプラグインは文書IDを添字とした配列を渡してくれるので、<{if $content.content_id != $key}>でこの文書自身の読み込みをスキップすることができます。

上記にはカテゴリや文書に固有の情報をハードコードしていないため、同一の文書を使い回すことができます。ソースを同一にできれば変更にも強いですね。これをテンプレートファイルにすると各文書が1行で済みますが、モジュールのアップデートが必要なので面倒だな……と考えて思いつきました。1つのファイルを複数文書からラップすればいいのだ!そこでXOOPS_TRUS_PATH/wraps/docs/ に上記のコードを faq_cat_index.html という名前で保存し、ラップを試みました。 

しかしpicoは、1つのhtmlファイルを複数の文書からラップすることをなぜか許してくれません。1つめはもちろんOKなのですが2つの文書からは、文書を選ぶとすぐに faq_cat_index1.html のようにリネームされてしまいます。ではサーバ側でシンボリックリンクを張って分身の術を……いかにもメンテナンス性が低いですね。

次に思いついたのは手動ラップというか、Smartyのincludeで先の文書を読み込むこと。結局これがうまくいきました。具体的には

<{include file="`$smarty.const.XOOPS_TRUST_PATH`/wraps/`$mydirname`/faq_cat_index.html"}>

という1行だけからなる文書をカテゴリ毎に作り、INDEXというタイトルで保存します。この文書の表示優先度(weight)をカテゴリ内で最小にしておくことも忘れずに。picoはキャッシュが効くので、元となるファイルは同一であっても、各pico文書には自分のカテゴリの文書を読み込んだ結果がキャッシュされます。

 


友達に伝える
タグ: XOOPS pico smarty
作成: 2013/8/24 by:webmaster
更新: 2013/10/16 by:koji


サイト全体でタグを管理するため、pico のタグを letag でも管理する

Tech

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

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

ログイン

コメント

タグ(キーワード)