MTMLとJavaScriptで、Movable TypeをHeadless CMSとして使う

  • 投稿日:
  • by
  • カテゴリ:

Headless CMSとMovable TypeとData API

Headless CMSを簡単に説明すると、「コンテンツをグラフィカルな表現で閲覧するための機能をもたない、データを管理するためのバックエンド側の機能のみを提供するCMS。一般的にコンテンツの公開はAPIを通じて行われ、CMSとは切り離された方法でグラフィカルな表現に変換される。」といったところでしょうか。(英語版Wikipediaにはページはあったのですが、やや偏っている印象もあったので引用はしませんでした。)デバイスの多様化に伴い、数年前からよく聞くようになってきたCMSのトレンドの一つだと思います。

MTはテンプレートを書いてファイルとして書き出すのが基本なので、これを「グラフィカルな表現に変換する機能」すると、その面から見たときはHeadless CMSではないと考えるのが妥当だと思います。

しかし一方で、MTではData APIというRESTfulなAPIを使ってコンテンツを取り出すこともできるので、これを使えばMTをHeadless CMSと考える(Headless CMSとして使う)こともできると思います。

この記事では、

  • Data APIを利用して
  • しかしJavaScriptなどのプログラムを意識することなく
  • 馴染みのあるMTタグを使って
  • MTをHeadless CMSとして使う

ということを実現できるツールを紹介します。

MT Data API React

MT Data API Reactは、Data APIで取得したデータをMTタグで書いたテンプレートでHTMLに変換して表示することのできるツールです。

以下のURLで試すことができます。「ブログのエンドポイント」に試したいブログのData APIのエンドポイントを入れれば、そのデータでブラウザ上で対話的に動作を確認することができます。

https://usualoma.github.io/mt-data-api-react/docs/playground.ja.html

「開発環境」タブの手順で「SFTPでテンプレートを更新して確認」や、「開発環境」のタブの手順で「本番環境では軽量化のために書き出したテンプレートを利用する」といったこともできます。

特徴

MTタグを書くだけで簡単に設置できる

これが最大の特徴ですが、JavaScriptを1行も書くことなくMTタグを書くだけで設置できます。

「JavaScriptを使ってAPIで取得したデータを表示する」というのもシンプルな作業ではあるのですが、実際にやるとなると「Data APIの仕様を理解する」という学習は必要になります。またJavaScriptを使うので安易に実装するとXSSなどの脆弱性に繋がる可能性があります。

MovableTypeにある程度なれている場合には、MTタグを使ってHTMLを構築するのは容易なはずなので、新しい学習のコストや脆弱性のリスクなしに、簡単に設置することができます。

ただこの部分には課題もあり、現状では使えるタグは少ないので、「サイト全体を構築する」ということはまだ難しい状態です。

JSはそれほど重くない

読み込みに必要なJSは、圧縮した状態で90KBほどです(2019年12月現在)。軽いとはいえないサイズですが、利便性とのトレードオフで考えれば許容できるサイトも多いのではないかと思います。

用途

外部のサイトへの埋め込み

メインのサイトの表示としてではなく、外部のサイトへの埋め込みの用途として利用できると思います。

  • 「新製品の特設サイト」と「コーポレートサイト」を別のMT、別の組織で管理している
  • 「コーポレートサイト」でも「新製品」のニュースを表示したいが、デザインは「コーポレートサイト」の方で管理したい

というケースで、従来であれば「JSON形式でファイル書き出してからAJAXで読み込んで表示」という手順になったと思いますが、これを(内容を示し合わせた)JSONファイルを書き出したりすることなく、表示する側で柔軟に管理できるようになります。

Rubyの関数オブジェクト

  • 投稿日:
  • by
  • カテゴリ:

tl;dr;

基本的には以下のページで説明されているとおりだと思います。

この記事は、これらを少し長めのコードで試してみたものです。

関数オブジェクトを取得

Object#methodで取得できるとのことで、まずは試してみました。

