program
【Movable Typeでも複雑な処理を一元管理!】1/3
複雑な処理をスッキリ整理! グローバル・モディファイアプラグイン
「コピー&ペースト」?
確かに同じ処理を行うことができますね。
でもCMSは一つの「システム」です。
「システム」が入っている以上、「システム」にやらせたいとは思いませんか?
まずはMovable Typeについて、以下のようなケースを考えてみましょう。
このリンク、かっこ悪いけど……
Movable Typeでは本来、カテゴリ、月別などのアーカイブテンプレートや個別テンプレートとその元となる記事は出力されるURLを基準にブログが指定されるべきです。
しかし、特にPowerCMSのカスタムオブジェクトなどでは、データの関連性や会員専用エリアなどの都合でURLとは違うブログに所属させたほうが都合がいい場合があります。
そのような事情でアーカイブテンプレートなどをブログURLの下ではないディレクトリに出力した場合でも、同じドメイン内であれば<$MTCategoryArchiveLink$>などでURLを出力したリンクそのままで遷移する事ができます。
しかし、出力されたHTMLのソースをみてみると……
1 |
<a href="http://www.exsample.com/dir0/news/../../dir1/cat/index.php">リンク</a> |
上のディレクトリを表す「../」がそのまま出力されています。
何らかのシステムで出力されているのがバレバレじゃないですか!?
……ページの内容で分かることも多いのでこの程度であれば放置することもありますが、せっかくなのできれいに整形しましょう。
1 2 |
<$MTCategoryArchiveLink setvar="url"$> <a href="<$MTGetVar name="url" replace="/dir0/news/../../","/"$>">リンク</a> |
2回だけ上に出ていてそのディレクトリ名もはっきりしているのでこれぐらいで収まりますが、あまりスッキリしませんね。 メンテナンス性も悪いです。
こういうときはプラグインでグローバルモディファイアにしてしまいましょう!
プラグインは、作れる。
「プラグインなんて難しい。自分にできるわけがない」とお考えの方も多いでしょう。
しかし今回のような、グローバルモディファイアのプラグイン自体はすごく簡単です。
今回のプラグインは公式の開発者向けガイドと同じような表記だと以下のようなファイル構成になります。テスト関係は割愛しています。
|__ plugins/
|__ RealPath/
|__ config.yaml
|__ lib/
|_ RealPath/
|__ L10N.pm
|_ L10N/
| |_ en_us.pm
| |_ ja.pm
|_ Tags.pm
「$MT_DIR/」はMTをインストールしたディレクトリです。この直下に「plugins/」ディレクトリがあります。
この下に「RealPath/」ディレクトリ以下を作成します。
実際にプラグインの処理を行うPerlモジュール(PHPやjavascriptのクラスにあたるもの)の設置場所は「RealPath/lib/」以下になります。
複雑なプラグインではこの下に「MT/App/RealPath/」などができる場合もありますが、今回はすべて「RealPath/」配下のモジュールになります。
config.yaml
YAMLは構造化データをシンプルに記述するテキストデータ形式です。
プラグインの基本情報を記述します。
1 2 3 4 5 6 7 8 9 10 11 |
id: RealPath key: RealPath name: <__trans phrase="_PLUGIN_NAME"> version: 1.0 description: <__trans phrase="_PLUGIN_DESCRIPTION"> author_name: <__trans phrase="_PLUGIN_AUTHOR"> author_link: https://www.m-hand.co.jp/ l10n_class: RealPath::L10N tags: modifier: realpath: $RealPath::RealPath::Tags::_real_path |
07行目まではMTが他のプラグインと区別する名前や、管理画面などで表示する内容になります。
「<__trans phrase=”なんとか”>」は、08行目で指定しているPerlモジュールによってMTの設定言語により変換される、多言語対応になっています。
09行目では、ここから下のインデントでタグに関する処理があることを意味しています。
10行目では、ここから下のインデントで、グローバルモディファイアを追加することを意味しています。
11行目がこのプラグインの動作を決定しています。
「:」の左側「realpath」がMTMLタグに記述するモディファイアを指定しています。
右側の「$RealPath::RealPath::Tags::_real_path」は「realpath」でこの「RealPath」プラグイン内の「RealPath::Tags」モジュール内の「_real_path」関数を実行することを意味しています。
実際に組んでみよう!
まず、お約束で「config.yaml」08行目で指定している以下のPerlモジュールを追加します。
L10N.pm
1 2 3 4 5 6 7 |
package RealPath::L10N; use strict; use base 'MT::Plugin::L10N'; 1; |
l10nは「localization(l<10文字>n)」の略です。
1 |
package RealPath::L10N; |
このファイルは「RealPath::L10N」モジュールです、という宣言です。「RealPath」はそのプラグインのディレクトリ名になります。
※直接実行しないので(できても何も起こらないはずですが)cgiファイルにあるような「#!/usr/bin/perl -w」といった行は記載しません。
3 |
use strict; |
ルールどおりに書かないとエラーを出力します、というおまじないです。
といっても昔のPerlが自由すぎたのであり、よほど古いコードでない限りこのルールに外れたPerlは無いはずです。
※Perlは「昔のコード」を実行できるようにするためにこの命令を追加しましたが、javascriptは逆に「古いブラウザ」でも実行できるように「文字列」として記述するようにしました。
5 |
use base 'MT::Plugin::L10N'; |
このモジュールは「MT::Plugin::L10N」モジュールを継承しています。
必要な機能は「MT::Plugin::L10N」モジュールに全て実装してあります。
プラグインにその機能を取り込むのがこのモジュールの役割になります。
7 |
1; |
「ファイルが正常に終わりました」というおまじないです。
Perlにはtrue(真),false(偽)は概念としてはありますが、値として定義されていません。数値の1または0を使用します。もっとも、Perlは1つの変数で文字列と数値の両方を保持するので、文字列でも問題はないはずです。
en_us.pm
英語に翻訳するモジュールです。
少しずつ意味を理解していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package RealPath::L10N::en_us; use strict; use base 'RealPath::L10N'; our %Lexicon = ( '_PLUGIN_NAME' => 'Realpath Plugin.', '_PLUGIN_DESCRIPTION' => 'remove dotted current/parent path global modifier', '_PLUGIN_AUTHOR' => 'M-HAND, Inc.', ); 1; |
5 |
use base 'RealPath::L10N'; |
「RealPath::L10N」モジュールを継承しています。
その「RealPath::L10N」モジュールが「MT::Plugin::L10N」モジュールを継承しているところと同じです。
7 8 9 10 11 |
our %Lexicon = ( '元の文字列' => '翻訳文字列', ・ ・ ); |
perlで「%」で始まるものはハッシュ、他の言語でいう連想配列になります(実はPHP5までの「array()」は全て連想配列です)。
ハッシュ「%Lexicon」に実際に翻訳するデータを追加します。
変数を最初に使う前に「our」をつけることでグローバル変数であることを宣言します。
多言語化する場合でも基本は英語なので、このファイルでは1行も書かないようにプラグインを作ることも可能です。
しかし、config.yamlをスッキリさせるためにこのプラグインのように作られているものが多いです。
ja.pm
日本語に翻訳するモジュールです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package RealPath::L10N::ja; use strict; use base 'RealPath::L10N::en_us'; use utf8; our %Lexicon = ( '_PLUGIN_NAME' => 'realpathプラグイン', '_PLUGIN_DESCRIPTION' => 'ピリオドによるパスを変換する グローバル・モディファイア', '_PLUGIN_AUTHOR' => '株式会社エムハンド', ); 1; |
5 |
use base 'RealPath::L10N::en_us'; |
3回目なのでもう分かりましたよね?
「RealPath::L10N::en_us」モジュールを継承しています。
後は英語が日本語になっている以外はen_us.pmと同じです。
6 |
use utf8; |
UTF-8でソースファイル(コメント以外)を記述するときのおまじないです。
このモジュールだけ全角文字を使用していることに気づきましたか?
HTML側にかかわらず、PerlモジュールはUTF-8で記述してください。
そして多言語化することで、多言語化モジュール以外の文字コードを気にする必要がなくなるのです。
2015.02.05追記
_PLUGIN_NAME,_PLUGIN_DESCRIPTIONがおかしかったのでこっそり修正。