Ver. 3.1.17 リリースのお知らせ


この記事では、2024年6月10日にリリースした Ver. 3.1.17 及び、Ver. 3.0.36、Ver. 2.11.65 の修正内容について紹介いたします。

現在お困りの問題に該当する項目がありましたら、お早めにバージョンアップのご検討をお願いいたします。

Ver. 3.1.17 リリースノート

セキュリティ

  • CMS-6828 pdfプレビュー機能のセキュリティ対応

新機能

  • CMS-6808 メディア作成・更新時のHookを新しく追加(saveMedia)
  • CMS-6814 エントリーの複製時にカスタムフィールド、カスタムユニット、ユニットに保存されたファイル名をランダムにするかをカスタマイズするオプション(entry_duplicate_random_filename)を config.system.yaml に追加
  • CMS-6827 子ブログを含んだ初期インストールが出来る仕組みを用意
  • CMS-6824 Google検索に対してサイト名を指定するWebSite構造化データを追加
  • CMS-6842 インストーラーでデータベースの照合順序を選択できるように修正

変更点

  • CMS-6804 CMSで作成するファイル・ディレクトリのパーミッション設定をconfig.server.phpで設定するように変更
  • CMS-6840 Ajaxによる部分テンプレートアクセスにCSRFトークンによる認証を追加し、許可するtpl指定(allow_tpl_path)を個別指定しなくてもいいように改修 & Ajaxリクエストのセキュリティレベルオプションを用意(ajax_security_level)

修正点

  • CMS-6803 Ver. 3.1.0 から Entry_Bodyの「前後リンク」設定をオフにしても {upperUrl} 変数(一覧リンク)が出力される問題を修正
  • CMS-6810 resizeImg校正オプションでメディア画像の場合、large画像(オリジナル画像)を元にリサイズをしないように修正
  • CMS-6809 メディアのlarge画像(オリジナル画像)がメディア画像修正のたびにオリジナル画像も更新されてしまい、オリジナル画像としての役割を果たせていない問題を修正
  • CMS-6812 重複しないファイルパスの生成処理を修正(毎回日時情報を更新するように変更)
  • CMS-6811 メディア(画像)で不要なスクエア画像が生成されている問題を修正
  • CMS-6797 会員限定フラグが無効の場合、マイクロページャーが表示されない問題の修正
  • CMS-6813 バージョン管理ポップアップで、バージョン作成者のユーザーが削除済みだとphpエラーが出る問題を修正
  • CMS-6815 変数表のEntry_Calendarを修正
  • CMS-6780 URL引用ユニットの BEGIN veil 位置を修正
  • CMS-6818 バージョン編集画面で一時保存バージョンがないと、現在編集しているバージョン名が出ない問題を修正
  • CMS-6782 チェックリストモジュールのコンフィグにnotFoundブロックを追加、検索がヒットしなかった場合にメッセージの表示
  • CMS-6616 管理画面のサイドメニューに便利ツールのリンク集を追加
  • CMS-6826 組み込みJS の「google code prettify」が post include や ダイレクト編集のようにajaxで引っ張ってきたコンテンツに発火しない問題を修正
  • CMS-6823 使われていないブログのカスタムフィールド「サイト 説明」を削除
  • CMS-6833 カスタムフィールドメーカー出力コードを貼り付けた時セル余白が揃いやすいよう対策
  • CMS-6835 コンフィグデータが壊れている場合、コンフィグ保存しても過去のコンフィグが消えない問題を修正
  • CMS-6836 アクセス設定のコンフィグページがルール毎の設定をできない問題を修正
  • CMS-6838 非推奨のCSSのdevice-widthメディア特性使用箇所を削除
  • CMS-6839 a-blog cmsロゴを新しいロゴに変更する

Ver. 3.0.36 リリースノート

セキュリティ

CMS-6830 pdfプレビュー機能のセキュリティ対応

修正点

  • CMS-6841 画像ユニットを未来バージョンで保存すると、画像が保存できない問題を修正

Ver. 2.11.65 リリースノート

セキュリティ

  • CMS-6831 pdfプレビュー機能のセキュリティ対応

主なリリースノートの詳細な内容