以下のことが分かりました。

  • トップレベルでのメソッド定義はmodule Kernelにプライベートメソッドとして追加される
    • トップレベルのselfであるmainで呼べるようになる
  • method(:hello) (つまり self.method(:hello) で)トップレベルの hello をオブジェクトとして取得できる
  • 定義したクラスのメソッドも instance.method(:hello) で取得できる

レシーバの確認

Object#methodから返ってくるのはclass Methodのオブジェクトで、「メソッドの実体(名前でなく)とレシーバの組を封入します」とのことなので、どのような意味か確認しました。

Object#methodを呼んだ際のレシーバが、暗黙のレシーバであるselfとして封入されていそうです。

Procはどうなっているか?

暗黙のレシーバの確認をしていて、そういえばProcだどどうなんだろうと思って調べてみました。

Procは「ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです」とのことなので、selfへの参照も含まれるということだと思います。

class UnboundMethodの存在

ここまで忘れていましたが、Module#instance_methodを使うと、レシーバをもたないオブジェクトを取得することができるようです。

Module#instance_method に「バインドできるのは、 生成元のクラスかそのサブクラスのインスタンスのみです。」とあるとおり、確かにサブクラスでもないObjectをbindしようとしたらTypeErrorになりました。

まとめ

  • Object#methodで関数オブジェクトを取得できる
  • 関数オブジェクト(MethodやProc)はレシーバの情報ももっていて、オブジェクトをcallした場合にはそれが暗黙のレシーバとして使われる
    • レシーバをもたないclass UnboundMethodもあるが、UnboundMethod#bindしないと呼べない

ということのようです。

これは何か?

iOSの「ショートカットアプリ」用のショートカットをサーバー側で生成して、iPhoneからはQRコードを読むだけでインストールできるようにする、Movable Typeのプラグインです。

ShortcutsApp

このプラグインを使って生成したショートカットでは「Data APIのURL」のような設定が最初から埋め込まれているので、iPhone側では何も設定することなく利用することができます。(「Webサービスのパスワード」も埋め込むことができますが、暗号化はされません。その辺りの問題については以前の「iOS12のショートカットアプリとMovable TypeのData API」のサンプルの記事の「サンプルを利用する場合の注意事項」参照してください)

使い方

プラグインのZIPファイルをダウンロードして、Movable Typeへインストールすると利用できるようになります。設定は特に必要ありません。

インストールすると左側のメニューに「ツール > ショートカット.app」が追加され、メニューをクリックすると利用できるショートカットの一覧が表示されます。一覧からは、「インストールボタンのクリック -> iOS端末でQRコードを読み込み -> 表示された画面からインストール」の流れでiOS端末にショートカットをインストールすることができます。

管理者ユーザーでアクセスしている場合には、一覧のインストールボタンの左側にユーザーアカウントの選択肢が表示されます。「パスワードを埋め込む」を選択した場合には、ここで選択したユーザーのWebサービスパスワードが埋め込まれたショートカットを用意できます。これを使うと「管理者ユーザーが代理でMT上で操作を行い、ショートカットの利用者にはメールでインストール用のURLを送る」というような運用をすることができます。

同梱されているショートカット

以下の2つのショートカットが同梱されています。

写真を投稿

「写真」アプリのシェアボタンから、ショートカットを選択するとそのまま記事を投稿できます。以前の記事の「iOS12のショートカットアプリとMovable TypeのData API」のサンプルで紹介したショートカットと同じものです。

「パスワードを埋め込む」を選択していない場合には、投稿時にWebサービスのパスワードの入力が必要になります。

再構築

すべてのテンプレートを再構築します。

システムコンテキストからインストールした場合にはMovable Type 内のすべてのサイトが、サイトのコンテキストでインストールした場合にはそのサイトが、それぞれ再構築されます。

Siriに再構築をお願いすることもできます。

ショートカットの追加

ショートカットは、「テーマ」のように後から追加することもできるようになっています。

