株式会社HAMWORKS
🤖

DataAPIのエンドポイントから MTAppjQuery の user.js にブログIDを自動取得するTips

2021/08/05に公開

MTAppjQueryに限った話しではありませんが、Movable Typeではサイトや子サイトを作成されたときに生成される blog_id と呼ばれる一意のIDが付与されます。このIDは作成した順番に生成されるため例えば本番環境と開発環境でサイトや子サイトを作成してたときに作成順を間違ってしまうと blog_id が本番と開発で異なる状態になるケースがあります。

Dumpデータをリストアする場合は、同じIDの状態で維持できますが管理画面から任意のタイミングで生成されたものは作成順としてIDが付与されます。

blog_id は MTAppjQueryのuser.js(管理画面カスタマイズ)でも良く利用されるため、このIDを名前で定義して MTAppjQueryの提供メソッド mtappVars.blog_id で管理画面で現在のいるサイト・子サイトの blog_id を取得することが可能です。

mtappVars

user.jsは管理画面でテンプレートとして利用する場合は、MTMLタグが利用できるためよくconfigのモジュールに定数の値として数字をセットしてuser.jsに渡していました。
このようにMTMLで設定したIDを変数管理してuser.js側ではオブジェクトのkeyとvalueにしておくことで mtappVars.blog_id と比較するようことができます。

// config テンプレート モジュール
<mt:SetVars>
site_id_parent  =1
site_id_test    =2
</mt:SetVars>
<mt:Include module="config" parent="1" note="親サイトの config モジュールを読み込み" />
const site_id = {
  parent: <mt:Var name="site_id_parent" />,
  test: <mt:Var name="site_id_test" />
};
// サイトのウェブページのみを対象に判定する
if(mtappVars.blog_id == site_id.parent && mtappVars.screen_id == 'edit-page'){
  // ここにウェブページの編集画面のカスタマイズを書く
}

しかし、この場合 SetVars で定義したIDは手動でセットした数字になるため、先程の開発と本番と異なる場合は変える必要が出てきます。
そこで、DataAPIのエンドポイントから blog_id を抽出して本番と開発でも異なる環境下でも site_id が自動で変わるように実装してみました。

注意点としてはData APIを利用するため、サイトごとにData APIは有効にしておく必要があります。

Data APIで site_idを取得する

まずは Data APIの site_idのエンドポイントから site_id をみてみましょう。
以下の例は 親サイト・子サイトの一つずつ設定した場合のレスポンス例になります。

https://XXXXX/[mt-instaldirectory]/mt-data-api.cgi/v4/sites とブラウザやAPIクライアントでエンドポイントを叩くことで以下のレスポンスが返ってきます。

items の中には配列のオブジェクトとして、各サイト・子サイトの情報が親と子関係なく配列として返ってきます。
親 → 子 という上下関係はなく、サイトや子サイトが追加されることで配列に要素が追加される仕様になります。
親と子の関係を表す部分は、 parent という key の情報になります。親サイトの場合は parent となるサイトがないため valuenull が返ってきます。
子サイトの場合は、 parent に入る値は、親のIDと名前が付与されます。この部分で親と子の関係の識別をしている仕様になります。

{
  "items": [
    {
      "archiveUrl": "https://XXXXXXX.com/",
      "ccLicenseImage": "",
      "ccLicenseUrl": "",
      "class": "website",
      "createdBy": {
        "displayName": "ユーザ名",
        "userpicUrl": null
      },
      "createdDate": "2021-07-27T22:39:06+09:00",
      "customFields": [
        
      ],
      "dateLanguage": "ja",
      "description": null,
      "host": "XXXX.com",
      "id": "1",
      "language": "ja",
      "modifiedBy": {
        "displayName": "ユーザ名",
        "userpicUrl": null
      },
      "modifiedDate": "2021-07-27T22:40:21+09:00",
      "name": "親サイト名",
      "parent": null,
      "pingOthers": [
        
      ],
      "relativeUrl": "/",
      "serverOffset": "9",
      "timezone": "+09:00",
      "updatable": false,
      "url": "https://XXXXXXX.com/"
    },
    {
      "archiveUrl": "https://XXXXXXX.com/children/",
      "ccLicenseImage": "",
      "ccLicenseUrl": "",
      "class": "blog",
      "createdBy": {
        "displayName": "ユーザ名",
        "userpicUrl": null
      },
      "createdDate": "2021-08-02T11:45:03+09:00",
      "customFields": [
        
      ],
      "dateLanguage": "ja",
      "description": null,
      "host": "XXXX.com",
      "id": "2",
      "language": "ja",
      "modifiedBy": {
        "displayName": "ユーザ名",
        "userpicUrl": null
      },
      "modifiedDate": "2021-08-03T12:31:02+09:00",
      "name": "子サイト名",
      "parent": {
        "id": "1",
        "name": "親サイト名"
      },
      "pingOthers": [
        
      ],
      "relativeUrl": "/test/",
      "serverOffset": "9",
      "timezone": "+09:00",
      "updatable": false,
      "url": "https://XXXXXXX.com/test/"
    }
  ],
  "totalResults": 2
}

