Google Calendar の情報をAPIで取得して、Timeline APIで表示する(その1)



0.MashUp
Google Calendarがリリースされてしばらく経ちますが、使えそうで、使えなさそうで。自分の予定を管理したり、複数で共有したり、ってなことも出来るのですが、私自身はまだもう一つ使いこなせていないというところ。
で、単体での使用はまだまだこれから良い方法を考えるとして、MashUpでもう少し面白く使えないかと、いうところに、こちらのサイトでの展開を考えて、Google Calendarをデータベースとして、Timeline APIインターフェイスとして使用することを試してみた。実際の運用はこちらdLINKbRING.Artを参考ください。


1.Google Calendar Data API
Google Calendar Data APIを利用して、データをまず取得する。ちなみに、こちらはGoogle Maps APIと同様にユーザー登録してIDを取得する必要がある。IDさえ取得してしまえば、結局XMLでの配信なので、それほど難しいことはない。
1.1 XMLアドレス
取得XMLアドレスは下記で、取得したいユーザーIDを使って、例えば、以下のようになる。ちなみに、"full"のところを変えると取得するデータの内容が変化する。詳しくは、こちら


//全てのデータを取得する場合
  http://www.google.com/calendar/feeds/取得したユーザーID%40gmail.com/public/full
//特定のデータを取得する場合
  http://www.google.com/calendar/feeds/取得したユーザーID%40gmail.com/public/full/データID



1.2 後は読み込むだけ
あとは、これを読み込んでしまえばいい。たとえば、以下のような感じ。自分で作らなくても、SimpleXMLなどを使うともっと簡単にできるとも思う。


<?PHP //PHPクラス
 class Getgooglecal {
  private $googleID ;  //Store google user ID (without ID "@gmail.com" is used)  
  private $gcalInfo;  //Store recieved file as array
  private $gcalEventID="";
  private $itemnum=0;  //Count Item number
  private $url;  //Store xml url
  
 public function __construct()
 {
 }

  //Set Google User ID
  public function SetgoogleID($mygoogleID){
   $this->googleID=$mygoogleID;
  }
  
  //Set Google Event ID you wnt to search
  public function SetGcalEvent($MyGcalEventID){
   $this->gcalEventID=$MyGcalEventID;
  }
  
  //Recieve xml file
  public function GetgcalInfo(){
   //Generate xml url
   //      
   $today=getdate();
   if( $this->googleID==""){
    $this->gcalInfo["message"]="Google ID does not set!";
   }else{
     $this->url ="http://www.google.com/calendar/feeds/";
     $this->url.=$this->googleID."%40gmail.com/public/full";
    if($this->gcalEventID!=""){  // to fetch one data
     $this->url.='/'.$this->gcalEventID;
    }
    //Call main body of reading xml file
    $this->GenerategcalInfo();
    //print($this->url);
    if($this->itemnum==0){
     $this->gcalInfo["message"]="No Result";
    }
   }
   return($this->gcalInfo);
  }
  
  //Read XML File and store to array
  private function GenerategcalInfo(){
   $XMLRead=new XMLReader;
   //print($this->url);
   $this->itemnum=0;
   //$XMLRead->open($this->url);
   if($XMLRead->open($this->url)){
   while($XMLRead->read()){
    switch($XMLRead->name){
     Case "entry":
      $XMLRead->read();
      while($XMLRead->name!="entry"){
       switch($XMLRead->name){
        Case "id":
         if($XMLRead->nodeType==1){
          $XMLRead->read();
          $this->gcalInfo["entry"][$this->itemnum]["id"]= $XMLRead->value;
         }
        break;
        Case "published":
         if($XMLRead->nodeType==1){
          $XMLRead->read();
          $this->gcalInfo["entry"][$this->itemnum]["published"]= $XMLRead->value;
         }
        break;
        Case "updated":
         if($XMLRead->nodeType==1){
          $XMLRead->read();
          $this->gcalInfo["entry"][$this->itemnum]["updated"]= $XMLRead->value;
         }
        break;
        Case "title":
         if($XMLRead->nodeType==1){
          $XMLRead->read();
          $this->gcalInfo["entry"][$this->itemnum]["title"]= $XMLRead->value;
         }
        break;
        Case "content":
         if($XMLRead->nodeType==1){
          $XMLRead->read();
          $this->gcalInfo["entry"][$this->itemnum]["content"]= $XMLRead->value;
         }
        break;
        Case "link":
         if($XMLRead->nodeType==1){
          if($XMLRead->getAttribute("type")=="text/html" and
        substr($XMLRead->getAttribute("href"),0,31)
            =="http://www.google.com/calendar/"){
           $this->gcalInfo["entry"][$this->itemnum]["link"]=
            $XMLRead->getAttribute("href");
           $this->gcalInfo["entry"][$this->itemnum]["eid"]= 
            substr(strstr($XMLRead->getAttribute("href"),"eid="),4);
          }
         }
        break;
        Case "gd:recurrence":
         if($XMLRead->nodeType==1){
          $XMLRead->read();
           $this->gcalInfo["entry"][$this->itemnum]["startTime"]=
            $XMLRead->getAttribute("startTime");
           $this->gcalInfo["entry"][$this->itemnum]["endTime"]= 
            $XMLRead->getAttribute("endTime");
         }
        break;
        Case "gd:when":
         if($XMLRead->nodeType==1){
           $this->gcalInfo["entry"][$this->itemnum]["startTime"]= 
            $XMLRead->getAttribute("startTime");
           $this->gcalInfo["entry"][$this->itemnum]["endTime"]= 
            $XMLRead->getAttribute("endTime");
         }
        break;
        Case "gd:where":
         if($XMLRead->nodeType==1){
           $this->gcalInfo["entry"][$this->itemnum]["where"]=
            $XMLRead->getAttribute("valueString");
         }
        break;
        default:
        break;
       }
       $XMLRead->read();
      }
      $this->itemnum+=1;
     break;
     default:
     break;
    }
   }
   }
   $XMLRead->close;
   $this->gcalInfo["count"]=$this->itemnum;
  }
 }
  