ショートカットの書き出しファイルの仕様は以前の記事でも触れたのですが、アプリから書き出されるバイナリファイルをXML形式に変換して編集することが可能です。また、以前の記事の時点からの新しい発見もあって、「ショートカットアプリには、XML形式を再びバイナリに戻して読み込ませる必要がある」かと思っていたところ必ずしもそうではなく「shortcuts://import-shortcut というURLを使った場合には、XML形式のまま読み込ませることができる」ということが分かりました。このプラグインではこの方法を利用して、ショートカットをMTMLを使ったテンプレートで管理しています。バイナリ形式に戻す必要がないため(XMLファイルさえ生成できればよいので)、インストール先のサーバー環境を選ばずに動作するようになっています。

具体的なカスタマイズの手順

手順は以下の通りです。

  1. iOSのショートカットアプリでショートカットを作成する
  2. ファイルとして書き出す
  3. XML形式に変換する
  4. ショートカットの定義(プラグイン独自の shortcut.yaml )を書く
  5. プラグイン内のshortcutsディレクトリの下に入れる

1が非常につらい作業(ショートカットアプリ内で、GUIでかつ限りられた機能だけでのプログラミング)ではありますが、他は特に難しいことはないと思います。基本的にはテーマを追加するのと同じような手順です。

XML形式への変換

Macであれば以下のコマンドが利用できます。

plutil -convert xml1 -o MT用テンプレート.tmpl 書き出したファイル.shortcut

またはDockerを利用できる環境であれば、以下のコマンドが利用できます。

docker run -it --rm -v $PWD:/files usualoma/libplist plistutil -i /files/書き出したファイル.shortcut -o /files/MT用テンプレート.xml.shortcut

shortcut.yamlを書く

ショートカットの定義をshortcut.yamlに書きます。テーマでのtheme.yamlのようなもので、主なキーの意味は以下の通りです。

  • id : ショートカットのID
  • label : MTの管理画面上での名前
  • version : バージョン
  • name : インストール先のショートカットアプリでの名前
  • description : ショートカットの説明
  • install_instruction : インストールの手順などの説明文
  • view : 利用可能なコンテキスト(system、website、blog)
  • template : ショートカットのテンプレートのファイル
  • expires_in : インストール用URLの有効期限の秒数

同梱されているショートカットを雛形にすると簡単かもしれません。

トラブルシューティング

写真の投稿ができない

iOSの問題だと思うのですが、時々ショートカットが正常にインストールできないことがあり、「写真の情報を取得できない」という問題が発生することがあります。この問題は「インストール前に写真アプリを開いておく」ということで発生確率を下げることができそうなのですが、それでも発生することが稀にあります。

発生した場合には、インストールしたショートカットを一度削除して、インストールし直すという手順で修正されると思います。

まとめ

「写真アプリからのシェア操作で投稿できる」というのはなかなか新鮮な体験だと思うので、ぜひ試してもらえればと思います。

またこのプラグインの例ではでは「写真のアップロードから、記事の作成と公開」まで行っていますが、もっとシンプルに「写真をアップローロドするだけ」というようなショートカットも実際の運用では便利だったりすると思うので、ショートカットアプリとData APIを連携は考え方しだいで、いろいろと面白いことができそうな気がします。

この記事について

この記事は Movable Type Advent Calendar 2018 の10日目の記事です。

Happy Holidays!

発生する条件

php.iniで以下のように設定されている時に、multipart/form-dataでUTF-8の内容をPOSTすると文字化けすることがある。(application/x-www-form-urlencodedでは文字化けしない)

mbstring.encoding_translation = On
mbstring.http_input = auto
mbstring.internal_encoding = UTF-8

どんな流れで発生しているか?

PHPではPOST時のハンドラをMIMEタイプ毎に登録する仕組みになっているようで、mbstringでは以下の場所でapplication/x-www-form-urlencodedとmultipart/form-dataで別々のハンドラが登録されている。

https://github.com/php/php-src/blob/master/ext/mbstring/mbstring.c#L680-L681

application/x-www-form-urlencodedの場合はmbstring内でリクエストのボディ全体から文字コードを判定するため、期待した通りUTF-8として扱われる

multipart/form-dataの場合は以下の場所で文字コードの判別が行われるが、

