2017年4月9日日曜日

【プラグイン公開】Google Calendar List View - 公開Googleカレンダーの一覧表示ショートコードプラグイン

ちょっと探したけどなかったので自前で開発して、WordPress公式プラグインとして公開しちゃいました。ブログを読み返していて気づきましたが、2014年の時点で、WordBench大阪で若干開発していたのですね。こちらは複数のカレンダーをマージして一覧表示するものだったようです。これのソースは消しちゃったかもですね。。。まぁいつでも作成できるのでもういいんですけど..

日本語翻訳も作ったのですが、「#2750 Plugin Directory: Changelogs not updating on Rosetta plugin directories」でチケット化されましたが、 WordPress Translate がおかしいため、完全に翻訳されなかったりプラグインサイトの翻訳がおかしかったりしますねぇ。なのでここで詳細を説明します。また公式プラグインについては、下記の英語版が最新なのでこちらをみてください。


変更履歴


  • 2017.04.09   1.0公開
  • 2017.04.10   1.1公開
    • 4つのショートコードを追加、max_view, html_tag_class, html_tag_date_class, html_tag_title_class
  • 2017.04.11   1.2公開
    • 2つのフック「lvgc_output_data」「lvgc_gc_data」を追加
    • タイムゾーンまわりの修正(date関数の代わりに、current_time, get_date_from_gmt関数へ変更)
    • 開催中のイベント(日で判断)については、html_tag に対して list-view-google-calendar-holding というclassを追加し、開催中のイベントの強調表示をCSSで可能とした。
  • 2017.04.18 1.3, 1.4, 1.41, 1.42公開
    • フック「lvgc_each_output_data」を追加(1.4)・修正(1.41, 1.42)
    • html_tag 初期値の問題を修正(1.3)
    • id オプションを追加(1.3)

公開カレンダーを WordPress 上で一覧表示したい


新着情報一覧と同じ感じにってことです。
さらに多言語だったら、カレンダーも複数あるかもしれないなと思って、複数指定できるようにしてます。

ショートコード


  • <ul>[gc_list_view]</ul>
カレンダーが1つの場合で、特にデフォルト設定でよいなら、Google Calendar API KeyとGoogle Calendar ID の2つの設定をするだけで、上記ショートコードは動作します。
利用する場合には、「テキスト」モードで設定してください。理由は、汎用性を保つために、<ul></ul>タグを別途つける必要があるためです。それが面倒な場合には
  • [gc_list_view html_tag="p"]
を使えば、<p>タグで出力されますので、ビジュアルモードで問題ありません。
あるいは後述するフックを使えば、出力データを自分のテーマに合わせたカスタマイズが簡単にできます!

デフォルト設定


  • Googleカレンダーから、「現在日付」を起点として未来のカレンダーを10件取得して表示します。
  • 日付フォーマットは、YYYY.MM.DD(2017.04.10)です。
  • 表示順番は、「起点」をベースとした日付の昇順です。

ショートコードオプション (version 1.4)


  • [gc_list_view start_date="YYYY-MM-DD/ALL" end_date="YYYY-MM-DD" date_format="Y.m.d" orderbysort="ascending/descending" g_id="Google Calendar ID" g_api_key="Google Calendar API Key" max_view=10 html_tag="li/p/dd" html_tag_class="" html_tag_date_class="" html_tag_title_class="" id=""]