CMS-6814 エントリーの複製時にカスタムフィールド、カスタムユニット、ユニットに保存されたファイル名をランダムにするかをカスタマイズするオプション(entry_duplicate_random_filename)を config.system.yaml に追加

Ver. 3.1.17 より、エントリー複製時にカスタムフィールド、カスタムユニット、ユニットに保存されたファイルの名前を "元のファイル名_連番" として複製することができるようになりました。

この機能はデフォルトでは無効になっているため、config.sysrem.yaml に次の記述を追加することで有効化できます。

entry_duplicate_random_filename: 'off'

CMS-6842 インストーラーでデータベースの照合順序を選択できるように修正

インストール時に、MySQLの照合順序を選択できるようになりました。


インストール時にMySQLの照合順序を選択するためのプルダウン

インストール時にMySQLの照合順序を選択できます。


以前のバージョンでは、データベースを提供しているサービス側で照合順序を設定する必要がありましたが、Ver. 3.1.17 より、インストール時に a-blog cms から設定できるようになります。


これにより、サーバーの管理画面からデータベースの照合順序を変更できない場合に phpMyAdmin などから照合順序を変更する必要がなくなります。

CMS-6804 CMSで作成するファイル・ディレクトリのパーミッション設定をconfig.server.phpで設定するように変更

CMSが作成するファイル・ディレクトリのパーミッションをconfig.server.phpで設定できるようになりました。

今までは、サーバーの設定によってファイル・ディレクトリ作成時のパーミッションが決定されていたため、サーバーの設定によってはCMSが作成した、ファイル・ディレクトリに意図しないパーミッションが設定されてしまう場合がありました。

そういった場合でも CMS 側の設定で、作成するファイル・ディレクトリのパーミッションを設定することができます。

デフォルトの指定だと、指定パーミッションとumaskを比較し、論理演算子のANDによって、厳しいほうのパーミッションになるようになっています。

// CMSで作成するディレクトリ・ファイルのパーミッションを設定します
define('CHMOD_DIR', (0775 & ~ umask()));
define('CHMOD_FILE', (0664 & ~ umask()));

例えば、CMSで作成するディレクトリのパーミッションは 775、ファイルのパーミッションは 664 にしたい場合は、config.server.php で以下のようにします。

define('CHMOD_DIR', 0775);
define('CHMOD_FILE', 0664);

CMS-6840 Ajaxによる部分テンプレートアクセスにCSRFトークンによる認証を追加し、許可するtpl指定(allow_tpl_path)を個別指定しなくてもいいように改修 & Ajaxリクエストのセキュリティレベルオプションを用意(ajax_security_level)

htmx というライブラリを a-blog cms でより簡単に利用できるようにすることを目的に、URLコンテキストの tpl 指定の仕様を改善いたしました。

Ajaxによる部分テンプレートアクセスにCSRFトークンによる認証を追加し、許可するtpl指定(allow_tpl_path)を個別指定しなくてもいいように改修

ポストインクルードや htmx など、Ajax による部分テンプレートへのアクセス時に、許可するtplを private/config.system.yaml で指定(allow_tpl_path)する必要がなくなりました。

Ver. 2.11.25 より、URLコンテキストで tpl を指定する場合は private/config.sytem.yaml で指定したい tpl を設定する必要がありました。

allow_tpl_path: [inlcude/search.html, hoge/custom.html]

これは、tpl コンテキストを指定することで、同一コンテンツの複数のページが表示できてしまう問題をtpl に指定可能なパスを設定することで回避するためでしたが、Ver. 3.1.17 より Ajax によるテンプレートへのアクセスに限り、CSRFトークンによる認証でこの問題を回避するように変更されました。

これにより、ポストインクルードや htmx を利用する場合に、forbid_tpl_url_context: off にする、tpl に指定可能なパスを allow_tpl_path に指定するなどの準備が必要でしたが、それがなくてもポストインクルードや htmx を利用することができるようになりました。

htmx の場合は以下のような JavaScript を記述することで、htmx によるリクエストのリクエストヘッダーに CSRFトークンを付与することができます。

  document.addEventListener("htmx:configRequest", function(event) {
      const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
      event.detail.headers['X-CSRF-Token'] = csrfToken;
  });