https://github.com/php/php-src/blob/master/main/rfc1867.c#L427-L429

判別対象のデータが例えば以下のようなヘッダー行なので、

Content-Disposition: form-data; name="name"

「mbstring.http_input = auto」 => 「ASCII,UTF-8」だとASCIIだと判定されてしまい。その下に続く内容もASCIIとして「ASCII -> UTF-8」で変換が行われてしまう。

回避方法

以下のような方法がある。

  • 「mbstring.http_input = UTF-8」にする
  • フォーム要素に「multipart/form-data」をつけない
  • 全ての項目のname属性にマルチバイトの文字を入れる

以下のようなフォームであれば文字化けしない。

<form enctype="multipart/form-data" method="POST">
<input name="📛" value="天野" />
</form>

この記事について

iOS12で利用できるようになったショートカットアプリは、自分の好みの「手順」をSiriから呼び出せるようにしたりホーム画面にショートカットを作ったりできるというものですが、その中でどうやら「手順」としてウェブAPIへのリクエストをなかなか自由にできるらしいという話を聞いたので、それならばということで、Movable TypeのData APIとの連携を試してみました。

この記事では、実際の運用でありえそうなパターンとして以下の3つのサンプルを紹介します。

  • 写真を選択して記事を作成
    • 写真は複数選択が可能で、記事には写真を撮影した際の位置情報が付与されます。
  • Evernoteから記事を作成
  • コンテンツタイプとしてURLを収集

それぞれのパターンについて、項目の下の方にエクスポートした「.shortcut」へのリンクを置きました。iOS12でショートカットアプリをインストールしてあれば、実際にショートカットを試してみることもできます。(動画では実行時にパスワードが表示されてしまっていますが、「.shortcut」からインストールされるバージョンでは実行しただけでは表示されないように修正されています。)

対象になるMTのバージョン

コンテンツタイプを利用するサンプルではMT7が必要です。それ以外のサンプルはMT6でも動作します。

写真を選択して記事を作成

ショートカットアプリを使うと「共有シート」に項目を追加して、選択した写真を「ショートカット」に渡すことができるようになります。

このサンプルではそれを使って、以下の操作で記事を作成できるようにしてみました。

  1. 写真を選択(複数可)
  2. シェアボタンから、登録したショートカットを選択
  3. タイトルと本文を指定

写真はアセットとしてアップロードされ、記事の本文に挿入されます。(カスタムフィールド版もあります)写真に位置情報が含まれている場合には、緯度と経度も投稿情報に含まれます。

MTへ画像を投稿.shortcut

カスタムフィールド版

カスタムフィールド版では、「記事」に対して以下のようなベースネームを持つフィールドが設定されていることを想定しています。

  • image
  • latitude
  • longitude

1枚目の画像がimageのフィールドに入り、2枚目以降の画像は本文に挿入されます。

MTへ画像を投稿(カスタムフィールド版).shortcut

Evernoteから記事を作成

メモアプリや編集アプリからデータを受け取り、MTで記事を作成するパターンです。ここではEvernoteと連携させています。

Evernoteでは普通に書くとh2、h3などの細かい指定はできないため、以下のような形で置き換えるようにしています。

  • 太字 -> h3
  • リスト -> そのまま
  • その他 -> divなどは削除し、極力シンプルなHTMLになるようにする

変換結果がやや不安定なので、このサンプルは現実的に使い物になるかどうかはやや微妙です。Markdownの編集アプリからそのままMarkdownとして投稿などの方が現実的かもしれません。

EvernoteからMTへ投稿.shortcut

コンテンツタイプとしてURLを収集

スマートフォンからアクションすると考えると、「記事」よりも細かい(「ソーシャルブックマークに追加」程度の)粒度でなにかできるとよい場合もあると思います。このサンプルでは、以下のようなフローで記事作成を行うための「URLの収集」をショートカットでできるようにしてみました。

  • 記事にするURLをスマートフォンで収集しておく
  • 後で収集したURLを組み合わせて「まとめページ」をつくる