user.jsでIDを名前で識別できるようにする

ここから本題になります。
Movable Type のエンドポイントも含め blog_id がベースになっています。MTMLでも同様に blog_id で識別させて必要なコンテンツデータや記事にアクセスして出力させています。

管理画面やサイト含めIDは識別しずらいため名前で定義することで視認性を高めることができます。

エンドポイントを取得するために axiosを設定しておく

MTAppjQueryだから $.ajax となるかもしれませんが、ここでは axios を利用します。
※あくまでも好みの問題なので Ajaxに関してはお好きなものを利用して構いません。

システム管理画面からプラグイン→MTAppjQueryの設定にアクセスします。
システム全体に適用する設定からuser.js の読み込み直前のテキストフィールドにaxiosのコードを挿入します。今回はCDNを利用しています。

axios

user.jsを設定したテンプレートにアクセスして、以下のコードを挿入します。

siteList に エンドポイントを設定します。

次に siteIds に 必要なkeyをセットして扱いやすいデータに加工しています。 ここでは idnameclassparent の情報を入れておきました。

class は、親サイトの場合は website 子サイトの場合は blog になります。Movable Type 6 のときまでは、ウェブサイトとブログという位置づけだったための名残になります。

Movable Type 7からは表記名がサイト・子サイトと表現することなりましたが、後方互換という意味で今でも websiteblog を利用しています。

parentSiteschildrenSites で親サイトと子サイトでフィルタリングします。このようにしておくことで親と子で識別しやすくできるかと思います。

getBlogId では、引数に targetname を設定しています。parentSiteschildrenSites で必要なサイトの情報を配列でもたせたので、 配列の操作から id を抽出し 取り出せた配列をStringにしてから数字に変換しています。

最後に site_ids に各keyごとに作成した getBlogId の関数を呼びだしてIDをセットします。

site_ids.parentSiteId で定義した オブジェクトにアクセスすると 1 (任意のID)を取得することができます。

名前の識別の場合、管理画面側で名前を変えられると値が取得できなくなってしまいますが、ブログの名前は基本変えないルールにすれば IDが変わってもコード側で柔軟に対応できるかと思います。

(async function ($, window, document, undefined) {

const siteList = await axios.get('/[MTインストールディレクトリ]/mt-data-api.cgi/v4/sites')

const siteIds = siteList.data.items.map(value => {
  return { id: value.id, name: value.name, class: value.class, parentId: value.parent }
})
/*
siteIds
[
  {id: "1", name: "Movable Type Knowledge", class: "website", parentId: null}
  ~~~~
]
*/
const parentSites = siteIds.filter(v => v.class === 'website' && v)
const childrenSites = siteIds.filter(v => v.class === 'blog' && v)
const getBlogId = (target, name) => target.map(v => v.name === name && v.id).join() - 0
const site_ids = {
  parentSiteId: getBlogId(parentSites, 'Movable Type Knowledge'),
  testSiteId: getBlogId(childrenSites, 'テスト')
}
console.log(site_ids.parentSiteId)  // 1
})(jQuery, window, document)

Data APIを利用することで、このように従来のMTMLでやっていたことが エンドポイントだけで加工ができるようになります。

blog_idのほかにもエンドポイントを活用して user.js を作り上げると そもそもMTのテンプレートにuser.jsを出力させずに GithubなどのGitで管理してデプロイ時にMTのドキュメントルートにビルドさせるようにすればMTの管理画面ではビルドさせれた user.jsのパスを指定するだけで管理画面をカスタマイズも可能です。

Jamstackなどでテンプレートを作った際に user.jsだけは MTテンプレートになってしまうのは管理的な意味で二重管理(コードのコピペ)になってしまいます。

user.js用のリポジトリを用意しておけば MTのテンプレート不要で分離できる運用が可能になります。

今回はData APIを使ってよくある blog_id の管理方法を紹介しました。

一度活用してみてはいかがでしょうか。

株式会社HAMWORKS
株式会社HAMWORKS

Discussion