Ajax でないアクセスで tpl コンテキストを利用する場合は、private/config.syetem.yaml でtpl に指定可能なパスを設定する必要があります。

Ajaxリクエストのセキュリティレベルオプションを用意(ajax_security_level)

互換性のため、Ajaxリクエストのセキュリティレベルは段階別に設定できるようになっています。


レベル 説明
0 チェックを行いません。セキュリティ的に安全でないので基本的には指定しないことを推奨します。
1 Referer 及び HTTPヘッダーによる Ajax 判定をチェックします。
2 Referer 及び HTTPヘッダーによる Ajax 判定に加えて、CSRFトークンをチェックします。

private/config.system.yaml で変更することができるようになっています。

ajax_security_level: 1 # ajaxリクエストのセキュリティレベルを設定します。(0: チェックなし 1: RefererとHttpヘッダーを確認 2: CSRFトークン確認)

新規インストール時は最も厳しいセキュリティレベルである 2 となりますが、アップデート時の場合は互換性のため 1 となっております。

セキュリティレベルが 1 や 0 の場合でも Ajax によるテンプレートアクセスの場合は、private/config.system.yaml での設定は不要です。

ACMS_POST_2GET_Ajax

また、今までは ポストインクルードや htmx を利用するばあいに、ACMS_POST_2GET というモジュールを活用してURLの組み立てとリダイレクトを実装していましたが、CSRFトークンによる認証 を行うためには、新しい、ACMS_POST_2GET_Ajax というモジュールを利用する必要があります。

ACMS_POST_2GET_Ajax モジュールを利用することにより、適切にCSRFトークンによる認証が行われるだけではなく、tpl指定がある場合、tplが削除されることなるURLが組み立てられリダイレクトされます。

例えば ポストインクルードでキーワード検索を実装する場合は以下のようなコードになります。

<form action="" method="post" class="js-post_include" target="#jsChangeContents">
  <input type="text" name="keyword" value="" size="15" />
  <input type="hidden" name="tpl" value="include/searchResultSample.html" />
  <input type="hidden" name="bid" value="%{BID}" />
  <input type="submit" name="ACMS_POST_2GET_Ajax" value="検索" />
</form>
<div id="jsChangeContents">
  <p>この部分が置き換わります。</p>
</div>

ポストインクルードや htmx などで Ajax によるテンプレート取得を行う場合は、今後 ACMS_POST_2GET_Ajax モジュールをご利用ください。

最後に

該当する問題がありましたら、お早めにバージョンアップのご検討をお願いいたします。
また、迅速にご報告いただいたユーザーの皆さま、誠にありがとうございました。

今後もご報告いただいた内容に対して真摯に受け止め修正と改善を行ってまいります。
今後ともどうぞよろしくお願いいたします。

ポストインクルードの準備・設定

Ver. 2.11.25 以降のバージョンでデフォルトで tplコンテキストの設定が無効になるような設定になりました。

理由:URLを変更すれば好きなテンプレートを簡単に指定することが出来ることにより、意図しないページが無制限にできてしまいため、セキュリティ・SEO対策としてURLコンテキストによるtpl指定は制限するようになりました。

ポストインクルードで引っ張ってくるテンプレートは、基本テンプレートを指定してインクルードするので、上記の制限によりうまくインクルードされない可能性があります。 CMSのバージョンによって対応が変わりますので、以下ご確認ください。

Ver. 3.1.16 以下 & Ver. 2.11.25 以上の場合

例えば以下のようなTPL指定をするとURLは「https://example.com/xxxx.html/tpl/include/thumbnail.html」になり、URLでtpl指定をしてしまうことになります。

<input type="hidden" name="eid" value="%{EID}" />
<input type="hidden" name="tpl" value="include/thumbnail.html" />

このままでは制限をうけて正常にインクルードできないので、以下の方法により回避します。

設定を全体を解除する(非推奨)

private/cofig.system.yaml にある forbid_tpl_url_context を off に設定します。

forbid_tpl_url_context: off

この方法は、制限をなくしてしまう設定になるので、セキュリティ・SEO的に非推奨になります。古いバージョンからのアップデートで一時的にオフにしたいなど、理由がある場合のみ指定ください。

設定を部分的に解除する