こういった場合には、MT7のコンテンツタイプが使えそうです。

  • URL
  • タイトル
  • og:image
  • 埋め込みHTML

といったフィールドをもつコンテンツタイプを作り、ここにデータを貯めていきます。「タイトル」「og:image」はショートカットの中で自動で取得します。「埋め込みHTML」はURLがTwitterの場合にのみ、oembedのAPIを使って自動で取得します。(少し拡張すれば、YouTubeなどoembedのAPIを提供している他のサービスでも取得できるようになります)

URLをMTへ保存.shortcut

管理画面の方は以下のような雰囲気です。

ref-page-type.png
「参照ページ」コンテンツタイプ
a-ref-page.png
参照ページの編集
curation-page-type.png
「まとめページ」コンテンツタイプ
a-curation-page.png
まとめページの編集

サンプルの紹介は以上になります。

サンプルを利用する場合の注意事項

これらのショートカットアプリではWebアプリのパスワードを利用するのですが、「テキストデータ」としてしか保存する方法が見つからなかったので、「ショートカット」を開くと確認できる状態で保存されます。一応、通常の使用では表示されないように工夫はしているのですが、アプリから開くと容易に表示可能です。特に強い権限を持つユーザーで利用する場合には注意が必要です。(「iCloudキーチェーン」が使えるとよさそうなのですが、それはまだできないようで。)

「ショートカット」の可能性

ショートカットアプリで作成した「ショートカット」は共有のために書き出すことができるのですが、書き出されるファイルは(バイナリの)plist形式なので、少し手を加えることでテキストエディタで編集することもできます。Macであれば以下のようなコマンドを実行することで編集が可能です。(Linuxにも同様の結果を得ることができるコマンドがあります)

テキストとして編集できることにより、例えば以下のようなことができるようになります。

  • エンドポイントの設定の埋め込み
  • ユーザーIDやパスワードの埋め込み
  • メッセージの多言語化

これらを利用することで、例えばリテラシーの高くないユーザーに対しても「(編集済みの)ショートカットを受け取ってインストールするだけで、エンドポイントやパスワードを設定しなくても利用できる」というようにすることができそうです。

まとめ

これはなかなか面白いものだと思います。上のサンプルよりもっとシンプルなものでも、例えば「アセットの一括アップロード」だけでも十分に役立ちそうなので、MTを使っているならば(特別にマッチするような運用ではなくても)普通に便利に使えるような気がしています。 パスワードをそのまま埋め込まざるを得ないなど、現状としては課題もありますが、それらは今後のアップデートを(あまり期待せずに)待ちたいと思います。

MFA - MTで多要素認証を有効にするプラグイン

  • 投稿日:
  • by
  • カテゴリ:

Movable Typeで、サインイン時に多要素認証を利用できるようにするプラグインを公開しました。

現時点では「Eメールによる確認コードの送信」と「Google Authenticator(TOTPが利用できるデバイスやアプリ)による確認コードの生成」に対応しています。(どちらか一方のみを、システムで有効化できます)

いずれのプラグインも、Movable Type 6 でも Movable Type 7 でも利用できます。(どちらかというと Movable Type 7 に最適化されています)

Eメールによる確認コードの送信

デモ

使い方

以下の2つのプラグインをインストールします。

インストールすると全てのユーザーで、サインイン時にEメール経由で送信される確認コードの入力が必要になります。

Google Authenticatorによる確認コードの生成

デモ

インストールに必要な要件

CPANモジュールのDigest::HMAC_SHA1を必要としています。マネージドなレンタルサーバーではインストール済みであることが多いと思います。自分で環境を構築している場合には明示的にインストールする必要があるかもしれません。

また、同じくCPANモジュールのMath::Random::MTは、必須ではないものの推奨されています。このモジュールがインストールされていると暗号的により好ましい設定が生成されます。(ただ、多要素認証はパスワード認証を補強するものであるので、「インストールされていなくてやや好ましくない設定が生成される」状態ではあっても、充分に有用なものであると言えると思います)

使い方

以下の2つのプラグインをインストールします。

