オブジェクトのプレビューの機能向上

先月、記事「オブジェクトのプレビュー機能を実装」でプレビュー機能の実装方法を紹介しました。しかし、この実装ではいくつかの課題があることに気付きました。

  • 環境変数に設定しているCMSのユーザーが「管理者」でない場合、他人が所有する公開済のオブジェクトが取得できない
  • リビジョンのプレビューができない

前者はRESTful APIのエンドポイントにアクセスする際トークンを渡さなければ良いのですが、後者と合わせてプラグインでRESTful APIのメソッドを追加して解決することにしました。

プラグインの実装

以前から計画していた「JamstackSupport」プラグインという名前で作成することにします。(Webhookを叩く機能などを追加予定です。)api_methodsに追加するエンドポイントの情報を記述します。requires_loginを指定していないので、エンドポイントアクセス時にトークンの送信が必要になります。

{
    "label"      : "JamstackSupport",
    "id"         : "jamstacksupport",
    "component"  : "JamstackSupport",
    "version"    : "0.1",
    "author"     : "Hideki Abe",
    "author_link": "https://www.anothersky.jp/",
    "description": "Support Jamstack.",
    "api_methods": {
        "v1": {
            "preview": {
                "component": "JamstackSupport",
                "method": "preview_object",
                "allowed": ["GET"]
            }
        }
    }
}

そして、JamstackSupport.phppreview_objectで処理をしてJSONを返すようにします。lib/Prototype/RESTfulAPI/v1.phpのgetメソッドを流用してカスタマイズしました。APIユーザーであることを確認するために、プラグインの設定画面にUser IDを登録することを検討しています。

<?php
require_once LIB_DIR . 'Prototype' . DS . 'class.PTPlugin.php';

class JamstackSupport extends PTPlugin {

    public function __construct () {
        parent::__construct();
    }

    public function preview_object ( $app ) {
        // lib/Prototype/RESTfulAPI/v1.phpのgetメソッドを流用しカスタマイズ
        // User IDでAPIユーザーであることを確認する
        // 最後の3行以外は掲載省略
        $obj = $obj->load( $app->object_id, null, $cols );
        $obj = $app->object_to_resource( $obj, $columns );
        $app->print_json( $obj );
    }
}

これにより、/powercmsx/api/v1/1/entry/preview/[object_id]でプレビューしたいオブジェクトが取得できるようになりました。 Postmanを利用して実装したpreviewメソッドの動作確認をしている様子

Next.jsの実装変更

記事「オブジェクトのプレビュー機能を実装」で紹介したコードを少し変更します。具体的には、getObjectメソッドでプレビューしたいオブジェクトを取得していましたが、runFetchメソッドで先程作成したプレビューメソッドにアクセスするようにします。また、プレビューデータでオブジェクトIDを渡すようにしました。記事詳細ページ([basename].js)もrunFetchメソッドを利用するように変更します。

pages/api/preview.jsのコードを一部抜粋して紹介します。

const options = {
  cols: 'id,basename',
};
const endpoint = `/entry/preview/${req.query.id}`;
const response = await client.runFetch(endpoint, 'get', 1, options, {}, token);

const json = await response.json();
res.setPreviewData({
  id: json.id,
  basename: json.basename,
  token: token,
});

変更完了後、ステータス・リビジョンにかかわらずプレビューできることが確認できました。