?>



2.Timeline API
Timeline APISIMILE Projectでいろいろと開発されているものの一つ。カレンダー表示インターフェイスAJAXによりGoogle Map的ドラッグ操作が可能とするもの。
2.1まずは
SIMILE | Timeline | Documentation | How to Create Timelinesこちらのサイトを見ながら、ほとんどコピペしていけば、それなりのものが出来る。
で、例えば以下のようになる。


//メインページ用
  .....
  <script src="http://simile.mit.edu/timeline/api/timeline-api.js" type="text/javascript" charset="UTF-8"></script>
  <script type="text/javascript">
   //<![CDATA[
    var tl;
   //]]>
  </script>
  .....
  <body onload="onLoad()" onresize="onResize();">
  .....
  <div id="mytimeline" style="height: 150px; border: 1px solid #aaa"></div>
  .....

//onLoad用javascript関数
function onLoad() {
/* datasetting */
var now=new Date();
  
/* Timeline Setting */
  var eventSource = new Timeline.DefaultEventSource();

 var bandInfos = [
  Timeline.createBandInfo({  /* 最初のカレンダー */
   eventSource:    eventSource,  /* ソースデータ*/
   timeZone:       +9,  /* GMT時間帯:日本では+9 */
   date:           now,  /* 初期中心軸の時間::常に表示した時間になるように設定 */
   width:          "70%",  /* 複数のカレンダーの配分*/
   intervalUnit:   Timeline.DateTime.WEEK,   /* カレンダーの幅 WEEK:週 MONTH:月 など*/
   intervalPixels: 100,  /* 時間幅 */
  }),
  Timeline.createBandInfo({ /* 2番目のカレンダー:以下の設定は上記と同様 */
   eventSource:    eventSource,
   date:           now,
   timeZone:       +9,
   showEventText:  false, /* イベントタイトルのテキスト表示をしない */
   trackHeight:    0.3, /* 時間バーの幅を設定(デフォルトは1.0) */
   trackGap:       0.2, /* 各データ間の隙間設定 */
   width:          "30%", 
   intervalUnit:   Timeline.DateTime.MONTH, 
   intervalPixels: 60,
  })
 ];

 bandInfos[1].syncWith = 0;
 bandInfos[1].highlight = true;
  /* カレンダーを表示 */
  /* "mytimelineがHTML内のID名。ただし、ここを"timeline"にしてしまうと、
   (多分、データ表示に使っているID名と当たって)エラーが発生してしまうので注意。 */
 tl = Timeline.create(document.getElementById("mytimeline"), bandInfos);
  /* XMLを取得して、カレンダーへ送付する。 */
 Timeline.loadXML('Timelineに表示するXMLアドレス', function(xml, url) { eventSource.loadXML(xml, url); });
}