インストールすると各ユーザーが、ログイン後に「システム > 多要素認証」のメニュー内の「Google Authenticator」で有効と無効を切り替えられるようになります。Google Authenticatorだけでなく、 AuthyなどTOTPに対応している多要素認証のコードを生成するアプリケーションであれば利用できると思います。有効化されているユーザーでは、サインイン時に確認コードの入力が必要になります。

万が一、デバイスを紛失するなどでコードが生成できなくなった場合には、管理者としてサインインすると「システム > ユーザー」で多要素認証のリセットを行うことができます。(管理者がサインインできなくなった場合にはまずは落ち着いて、その後プラグインをアンインストールしてサインインして、サインイン状態のまま再度インストールするとサインイン状態が維持されるので、そこでリセットの操作を行うことができます)

TODO

現時点では、これらのプラグインでは最低限の機能しか提供されていませんが、今後としては以下のような展開があってもいいかもしれません。

  • リカバリーコードを利用できるようにする
    • デバイスが手元になかったり紛失したりしてしまった場合に利用できる、リカバリーコードを生成できるようになるとよさそうです
  • 有効にする認証のタイプを選択できるようにする
    • 現在は、システム全体でEメールかGoogle Authenticatorのどちらか一方しか利用できないので、ユーザー自身で複数のタイプから選択できるようになるとよさそうです
  • 多要素認証のポリシーをシステム全体で設定できるようにする
    • 「多要素認証を、全てのユーザーで必須にする」などのポリシーを定められるようになるとよさそうです

この記事について

この記事は Movable Type Advent Calendar 2017 の21日目の記事です。

MySQLの「Incorrect string value: '🍣'」問題

  • 投稿日:
  • by
  • カテゴリ:
CREATE TABLE `注文` (
  `内容` TINYTEXT CHARACTER SET utf8mb4
);

なテーブルに、🍣だけをたくさん挿入しようとすると「Incorrect string value: '🍣'」になる。

> INSERT INTO `注文` (`内容`) VALUES (REPEAT('🍣', 64));
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8D\xA3' for column '内容' at row 1

🍣 と 🍺の場合には「Data too long」になる。

> INSERT INTO `注文` (`内容`) VALUES (REPEAT('🍣 と 🍺', 64));
ERROR 1406 (22001): Data too long for column '内容' at row 1

TEXT系のカラムの場合にはカラムのサイズで切ったバイト列に対して正しい文字列かどうかを判定していて、そのためマルチバイトのエンコーディングで文字の途中で切られた場合には(実際には「Data too long」という理由で切られたのに)「Incorrect string value」となっていたということのようでした。

Bug #87100として報告してStatusはVerifiedになったのですが、その後動きがないように見えるので、今後どうなるかはよくわかっていません。

検証環境用のアクセス制限をnginxで11行で設定する

  • 投稿日:
  • by
  • カテゴリ:

どんな状況での話か

  • 公開前や移行時の確認用のサーバーに、念のためパスワードを設定しておきたい
    • 厳密なアクセス制限は必要なく、「URLにアクセスしただけでは見られない」という程度の制限でよい
  • ウェブサーバーはnginxで、バックエンドのサーバーにプロキシしている
  • バックエンドのサーバーで、BASIC認証やDigest認証が使われている
    • つまり、nginxで単純にBASIC認証をかけてしまうと不都合がある

という稀によくありそうな状況で、既存の設定に影響をあたえること無く11行くらいで設定する方法についての話です。

注意事項

ユーザーが思った通りに認証情報を破棄できなかったりするので、本番運用でのアクセス制限として利用するものではありません。

設定前のファイル

な感じです。

設定後のファイル

11行(変数定義などで+4行)追加して以下のようになります。

流れとしては、

  1. サーバーでは、秘密のcookieが確認できない場合にはBASIC認証が必要とのレスポンスを返す
  2. ブラウザでは、BASIC認証が設定されているときのダイアログが表示される
  3. サーバーでは、正しいパスワードが送られてきた場合には秘密のcookieを設定する
  4. それ以降は、秘密のcookieが設定されていればBASIC認証の情報は必要なくアクセスできるようになる