private/cofig.system.yaml にある allow_tpl_path にポストインクルードで利用するファイルを指定します。複数ある場合にはカンマで区切って設定します。

allow_tpl_path: [inlcude/search.html, hoge/custom.html]

Ver. 3.1.17 以上の場合

Ver. 3.1.17で、特に意識・設定することなく、ポストインクルードを利用できるように改善されました。

改善内容

private/config.system.yaml の「ajax_security_level」の設定に応じて、ポストインクルード(Ajax)のアクセスを認証することにより、直接のGETリクエストと、ポストインクルード(Ajax)でのリクエストを区別することが出来るようになり、tpl指定の制限をしたまま、ポストインクルード(Ajax)のリクエストは許可するということが出来るようになりました。

ajax_security_level: 2 # ajaxリクエストのセキュリティレベルを設定します。(0: チェックなし 1: RefererとHttpヘッダーを確認 2: CSRFトークン確認)

Ajaxセキュリティレベル

レベル0

ajax_security_level: 0

レベル0は、特になにも認証をしないので、基本的には設定しないでください。

レベル1

ajax_security_level: 1

レベル1は、RefererとHttpヘッダーを確認して、Ajaxリクエストであることを確認します。ポストインクルードを利用すれば自動でHTTPヘッダーは付与されるので、特に意識する必要はありません。

もしポストインクルードではなく独自のAjaxリクエストで、HTMLを取得する場合は以下HTTPヘッダーを付与ください。

Referer: https://example.com/xxxxx/xxxx.html
X-Requested-With: XMLHttpRequest

レベル2

ajax_security_level: 2

レベル2は、レベル1のチェックに加え、CSRFトークンを使った認証を行います。ポストインクルードを利用すれば自動でHTTPヘッダーにCSRFトークンが付与されるので、特に意識する必要はありません。

もしポストインクルードではなく独自のAjaxリクエストで、HTMLを取得する場合は以下HTTPヘッダーを付与ください。

Referer: https://example.com/xxxxx/xxxx.html
X-Requested-With: XMLHttpRequest
X-Csrf-Token: xxxxxxxxxxxxxxxxxxx

X-Csrf-Token に設定する値は、テンプレートに「check-csrf-token」文字列を追加することにより、CMSで追加できます。例えばクラス名で指定するなどです。

<div class="check-csrf-token">
...
</div>

CSRFトークンは、metaタグに生成されています。JavaScriptなどでこの値を取得してご利用ください。

<meta name="csrf-token" content="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
const csrfToken = document.querySelector('meta[name="csrf-token"]').content

CSRFトークンを生成すると、セッションがスタートしてしまうので、ブラウザキャッシュなどが利用できなくなります。必要なページのみ指定するようにしてください。

承認申請画面でデフォルト承認者を設定できるようにするカスタマイズ

今回のカスタマイズのゴールは、採用情報の投稿者Jが特定の編集者Hに承認依頼を行うことを便利にする、ミスを減らすことができるようにすることを考えてカスタマイズを進めていく事にします。


今回のサイトの構成

システムとしては a-blog cms プロフェッショナル版 を利用します。

ルートブログや子ブログに架空のダミーデータでユーザーを用意しています。実際には、もっと多くの人が登録されている場合もありますが、それぞれ 管理者・編集者・投稿者 の権限のユーザーを用意しました。

ルートブログ / bid=1



お知らせ / news / bid=2



採用情報 / recruit / bid=3



標準的な承認画面


標準的には、全員(編集者, 管理者)が選択された状態になっております。以下に実際の 選択UI を触れるようにしています。

今回の業務フローとして、承認者は 杉本さん(投稿者J)が、上司である村瀬さん(編集者H)に依頼したいところが、5人に対して承認依頼のメールを送ってしまう事になります。

具体的なカスタマイズ目標

ユーザーのカスタムフィールドでデフォルトの承認依頼をしたい人を設定できるようにする をメインの目標とします。加えて部署名も表示できるようにし、もし、上司である村瀬さん(編集者H)が不在の際に、同じ部署の承認可能な方が誰かも分かるようにします。


各ユーザーの情報を設定できるようにする

