Movable Typeで構築中のとあるイントラネットサイトにスケジュール表を実装することになりました。学生時代にJavaでカレンダーを出すプログラムを書いたことがあって結構大変なことも知っていたので、スケジュールの表示が分かりやすい「FullCalendar」というjQueryプラグインを選定して実装してみました。
jQueryプラグインなので、カレンダーを表示させることは簡単でしたが、イベントデータをどうカレンダーに結びつけるか検討が必要でした。方法はドキュメントに記載がありますが、次の3通りがあります。
fullCalendar
実行時に配列で渡す(events (as an array))- URLを指定してJSONを取得する(events (as a json feed))
- Ajaxでデータを取得して加工する関数を定義する(events (as a function))
fullCalendar
実行時に一括でデータを渡すのは非現実的、Ajaxで既存のDataAPIエンドポイントからデータを取得して加工するのはクライアントサイドに少し負荷がかかりそう、ということでevents (as a json feed)の仕様に沿ったJSONを出力するのがシンプルで良いかなと考えました。そこで、独自のDataAPIエンドポイントを追加してみることにしました。
エンドポイントの定義
次のようなconfig.yaml
を書き、mt-data-api.cgi/v3/fullcalendar/[blog_id]/list
にアクセスするとJSONデータが取得できるように設計しました。
name: DataAPIFullCalendar
version: 1.0
author_name: LAB inc.
author_link: http://lab-inc.jp/
applications:
data_api:
endpoints:
- id: list_entries_by_field
route: /fullcalendar/:blog_id/list
verb: GET
version: 1
handler: $DataAPIFullCalendar::DataAPIFullCalendar::EndPoint::Entry::list_entries_by_field
requires_login: 0
list_entries_by_fieldルーチンの定義
指定のブログからイベント情報(1イベント=1記事)を取得して、仕様に沿ったJSONに加工して出力するコードを書きました。
記事はMT::Entry->load()
で取得します。以下のコードはかなり基礎的な書き方をしましたが、join
の所を$args
に入れてMT::DataAPI::Endpoint::Common::filtered_list
をコールするとよりシンプルに書くことができることを後で知りました。また、エンドポイントで指定するブログIDは、$app->param('blog_id')
で取得できました。
my $col = 'dt_start';
my $class = MT->model('entry');
my $type = MT::Meta->metadata_by_name($class, 'field.' . $col);
my @entries = MT::Entry->load(
{
blog_id => $app->param('blog_id') ? $app->param('blog_id') : 1,
status => MT::Entry::RELEASE()
},
{
join => [
$class->meta_pkg,
undef,
{
'entry_id' => \'= entry_id',
type => 'field.' . $col,
$type->{type} => [ $app->param('start') . ' 00:00:00', $app->param('end') . ' 23:59:59' ]
},
{
range => {
$type->{type} => 1
}
}
],
sort => 'authored_on',
direction => 'descend',
}
);
その後、取得したデータをFullCalendarの仕様に合わせるために、ループを回してデータを加工しました。終日スケジュールか否かで日付の加工が必要になるなどしますが、 コードの要点は以下です。
foreach my $entry ( @entries ) {
my $meta = &get_meta($entry);
my $data;
my $dt_end;
if ($meta->{ 'dt_end' }) {
$dt_end = ts2iso($app->blog, $meta->{ 'dt_end' }, 1);
} else {
$dt_end = '';
}
$data = {
id => $entry->id,
title => $entry->title,
allDay => $meta->{ 'is_allday' } ? boolean::true() : boolean::false(),
start => format_ts('%Y-%m-%d', $meta->{ 'dt_start' }, $app->blog),
end => $dt_end,
};
push(@ret, $data);
}
後は@ret
を返すことで、JSONデータになって出力されました。
まとめ
MTのプラグインの基礎が分かれば、DataAPIエンドポイントの追加も意外と簡単にできることが分かりました。要した時間は事前に業務外の自習で(趣味的に)書いていたのが2時間ぐらい、業務中にFullCalendarの仕様に合わせたJSONにするのが2時間ぐらいでした。
Perlにはture
,false
がないことに戸惑ったり、日付の加工方法をどうするか探したのですが、MTのコードを読んで書き方が分かりました。プラグイン初心者の方である程度Perlが読めるようになったら、MTのコードやプラグインをよく書かれる方のコードを読んでみることをおすすめします。