となっています。

あえてBASIC認証のダイアログである必要はなく、セキュリティ的には期待される動作と異なるUIで好ましくはないのですが、403的なページを用意するよりもパスワードのダイアログを出してしまった方が楽だし説明も省けるので、一時的な制限ならこんなのもありではないかと思います。

therubyracerをAlpine linuxでも動くようにするDockerfileを書きました

  • 投稿日:
  • by
  • カテゴリ:

TL;DR

Alpine linux上では単純に$ gem install therubyracerしただけではtherubyracerは動かないのですが、これを動くようにするDockerfileを書きました。

DockerfileはDocker Hubのruby-with-therubyracerに置いてあり、usualoma/ruby-with-therubyracer:2.4.0-alpineという名前でbase imageとしても利用できるようになっています。(親のbase imageはruby:2.4.0-alpineです。)

何が必要だったか

therubyracerはlibv8というgemに依存しており、インストール時にlibv8に含まれるv8のライブラリにリンクされます。ここで、libv8は(ドキュメントにもあるのですが)通常だとコンパイル済みのバイナリで、Linuxの場合にはglibcにリンクされたものがインストールされるようになっているということのようです。そしてAlpine linuxではglibcではなくmusl libcがベースになっているという事情から、そのままでは動かないということでした。

そこまで分かれば後はlibv8をDockerfileでコンパイルすればよいだけなので既存のDockerfileを参考にしてlibv8をインストールして、その上でtherubyracerをインストールするようにしました。

docker image のサイズを抑えるためにやっていること

therubyracerではインストール時にlibv8のライブラリは静的にリンクされて利用時にはlibv8は参照されないようなので、libv8側のライブラリが含まれるディレクトリを$ rm -fr $(dirname $(dirname $(gem which libv8)))/vendorという形で削除しています。行儀のいいやり方ではありませんが、これだけで76MBほどかせぐことができます。

いずれにいしてもv8が入るのである程度大きくはなりますが、base imageから比較して55MB程度の増加で、debian8.0がベースのruby:2.4.0-slimで同じようにインストールしたものとと比較しても一応小ささは保たれているという感じです。

Movable Type のリスティングフレームワークの機能の一部である「フィルタ」を、MTタグやDataAPIのエンドポイントで利用することができるFilteredObjectsというプラグインを公開しました。

mt-plugin-FilteredObjects

記事やウェブページを複雑な条件で絞り込んで表示する場合、これまでは MTML で頑張るか、SearchEntriesで条件を指定していたと思います。FilteredObjects プラグインはこういったケースでのもう一つの選択肢になるものです。MTの「フィルタ」機能を利用するため(「フィルタ」は管理画面からGUIで条件を編集できるので)、プログラミングの知識がなくても条件を細かく指定することができ、MTMLの方ではそれを使ってシンプルな書式で結果を得ることができるようになります。

Getting sterted(とりあえず使ってみる)

プラグインのインストール

まずはFilteredObjectsプラグインをインストールしてください。

リスティングフレームワークを拡張するプラグインのインストール(必要な場合だけ)

FilteredObjectsはリスティングフレームワークを拡張する別のプラグインと組み合わせるとより強力になります。(プラグインによっては組み合わせることができない可能性もあります。)そして特に、カスタムフィールドで複数の条件を指定して絞り込みができるとここでは格段に便利になると思うので、おすすめはCustomFieldsListingプラグインです。(ただ実は、CustomFieldsListingプラグインはFilteredObjects側からだいぶ無理して利用させてもらう形になっているので、同時に利用した場合CustomFieldsListingの機能が正常に動作しなくなってしまう可能性があります。同時利用で不具合が起きる場合にはFilteredObjectsプラグインを削除してください)

「フィルタ」の準備

一覧ページで「フィルタ」の新規作成へと進み、条件を指定したあと、「識別子」を指定して「フィルタ」を保存してください。

screen-shot 2016-12-20 4.15.34.png