var resizeTimerID = null;
function onResize() {
 if (resizeTimerID == null) {
  resizeTimerID = window.setTimeout(function() {
   resizeTimerID = null;
   tl.layout();
  }, 500);
 }
}



2.2 データ書き込みようXMLの作成
上記で、カレンダーの枠が完成するので、今度はそこに表示するデータを準備する。データは以下の関数のところで呼び出される。XMLのサンプルは、こちら


Timeline.loadXML('Timelineに表示するXMLアドレス', function(xml, url) { eventSource.loadXML(xml, url); });



で、このXMLファイルをGoogle Calendar API取得したXMLを書き換えて作成する。例えば、以下のような感じ。読み取ったものを書き換えるだけなので、それほどややこしくない。この途中でフィルタ掛けしたり、追加の情報を書き込むように(例えばデータベースを参照して)などすればより便利なものを作成することが出来るだろう。
あとは、上記の'Timelineに表示するXMLアドレス'のところに、以下の"保存するXMLファイル名"を書き込めば完成。


<?PHP //PHP関数
 public function GetGoogleCal(){
  $ResgcalInfo=new Getgooglecal; //上記のGoogle Calendar API 取得クラスを呼び出す。
  $ResgcalInfo->SetgoogleID("GoogleユーザーID");
  $GcalInfo=$ResgcalInfo->GetgcalInfo();
  //XMLファイルの作成
  $XMLout ='<?xml version="1.0" encoding="UTF-8" ?>';
  $XMLout.="\n";
  $XMLout.='<data>';
  $XMLout.="\n";
   //各イベントentryごとに<event>タグ情報を発行
   foreach($GcalInfo["entry"] as $value){ 
      $start=strtotime($value["startTime"]);
      $end=strtotime($value["endTime"]);
	 $XMLout.='<event ';
	 $XMLout.='start="'.date("r",$start).'" '; //開始時間
	 $XMLout.='end="'.date("r",$end).'" '; //終了時間
	 $XMLout.='isDuration="true" ';
	 $XMLout.='title="'.$value["title"].'" '; //Title
	 $XMLout.='image="" '; //写真
	 $XMLout.='>';
	 $XMLout.=htmlspecialchars($value["content"]); //内容
     $XMLout.="&lt;br&gt;";
	 $XMLout.='&lt;a target="_blank" href="'.$value["link"].'" &gt;'.$value["title"].'&lt;/a&gt;'; //リンクURL
     $XMLout.="\n";
	 $XMLout.='</event>';
     $XMLout.="\n";
    }
  $XMLout.='</data>';
  $XMLout.="\n";
  //Write to XML file
  $fpwrite = fopen("保存するXMLファイル名", "w");
  fwrite($fpwrite,$XMLout);
  fclose($fpwrite);
 }
?>



3.とりあえず
とりあえず、これで完成。ただし、これだと、表示のスタイルがいまいちなので、この表示部分をカスタマイズしていく。こちらは、次回に回します。


関連リンク:
dLINKbRING.Art
SIMILE | Timeline
Google Calendar
Google Calendar Data API Overview
Powered BY AmazoRogi