だけのオプションを用意しました。オプション設定は他の設定よりも優先されます。

  • start_date = データ取得の「起点」を設定します。ALLだと一番古いカレンダーデータを起点とします。strtotime のフォーマットでの記述できます。
  • end_date  = データ取得の「終点」を設定します。デフォルトは制限なしで、設定するとそこまでのデータを取得します。strtotime のフォーマットでの記述できます。
  • date_format = データ表示時の日付フォーマットを変更できます。dateフォーマットを記述できます。デフォルトは Y.m.d = YYYY.MM.DD です。Y-m-d = YYYY-MM-DDなどのように変更できます。
  • orderbysort = 「起点」をベースにした表示時の日付ソートです。デフォルトは昇順です。descending を設定することで降順にできます。Google Calendar API v3では、この降順設定が削除された(Google Calendar API v2では ordersortがあった)ため、一旦データを取得した後にプラグイン側でソートしなおしています。ascending、descending以外の設定をした場合には、ascendingがセットされます。
  • g_api_key = Google Calendar API Keyを個別に変更したいときに設定できます。
  • g_id = Google Calendar IDを個別に変更したいときに設定できます。複数のカレンダーを使いたい場合に指定します。
  • max_view = 最大表示件数であり、この件数分を Googleカレンダーから取得します。
  • html_tag = 出力データの先頭、末尾に設定するタグを指定します。<li><p><dd>の3つを指定できて、それ以外の値がセットされた場合には<li>がセットされます。 class="list-view-google-calendar">がセットされます。
  • html_tag_class = html_tag に対する classのセットです。デフォルトは、list-view-google-calendar です(<html_tag  class="list-view-google-calendar ">***</html_tag>)
  • html_tag_date_class = 日付部分に対する classのセットです。デフォルトは、list-view-google-calendar_date です(<span class="list-view-google-calendar_date">日付</span>)
  • html_tag_title_class = タイトルに対する classのセットです。デフォルトは、list-view-google-calendar_title です(<a class="list-view-google-calendar_title" href="リンク">タイトル</a>)
  • id = もしフック利用時に、各ショートコードにおいてカスタマイズを変更したければ、この id を活用してみてください。

Google Calendar API Keyの生成方法



英語ですが、画像を加えてとても分かりやすく説明されています。これをみれば生成できると思います。なお APIは一日100万クエリまでの制限があります。それ以上使いたい場合には、Google Calendar API Usage Limits ページを参考にしてください。


Google Calendar ID の確認方法



英語ですが、画像を加えてとても分かりやすく説明されています。これをみればきっと探せるはず!

具体例を出してみます!


下記の例では、 「Public Calendar 1」「Public Calendar 2」という2つの公開カレンダーを用意してます。

「Public Calendar 1」
  • 2017.04.07 TEST Event 3 on Public Calendar 1
  • 2017.04.04 TEST Event 2 on Public Calendar 1
  • 2017.04.02 TEST Event 1 on Public Calendar 1
「Public Calendar 2」
  • 2017.04.14 TEST Event 3 on Public Calendar 2
  • 2017.04.11 TEST Event 2 on Public Calendar 2
  • 2017.04.10 TEST Event 1 on Public Calendar 2

とデータを入れています。上記日付は「起点日」をいれてますが、実際には終日、日時、複数日にまたがるケースを入れ込んでいます。




これに対して、下記のショートコードを固定ページの「テキストモード」で入れてみます。※Google Calendar IDは伏せ字にしてます。