screen-shot 2016-12-20 4.17.36.png

MTMLで出力する

「識別子」を付けて保存した「フィルタ」は mt:FilteredEntries と mt:FilteredPages を使って以下のように出力することができます。

Data API で取得する

Data API では /filtered-objects/entries に filter パラメータを指定して取得することができます。

Advanced Usage(もう少し凝った使い方)

MTの「フィルタ」では、「または(OR)」という条件を指定することができないのですが、FilteredObjects では複数の「フィルタ」を「または(OR)」でつなげることができます。

やや複雑になるので、具体的な例で考えてみます。

複数のニュースのブログから条件を指定してピックアップする

以下のように、複数のニュース用のブログがあるとします。

  • 会社全体のニュース
  • 製品毎のニュース

ここで、ウェブサイトのトップページに、

  • 会社全体のニュースからは全部
  • 製品毎のニュースからは「全体のニュースに表示する」にチェックを入れたものだけ

という条件で表示するケースを考えます。

この場合は「フィルタ」を2つ、それぞれ上の条件と同じものを指定して作成します。(特定のブログを指定するための「ブログID」の条件はMTの標準では表示されませんが、FilteredObjects をインストールすると表示されるようになります。)

screen-shot 2016-12-20 5.00.56.pngscreen-shot 2016-12-20 5.03.40.png

screen-shot 2016-12-20 5.09.59.pngscreen-shot 2016-12-20 5.10.34.png

スクリーンショットの内容で、以下の2つのフィルタを作成したとします。

  • blog-general-news
  • show-in-general-news

ここまでできれば MTML 側は簡単で、 mt:FilteredEntries タグの filter に2つのフィルタを「OR」でつなげて指定することで目的の記事を表示することができます。

また、Data API の /filtered-objects/entries エンドポイントで取得することもできます。

制限事項など

  • MTタグ、Data APIのエンドポイントの両方で、公開されている記事のみが対象になります
  • 誤って削除してしまうことのないように、「識別子」を付けた「フィルタ」ではゴミ箱アイコンが表示されなくなります
    • 「システム > フィルタの管理」で削除することができます
  • 種類が「日付と時刻」のフィールドでは「今より前」「今より後」が表示されますが、これは CustomFieldsListing を独自に拡張しているもので、うまく動かない場合は FilteredObjects 側の問題です
    • 日付の場合「今より前」は「今日の23時59分59秒より前」となり、「今より後」は「今日の0時0分0秒より後」となります
  • 「自分の記事」の条件には未対応です
  • 対象となるブログは「フィルタ」からいい感じに選択されるはずですが、うまくいかない場合には明示的に指定してください
    • mt:FilteredEntries/mt:FilteredPages では、マルチブログのモディファイアを指定することができます
    • /filtered-objects/entries エンドポイントでは、blogIds パラメータにブログのIDを「,」(カンマ)区切りで複数指定することができます

FilteredObjects プラグインでの「フィルタ」の運用について

MTでは「フィルタ」は「ユーザ」毎に管理されるデータなので、FilteredObjectsのようにテンプレートやData APIでで利用する道具としては向いていない部分があります。(他の「ユーザ」の「フィルタ」を見ることができない、など。)

「識別子」のついた「フィルタ」がいろいろな「ユーザ」のデータとして散らばるのは好ましくないと思うので、現時点としては『専用の「ユーザ」を作成して、全ての「フィルタ」はそこで管理する』が現実的な一つの回避策ではないかと思っています。

プラグインのインストール

  1. GitHubからzipファイルをダウンロードしてください。リリース一覧
  2. ダウンロードしたファイルを展開してください。
  3. pluginsディレクトリにアップロードしてください。

    インストール後のディレクトリの配置は以下のようになります。

    $MT_HOME/
        plugins/
            FilteredObjects/

サポートしている機能

  • スタティックパブリッシング
  • Data API

サポートしていない機能

  • ダイナミックパブリッシング

動作環境

  • MT6

この記事について

この記事は Movable Type Advent Calendar 2016 の20日目の記事です。