ユーザー情報にカスタムフィールドの設定することができるようにします。

  1. 承認したい人を選択できる SELECT UI
  2. 部署名を設定できるような INPUT UI

themes/*利用しているテーマ名*/admin/user/field.html を編集します。

admin/user/field.html

<table class="acms-admin-table-admin-edit">
  <tr>
    <th>部署名</th>
    <td>
      <input type="text" name="division" value="{division}" class="acms-admin-form-width-mini" />
      <input type="hidden" name="field[]" value="division" />
    </td>
  </tr>
  <tr>
    <th>承認ユーザー</th>
    <td>
    <select name="approval_user" class="acms-admin-form-width-mini">
    <option value=""></option>
    <!-- BEGIN_MODULE User_Search id="approval_user_list" -->
    <!-- BEGIN user:loop -->
    <option value="{id}" \{approval_user:selected#{id}\}>{name}</option>
    <!-- END user:loop -->
    <!-- END_MODULE User_Search -->
    </select>
    <input type="hidden" name="field[]" value="approval_user" />
    </td>
  </tr>
</table>

承認ユーザーを選択肢を表示させるために bid=1 のモジュールID 設定に User_Search モジュール id="approval_user_list" をグローバル化して設定します。


条件設定については運用次第ではありますが、他のブログのユーザーが表示された方がいい場合には、bid=1 を指定し、階層の設定を「下階層のブログも含める ( descendant-or-self )」を設定ください。
同一ブログのユーザーのみの場合には、bid を指定しないようにすることで子ブログ内のユーザーのみをリスト表示が可能です。

ログインユーザーの情報をどこでも利用できるようにする

a-blog cms の情報をいつでも、どこでも利用できるようにする際には、グローバル変数という変数に値を持たせることで管理できるようにします。例えば、%{NOW_DATE} のようにテンプレート書くと今日の日付を表示ができるようなものになります。

今回はログインしている際に、ユーザーのカスタムフィールド approval_user をグローバル変数化し %{APPROVAL_USER} で、テンプレートのどこでも利用することを可能にします。

extension/acms/hook.php

public function extendsGlobalVars(&$globalVars)
{

    if ( SUID ) {
        $field = loadUserField(SUID);
        $globalVars->set('APPROVAL_USER', $field->get('approval_user'));
    }

}

config.server.php

hook.php の記述を有効にするには、config.server.phpHOOK_ENABLE1 に設定を変更する必要があります。

define('HOOK_ENABLE', 1);

承認画面のカスタマイズ

標準的な承認画面 のところで表示していた画面の URL は
http://localhost/recruit/entry-52.html/tpl/ajax/revision-preview.html?rvid=4
のようになっていました。

http://localhost/recruit/entry-52.html のページの情報を
/tpl/ajax/revision-preview.html でテンプレートを置き換えて表示させています。

/themes/system/ajax/revision-preview.html が対象のテンプレートになりますが、このテンプレートファイルをご利用中のテーマにコピーしてカスタマイズするようにしてください。

ajax/revision-preview.html

<!-- BEGIN_MODULE Approval_NextUsergroup -->
<div class="acms-admin-margin-top-small">
  <span class="acms-admin-label acms-admin-clear"><!--T-->次の承認者<!--/T--></span>
</div>
<select name="receiver" id="input-nextGroup"
  class="acms-admin-revision-sidebar-select js-select2 acms-admin-margin-top-small"><!-- BEGIN group:loop -->
  <option value="{nextGroup}:0"><!--T-->全員<!--/T-->({nextGroupName})</option>
  <!-- END group:loop --><!-- BEGIN user:loop -->
  <option value="{nextGroup}:{user_id}" 
  <!-- BEGIN_IF [%{APPROVAL_USER}/eq/{user_id}] -->
   selected="selected"
  <!-- END_IF --> 
  >{user_name} <!-- BEGIN division:veil -->({division})<!-- END division:veil --></option><!-- END user:loop -->
</select>
<input type="hidden" name="approval[]" value="receiver" />
<input type="hidden" name="current_group" value="{currentGroup}" />
<!-- END_MODULE Approval_NextUsergroup -->

オマケ : ユーザー管理の一覧にも部署名を表示

ユーザーの管理画面の URL は http://localhost/bid/3/admin/user_index/ のようになっていました。その場合には themes/system/admin/user/index.html に元のテンプレートがありますので、ご自身のテーマの同階層にファイルをコピーしてカスタマイズしてください。

admin/user/index.html

<div class="acms-admin-summary-body">
	<strong>{name}</strong> / {code}<br>{mail} 
</div>

が名前やメールアドレスを表示させているところになりますので、ここに上記で追加したカスタムフィールド divisionapproval_user を追加します。

approval_user が数字で分かりにくいですが、今回は設定があることだけをお伝えする事とし、id を文字列にする方法については別の機会で紹介させていただきます。

<div class="acms-admin-summary-body">
	<strong>{name}</strong> / {code}
	<!-- BEGIN division:veil -->/ {division}<!-- END division:veil -->
	<!-- BEGIN approval_user:veil --> ({approval_user})<!-- END approval_user:veil --><br>{mail} 
</div>

<!-- BEGIN division:veil -->〜<!-- END division:veil --> で囲まれている点を補足しておきます。これは {division} に情報が何も編集されない時には囲まれている部分を表示させないという記述になります。値が無い時に / や () だけ表示されないようにしています。

最後に

今回は、プロフェショナル版での承認機能についてのカスタマイズについて紹介させていただきました。 普段、使えない機能となっておりますが、MYPAGE の開発ライセンス から試しに使ってみたいドメインを設定することで、購入することなく試すことが可能です。

標準的な機能として用意されていないものであっても、今回のようにカスタマイズでしっかり希望の運用ルールに近づけることも出来ます。もし、こうしたいがカスタマイズで難しい場合にはご相談ください。

Custom Search API との連携

JSON形式のデータを表示させることができるビルトインモジュール Json_2Tpl とGoogleの検索結果をJSON形式で取得することができるCustom Search API を連携させて Google の検索結果を使用するサイト内検索を実装することができます。

a-blog cms標準のサイト内検索機能はエントリー単位の検索ですが、 Custom Search API を連携させることで、一覧ページやトップページなどのページも検索対象に含めることができます。また、検索結果自動的に関連度順に表示されるため、普段Googleで検索するときのような検索体験を実現することができます。

Googleのサイト内検索を実装するためには以下の情報が必要になります。

  • GoogleのAPIキー
  • Googleカスタム検索エンジンの検索エンジンID

準備1: APIキーを用意する

Google Cloud Platform の管理画面からAPIキーを作成してください。 https://console.cloud.google.com/

必要であればIP アドレス(ウェブサーバー、cron ジョブなど)でAPIキーを使用できるウェブサイト、IP アドレス、アプリケーションを制御してください。

※Json_2Tpl ではwebサーバー側でHTTPリクエストを送信するため、HTTPリファラー(URL)による制限はできません。


HTTPリファラー(ウェブサイト)や、IP アドレス(ウェブサーバー、cron ジョブなど)でAPIキーを使用できるウェブサイト、IP アドレス、アプリケーションの制御を設定する画面

また、APIの制限も行いましょう。


APIの制限をする

準備2: 検索エンジンの設定

Google カスタム検索エンジンにログインして、検索エンジンの作成と検索エンジンIDの取得をします。
https://programmablesearchengine.google.com/

1. 検索エンジンの作成

検索対象のドメインと任意の名前を設定して検索エンジンを作成します。
注意点として検索できるサイトでないといけないので、ablogcms.ioなどではなく、ご自身のサイトなどを設定ください。


検索エンジンの作成

2. 検索エンジンIDの取得

コントロールパネルの「基本」タブ内、検索エンジン IDをコピーします。


検索エンジンIDの取得

サイト内検索の実装

APIキーと検索エンジンIDがそろったらa-blog cmsのカスタマイズを行い、Googleの検索結果を使用したサイト内検索を実装します。

1. モジュールIDの作成・設定

Json_2Tpl モジュールのモジュールIDを作成し、表示設定のJSONファイルに以下のURLを設定します。

https://www.googleapis.com/customsearch/v1?key=認証キー&cx=検索エンジンID&q=%{KEYWORD}&hl=ja&start=%{start}

&start=%{start} の部分はページャー機能を実装する場合に必要になります。



2. テンプレートの記述

Json_2Tplのテンプレートを書くためには、jsonの中身を確認する必要がありますが、例えばキーワードを "api" としたとき、検索結果のデータを1件目から取得したい場合は下記のURLをブラウザのアドレスバーに入力して検索すると、jsonの中身を確認することができます。 https://www.googleapis.com/customsearch/v1?key=認証キー&cx=検索エンジンID&q=api&hl=ja&start=1

jsonデータの中身が確認できたら、Json_2Tpl の テンプレートの書き方 を参考に検索結果を表示するテンプレートを記述します。

<!-- BEGIN_MODULE Json_2Tpl id="google_custom_search" -->
<div class="google-search clearfix">
	<!-- BEGIN items:loop -->
	<div class="search-item clearfix">
		<h2>
			<a href="{link}">{htmlTitle}[raw]</a>
		</h2>
		<p class="link">{link}[trim(100, '...')]</p>
		<div class="acms-col-md-10">
			<p>{snippet}</p>
		</div>
		<div class="acms-col-md-2 acms-sp-hide">
			<!-- BEGIN pagemap -->
			<!-- BEGEN metatags:loop -->
			<img src="{og:image}[resizeImg(130)]" width="130">
			<!-- END metatags:loop -->
			<!-- END pagemap -->
		</div>
	</div>
	<!-- END items:loop -->

  <ul class="search-pager">
		<!-- BEGIN queries -->
		<!-- BEGIN previousPage:loop -->
		<li class="link-item">
			<a href="search.html?keyword=%{KEYWORD}&start={startIndex}" class="btn">前</a>
		</li>
		<!-- END previousPage:loop -->

		<!-- BEGIN nextPage:loop -->
		<li class="link-item">
			<a href="search.html?keyword=%{KEYWORD}&start={startIndex}" class="btn">次</a>
		</li>
		<!-- END nextPage:loop -->
		<!-- END queries -->
  </ul>
</div>
<!-- END_MODULE Json_2Tpl -->

ページャーは、a-blog cms標準機能であるクエリストリングの値をグローバル変数として取得するを利用して実装しています。
具体的には、{startIndex} の値をクエリストリングに渡すことで、Json_2Tpl モジュールの表示設定、JSONファイルで設定したURLの %{start}のグローバル変数が {startIndex}を参照するようになります。

次にキーワード検索をするためのフォームを設置します。

<form action="/search.html" class="search-form" method="post" role="search" aria-label="検索フォーム">
	<input type="hidden" name="tpl" value="/search.html">
	<input type="hidden" name="query[]" value="keyword">
	<input type="hidden" name="query[]" value="start">
	<input type="hidden" name="bid" value="%{BID}">
        <input type="hidden" name="start" value="1">
	<input type="text" name="keyword" class="search-form-text" value="%{KEYWORD}" size="15" placeholder="検索キーワード">
	<span class="search-form-btn-wrap">
		<button type="submit" name="ACMS_POST_2GET" class="search-form-btn"><span class="acms-icon-search"></span>
		</button>
	</span>
</form>

完成


完成形

検索フォームに適当な検索ワードを入力し、検索ボタンをクリックした時に、画像のような検索画面が表示されていれば完成です。スタイルやHTMLの構造を変えることで、オリジナルのレイアウトにすることも可能です。

追記:複数ワード対応

上記の実装で検索はヒットするようになりましたが、複数ワードをスペースで区切って検索すると検索結果が出てきません。

方法としては、半角スペース&全角スペースを半角カンマに置き換えたグローバル変数 %{API_KEYWORD} を作成し、利用する事で複数ワードでの検索に対応できるようになります。

config.server.php

define('HOOK_ENABLE', 1);

extension/acms/Hook.php

    /**
     * グローバル変数の拡張
     *
     * @param array $globalVars
     */
    public function extendsGlobalVars(&$globalVars)
    {
        // $globalVars->set('key', 'var');
        $globalVars->set('API_KEYWORD', str_replace(' ', ',', mb_convert_kana(KEYWORD,'s','utf-8')));

    }
  1. モジュールIDの作成・設定 の Json_2Tpl の設定画面で %{KEYWORD} と設定していた部分を %{API_KEYWORD} と修正ください。