WordPressのカスタムフィールドのデータをGoogleカレンダーにインポートさせるために、iCalendar形式のデータをはき出させる

CSプレイヤーズでは、コンサドーレ札幌の選手データを収録するデータベースとしてWordPressを使用している。効率よく管理するために、カスタムフィールドを使用している。この中に、選手達の誕生日データがあり、これを公開Googleカレンダーに載っけたくなった。

Googleカレンダーにはインポートの機能があるので、これを使うことにする。直接インポートできるような便利な機能はないので、WordPress側でインポートできる様式で出力(表示)する方法を探った。これは、その時の覚え書きである。

まず最初に、今回成功したGoogleカレンダーへのインポートできた完成型はこちら。→誕生日カレンダー – CSプレイヤーズ(CONSA DE CONSA)

  • 公開カレンダーに、選手の誕生日を予定として記述。
  • 選手名でタイトルをつけ、その選手の誕生日に終日予定で表示。
  • 作成日は、生まれた年でそれ以降は、毎年繰り返し表示。
  • 説明にCSプレイヤーズのその選手のデータの載っているページのURLを記載。

といった形で表示したい。さすがにリアルタイムでシンクロナイズなどと言うことは無理なので、CSプレイヤーズに、データをはき出させて、それをGoogleカレンダーに手動でインポートする形を選択。


WordPressのカスタムフィールドのデータをGoogleカレンダーにインポートさせるために、CSV形式のデータをはき出させる:からの続き】

【iCalendar編】

CSV形式でのインポートでは、繰り返し予定が設定できないので、iCalendar形式でインポートする道を探ることにした。iCalendar形式は記述する内容が多いので、手をだしたくなかったのだが、仕方がない。

iCalendar形式の様式を参考にしたのはここ。

理解したた範囲では、iCalendar 仕様では、大まかに下記の様な書式でデータを記述すればよいようだ。

  • 全体をVCALENDARで囲み、データ部分は、VEVENTで囲む形になる。
  • データ部分には、各パラメータの記述様式が定められている。

BEGIN:VCALENDAR ←iCalendar形式の開始宣言
ヘッダ部分記述
BEGIN:VEVENT ←個別データ(予定)開始宣言
データ本文1記述
END:VEVENT ←個別データ(予定)終了宣言
BEGIN:VEVENT ←個別データ(2件目の予定)開始宣言
データ本文2記述
END:VEVENT ←個別データ(2件目の予定)終了宣言

 ・繰り返し・

BEGIN:VEVENT ←個別データ(最後の予定)開始宣言
データ本文最後記述
END:VEVENT ←個別データ(最後の予定)終了宣言
END:VCALENDAR ←iCalendar形式の終了宣言

これらを参考に、実際に記述したPHPは下記の通り。

【説明】

まず、ICalendarファイルであることを宣言

ヘッダ部分は、MacOSに附属のiCALと呼ばれるカレンダーソフトからエキスポートしたicsファイルのヘッダ部分をそのまま流用。そのため、PRODID:の項目などは正しくない。不用なパラメータもあるが、結果的にこれでうまく読み込まれたので、修正していない。正しい書式を求めている人は要修正。

ここでは、表示するデータを指定した。
numberposts=300:表示記事数300を上限と指定。今回は220データがあったので、こう指定。なくてもOK。
orderby=meta_value_num:メタ値でソート、そのメタ値は数字である。ただし、文内でソートに使うメタ値を指定していないので、&orderby=meta_value_numは不用かも。
order=ASC:ソートの順番は昇順(ASCEND)
今回は全データを出力したので、ここの書き方は適当(正しくないかも)。出力するデータを絞り込む際は、きっちり記述する必要有り。

foreach文で繰り返しを指定

ここから各個別データ部分の記述に入る。
まず、「BEGIN:VEVENT」で、個別データの開始を宣言

タイムゾーンを指定。
ただ、以下の日時指定の所でも指定しているのでなくてもいいかも。

個別データ(予定)の作成日時の指定。様式は「年月日T時分秒Z」と数字で表示。日付はカスタムフィールド(誕生日)のデータを呼び出して使うことにする。時間は適当でいいので投稿記事の作成日を使用。桁数が「4桁-2桁-2桁-T-2桁-2桁-2桁-Z」でなくてはならない。

Birthday-year、Birthday-month、Birthday-dayはカスタムフィールドの名前。