「Public Calendar 1」
    <ul>
    [gc_list_view g_id="◯◯@group.calendar.google.com" start_date="ALL" orderbysort="descending"]
    </ul>
    「Public Calendar 2」
    <dl>
    <dt>List View of Google Calendar Events</dt>
    [gc_list_view g_id="◯◯@group.calendar.google.com" orderbysort="descending" html_tag="dd"]
    </dl>

    で実際の表示は下記の通りです。



    スタイルシートがデフォルトなので <dd>が一行あいてますけれど、「Public Calendar 1」が<li>、「Public Calendar 2」が<dd>タグになっています。

    もちろん、リンクをクリックしたら公開カレンダーの詳細表示画面が新規ウィンドウで開きます。

    またPublic Calendar 1のほうは過去記事なので(実験時点で 2017.04.09)、start_date="ALL" あるいは、 start_date="2017-04-01" など起点日をイベント日時より前にしておかないと過去イベントは表示されません。まぁ過去イベントを表示したくないなら不要ですけどね。

    どんな設定があるの


    WordPressの管理ダッシュボードの「設定」内に「Google Calendar List View Settings」があります。ここで基本的な設定ができます。

    最初が上記で説明したショートコードの説明文です。





    次が、Google Calendar APIに関する設定です。
    maxResults 以外の設定は、ショートコードのオプションで設定できます。
    そのうちmaxResults もショートコードに入れないとダメだよねぇとかは思ってます。



    出力時の設定


    「起点日」を基軸とした日付のソート(昇順、降順)
    HTMLタグの出力設定になります。いずれもショートコードのオプションでも指定できます。



    拡張機能 & その他のお知らせ




    フックの使い方


    以下、サポートしているフックを テーマのための関数「functions.php」 内でどのように記述するかの例をあげておきます。

    lvgc_output_data


    ショートコードを出力直前に変更することができます。

    add_filter( 'lvgc_output_data' , 'lvgc_output_data_fix' , 10 , 2 );

    function lvgc_output_data_fix($out, $atts){
       // $out を置換するなりにして設定変更する

       return $out;
    }

    lvgc_each_output_data


    各イベントを出力する際のコードを変更できます。

    add_filter( 'lvgc_each_output_data' , 'lvgc_each_output_data_fix' , 10 , 3 );

    function lvgc_each_output_data_fix($out, $atts, $out_atts){
       extract($atts);
       extract($out_atts);

      // 以下、本プラグインのデフォルト出力コードです。これを変更するのが簡単でしょう。
      $out = '';
      $out .= '<' . esc_html($html_tag);
      $out .=  ' class="' . ($html_tag_class ? esc_attr($html_tag_class) : '') . ($holding_flag ? esc_attr(' ' . $plugin_name . '_holding') : '') . '">';
      $out .=  $html_tag_date_class ? '<span="' . esc_attr($html_tag_date_class) . '">' : '';
      $out .= ' ' . $date_format ? esc_html($start_date_value) : '';
      $out .= $html_tag_date_class ? '</span>' : '';
      $out .= ' <a';
      $out .= $html_tag_title_class ? ' class="' . esc_attr($html_tag_title_class) . '"': '';
      $out .= ' href="' . esc_url($gc_link) . '" target="_blank">' . esc_html($gc_title) .'</a>';
      $out .= '</' . esc_html($html_tag) . '>' . "\n";

      return $out;
    }

    もっとも単純な変更をしたい場合で、esc_html のようなエスケープをしない可読性を重視した書き方にするなら、下記がスッキリして分かりやすいかと思います。ちなみに、$gc_link, $gc_title は、エスケープ済みです。でも心配症なので、常にエスケープするように心がけてます。


    add_filter( 'lvgc_each_output_data' , 'lvgc_each_output_data_fix' , 10 , 3 );

    function lvgc_each_output_data_fix($out, $atts, $out_atts){
      extract($atts);
      extract($out_atts);

      $out = '';

      $out .= '<ul>';
      $out .= "<li class='hoge'> $start_date_value <a href='$gc_link'>$gc_title</a></li>";
      $out .= '</ul>';

      return $out;  

    }

    が最も単純な構成例かなと思います。

    またショートコードごとに変更したければ、

    [gc_list_view g_id="hogehoge"  id="hogehoge"]

    などのように ユニークな番号かキーワードである idをいれた上で、下記のようにすれば、 id="hogehoge" だけに適用できるフックを作成できますよ!

    add_filter( 'lvgc_each_output_data' , 'lvgc_each_output_data_fix' , 10 , 3 );

    function lvgc_each_output_data_fix($out, $atts, $out_atts){
      extract($atts);
      extract($out_atts);

      if($id === "hogehoge"):
        $out = '';
        $out .= '<ul>';
        $out .= "<li class='hoge'> $start_date_value <a href='$gc_link'>$gc_title</a></li>";
        $out .= '</ul>';
      endif;

      return $out;  
    }

    なお $id は、$atts['id'] に入っており、 extract($atts); によって、$id 変数に値が入ってます。


    $atts = ショートコードオプション(配列)


    $atts_out = 出力に必要なデータをいれた変数

    start_date_num = 各イベントの開始日(Ymd)
    start_date_value = 各イベントの開始日(date_formatで指定したフォーマット)

    end_date_num = 各イベントの終了日(Ymd)
    today_date_num = 本日(Ymd)
    holding_flag = 各イベントが開催日なら true, そうでないなら false
    gc_link = 各イベントのGoogleカレンダーへのリンク
    gc_title = 各イベントのタイトル
    plugin_name = プラグイン名

    $out_atts = array(
    'start_date_num' => $start_date_num,
    'start_date_value' => $start_date_value,
    'end_date_num' => $end_date_num,
    'today_date_num' => $today_date_num,
    'holding_flag' => $holding_flag,
    'gc_link' => $gc_link,
    'gc_title' => $gc_title,
    'plugin_name' => $plugin_name,

    );

    lvgc_gc_data


    Googleカレンダーイベントを取得してすぐに割り込みを入れてデータの変更が可能です。

    add_filter( 'lvgc_gc_data' , 'lvgc_gc_data_fix' , 10 , 2 );

    function lvgc_gc_data_fix($gc_data, $atts){
       // var_dump($gc_data); をいれた場合、どのようなデータが入っているか分かります。
       // 多次元配列になっていて、 
    $gc_data['items'] 内にイベント情報が入っています。
      if($gc_data['items']):
         foreach($gc_data['items'] as $num=>$item):
            // $num は現在処理中のデータ番号、$item が現在処理中のイベントになります。
         endforeach;
      endif;

      return $gc_data;
    }

    たとえば、終日イベントなら、$item['start']['date'] と $item['end']['date'] に開始日と終了日が入ってます。時間指定なら、$item['start']['dateTime'] と $item['end']['dateTime'] に開始日時と終了日時が入っています。時間指定の場合には、$item['start']['date'] と $item['end']['date'] は値として存在しないので終日か日時指定かはそこで判別できます。

    タイムゾーン処理に気をつけること

    date や i18_date では WordPress におけるタイムゾーン処理ではうまくいかないか、面倒が発生します。のでタイムゾーン処理なんて考えたくないぜ〜って人には、次のWordPress専用関数を利用すると幸せになれます。


    • 現在日時取得&日時フォーマット変換:current_time
         $current_time = currentitme("Y-m-d");  (2017-04-03 など年月日で取得する場合)
    • 日時フォーマット変換:get_date_from_gmt
        $start_date = get_date_from_gmt($item['start']['dateTime'], "Y-m-d");
        (Googleカレンダーイベントの開始日時をタイムゾーンに配慮して、年-月-日で $start_date に入れる)


     まぁとこんな感じで、テンプレートであろうが、固定ページ、投稿ページ(カスタム投稿含む)のどこでも、「公開」されているGoogleカレンダーについては、一覧表示できるぜ〜ってことですね。

    2017年4月20日 冒頭の文言を追加
    2017年4月18日 フックに関する説明を追記
    2017年4月17日 フックに関する説明を追記
    2017年4月10日 バージョン1.2 の加筆
    2017年4月10日 バージョン1.1 の加筆
    2017年4月9日 @kimipooh









    4 件のコメント:

    1. 今後実装したいな〜って思っている追加機能をメモっておきます。

      1. オプション:期日範囲のうち、新しいものを◯件表示
      ※現行は古いもの順
      <条件>maxResults は期日範囲を網羅する数値が必要


      2. 開催中のイベントを強調表示
      class を追加する

      3. class を自由に追加できるショートコードオプションを追加

      返信削除
    2. 上記の 2,3は バージョン 1.2 で実装。

      返信削除
    3. フックに関する利用説明を追加

      返信削除
    4. フックに関する説明追加。1.42公開
      lvgc_each_output_data は特に力を入れて説明書きました〜

      返信削除

    Google+ Badge