ここで問題発生。最初、単純にカスタムフィールド値(年月日)をただ表示するだけにしたのだが、カスタムフィールドの誕生日は全てが2桁ではない。月と日に1桁の数字がある。これをそのまま表示させると、年月日が8桁にならず、7桁や6桁のものができてしまう。

そこで年月日に関しては、sprint文で表示する数字の桁数を指定してある。カスタムフィールド値をそれぞれ、$year, $month, $dayに一旦読み込ませ、表示桁をsprint文で指定してある(%04d%02d%02d)。これで、1桁の月日には、頭に0がついて2桁表示になってくれる。上の例はそのsprint文が入っているバージョン。

UIDは各予定データ毎につける個別ID。本来はRFC 822に従うことが推奨されているのだが、よく分からないので、勝手な様式で作る。大事なのは同じものが他にこの世にないこと(唯一であること)。
そこで、「サイト名-誕生日-ファイル作成日時」といった形にすることにした。これで、記事内で同じ番号になることはないはず。
既にカレンダーソフトで同じUIDの予定があると後からインポートしても二重にならない。このあとでてくる「SEQUENCE:」でヴァージョン管理しているので、新しい方が優先される。

予定の終了日時を指定。ここでは、タイムゾーン(TZID=Asia/Tokyo)と、終日指定であること(VALUE=DATE)を宣言してある。
終日指定の場合は、この終了日時を翌日にしておけばいい。そのため、$dayに読み込ませる日に+1と足してある。
本当は、これでは月末の予定では、実在しない日になってしまうはずであるが、何となくうまくいったので、深く調べていない。

予定の繰り返し指定。毎年としている。

よく分からないが、OPAQUE がデフォルト。

予定のタイトルを指定。今回は「【誕生日】選手名」と表示されるようにした。

予定の場所を指定。今回は、特にないので空欄。あるなら指定。

説明文を指定。今回は、選手データのあるURLを指定してある。

予定の開始日を指定。場所はDTENDの前でも後でもかまわない。
誕生日の年月日を終日指定。

DTSTAMP: は予定の作成日を指定。誕生日の年月日にファイルの作成時分秒をあわせている。様式の説明はCREATED: と同じ。CREATEDとの違いはいまいち分からない。今回は同じなっている。

予定データのバーションを表す。数字は任意。予定データ毎のヴァージョン管理は大変なので、出力されたデータは全て同じヴァージョンになるようにしてある。上の例では、ヴァージョン5という意味。
ここだけは、毎回手作業で数字をあげていく。今回の場合、誕生日データを大量に読み込ませたのだが、回数は年に数回で、頻繁ではないので。

同じUIDを持つデータが重ねてインポートされた場合、この数字の大きい方で上書きされる。インポート時に、「処理されたが既存の予定は書き直されませんでした」旨表示された場合、この数字を大きくすると、うまくいく場合がある。

個別データ(予定)の終了宣言

foreach文の終了宣言

最後は、iCalendar形式の締め(終了)の宣言文


このPHPで、データを表示させると、下記の通り。CSSやタグのの関係で下記例はイタリックで表示されているが、イタリックである必要はない。

【例】

BEGIN:VCALENDAR
METHOD:PUBLISH
VERSION:2.0
X-WR-CALNAME:誕生日
PRODID:-//Apple Inc.//iCal 4.0.4//EN
X-WR-CALDESC:
X-APPLE-CALENDAR-COLOR:#E51717
X-WR-TIMEZONE:Asia/Tokyo
CALSCALE:GREGORIAN
BEGIN:VEVENT
TZID:Japan
CREATED:19770918T070155Z
UID:CSPLAYERS-CONSADECONSA-19770918-110113075555
DTEND;TZID=Asia/Tokyo;VALUE=DATE:19770919
RRULE:FREQ=YEARLY
TRANSP:OPAQUE
SUMMARY:【誕生日】選手名1
LOCATION:
DESCRIPTION:https://www.consadeconsa.com/players/url1/
DTSTART;TZID=Asia/Tokyo;VALUE=DATE:19770918
DTSTAMP:19770918T070155Z
SEQUENCE:5
END:VEVENT

  繰り返し(2件目〜最後のデータ)

END:VCALENDAR

これを、テキストファイルにコピー&ペーストして保存する。ファイル名は何でも良い。
文字コード:UTF-8、改行コード:CRLF、拡張子:ics

Googleカレンダーにインポートすると、200を超えるデータが、見事読み込まれた。繰り返しもちゃんと読み込まれている。

めでたしめでたし。