<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 15103 -->
<sect1 id="zend.gdata.calendar">
    <title>Google Calendar の使用法</title>
    <para>
        <classname>Zend_Gdata_Calendar</classname>
        クラスを使うと、Google Calendar サービスで
        イベントの閲覧や作成、更新、削除ができるようになります。
    </para>
    <para>
        Google Calendar API についての詳細な情報は
        <ulink url="http://code.google.com/apis/calendar/overview.html">http://code.google.com/apis/calendar/overview.html</ulink>
        を参照ください。
    </para>
    <sect2 id="zend.gdata.calendar.connecting">
        <title>Calendar サービスへの接続</title>
        <para>
            Google Calendar API は、その他の GData API と同様に
            Atom Publishing Protocol (APP) を使用しています。これは、XML
            ベースのフォーマットでウェブのリソースを管理するための仕組みです。
            クライアントと Google Calendar サーバとの間のやり取りは
            HTTP で行われ、認証済みの接続と未認証の接続の両方が利用できます。
        </para>
        <para>
            何らかのトランザクションが発生する際には、
            必ず接続を確立する必要があります。
            カレンダーサーバとの接続は、まず HTTP クライアントを作成して
            <classname>Zend_Gdata_Calendar</classname>
            サービスのインスタンスをそこにバインドするという手順で行います。
        </para>
        <sect3 id="zend.gdata.calendar.connecting.authentication">
            <title>認証</title>
            <para>
                Google Calendar API を使用すると、公開カレンダーだけでなく
                プライベートカレンダーのフィードにもアクセスすることができます。
                公開フィードには認証は不要ですが、
                認証しない場合は読み込み専用となり、機能が制限されます。
                プライベートフィードでは完全な機能が使用できますが、
                カレンダーサーバとの認証が必要になります。
                Google Calendar がサポートしている認証方式は、次の 3 通りです。
            </para>
            <itemizedlist>
                <listitem>
                    <para>
                        <firstterm>ClientAuth</firstterm>
                        は、カレンダーサーバとの間で直接
                        ユーザ名/パスワード
                        による認証を行います。この方式では
                        ユーザ自身がアプリケーションにパスワードを教える必要があるので、
                        これは他の方式が使えない場合にのみ使用するようにしましょう。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>AuthSub</firstterm>
                        は、Gooble のプロキシサーバを経由してカレンダーサーバとの認証を行ないます。
                        これは ClientAuth と同じくらい便利に使用でき、
                        セキュリティリスクもありません。
                        ウェブベースのアプリケーションでは、
                        これは最適な選択肢となります。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>MagicCookie</firstterm>
                        は、Google Calendar インターフェイス内の
                        半ランダムな URL にもとづいた認証を行なう方法です。
                        この方法は、実装するのが一番簡単です。しかし、
                        ユーザ自身が安全な URL を事前に取得しないと認証できません
                        またカレンダーリストにはアクセスできず、
                        アクセスは読み込み専用に制限されます。
                    </para>
                </listitem>
            </itemizedlist>
            <para>
                <classname>Zend_Gdata</classname> ライブラリは、
                これらのすべての方式に対応しています。
                これ以降の説明は、認証方式については理解しており
                適切な認証方式で接続できるようになっていることを前提として進めていきます。
                詳細な情報は、このマニュアルの
                <link linkend="zend.gdata.introduction.authentication">認証に関するセクション</link>
                か、あるいは
                <ulink url="http://code.google.com/apis/gdata/auth.html">Google Data API Developer's Guide
                の Authentication Overview</ulink>
                を参照ください。
            </para>
        </sect3>
        <sect3 id="zend.gdata.calendar.connecting.service">
            <title>サービスのインスタンスの作成</title>
            <para>
                Google Calendar を使用するためのクラスとして、このライブラリでは
                <classname>Zend_Gdata_Calendar</classname> を用意しています。
                このクラスは Google Data や Atom Publishing Protocol
                モデルへの共通インターフェイスを提供し、
                カレンダーサーバとのリクエストのやりとりを支援します。
            </para>
            <para>
                使用する認証方式を決めたら、次に
                <classname>Zend_Gdata_Calendar</classname> のインスタンスを作成します。
                このクラスのコンストラクタには、引数として
                <classname>Zend_Http_Client</classname> のインスタンスを渡します。
                これは、AuthSub 認証および ClientAuth 認証へのインターフェイスを提供します。
                これらの認証を使用する場合には、認証済みの HTTP クライアントが必要です。
                引数を省略した場合は、未認証の
                <classname>Zend_Http_Client</classname>
                のインスタンスを自動的に作成して使用します。
            </para>
            <para>
                以下の例は、ClientAuth 認証を使用して Calendar サービスを作成するものです。
            </para>
            <programlisting role="php"><![CDATA[
// ClientAuth 認証用のパラメータ
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$user = "sample.user@gmail.com";
$pass = "pa$$w0rd";

// 認証済みの HTTP クライアントを作成します
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);

// Calendar サービスのインスタンスを作成します
$service = new Zend_Gdata_Calendar($client);
]]>
            </programlisting>
            <para>
                AuthSub を使用する Calendar サービスを作成するのもほぼ同様ですが、
                少々長めになります。
            </para>
            <programlisting role="php"><![CDATA[

/*
 * 現在の URL を取得し、AuthSub サーバに
 * 認証後のリダイレクト先を伝えられるようにします
 */
function getCurrentUrl()
{
    global $_SERVER;

    // php_self をフィルタリングし、セキュリティを確保します
    $php_request_uri =
        htmlentities(substr($_SERVER['REQUEST_URI'],
                            0,
                            strcspn($_SERVER['REQUEST_URI'], "\n\r")),
                            ENT_QUOTES);

    if (isset($_SERVER['HTTPS']) &&
        strtolower($_SERVER['HTTPS']) == 'on') {
        $protocol = 'https://';
    } else {
        $protocol = 'http://';
    }
    $host = $_SERVER['HTTP_HOST'];
    if ($_SERVER['HTTP_PORT'] != '' &&
        (($protocol == 'http://' && $_SERVER['HTTP_PORT'] != '80') ||
        ($protocol == 'https://' && $_SERVER['HTTP_PORT'] != '443'))) {
        $port = ':' . $_SERVER['HTTP_PORT'];
    } else {
        $port = '';
    }
    return $protocol . $host . $port . $php_request_uri;
}

/**
 * AuthSub 認証済みの HTTP クライアントを作成し、ログインが必要なら
 * ユーザを AuthSub サーバにリダイレクトします
 */
function getAuthSubHttpClient()
{
    global $_SESSION, $_GET;

    // AuthSub セッションあるいはワンタイムトークンがなければ、
    // AuthSub サーバにリダイレクトします
    if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) {
        // AuthSub サーバへのパラメータ
        $next = getCurrentUrl();
        $scope = "http://www.google.com/calendar/feeds/";
        $secure = false;
        $session = true;

        // ユーザを AuthSub サーバにリダイレクトします

        $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
                                                             $scope,
                                                             $secure,
                                                             $session);
         header("HTTP/1.0 307 Temporary redirect");

         header("Location: " . $authSubUrl);

         exit();
    }

    // AuthSub のワンタイムトークンを、必要に応じてセッショントークンに変換します
    if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) {
        $_SESSION['sessionToken'] =
            Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
    }

    // この時点で AuthSub による認証がすんでいるので、
    // 認証済みの HTTP クライアントのインスタンスを作成することができます

    // 認証済みの HTTP クライアントを作成します
    $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
    return $client;
}

// -> スクリプトの実行はここから始まります <-

// ユーザが有効なセッションを保持していることを確認し、
// AuthSub セッショントークンを記録します
session_start();

// Calendar サービスのインスタンスを作成し、
// 必要に応じてユーザを AuthSub サーバにリダイレクトします
$service = new Zend_Gdata_Calendar(getAuthSubHttpClient());
]]>
            </programlisting>
            <para>未認証のサーバを作成して、公開フィードへのアクセスや MagicCookie 認証で使用することができます。</para>
            <programlisting role="php"><![CDATA[
// Calendar サービスのインスタンスを、
// 未認証の HTTP クライアントで作成します

$service = new Zend_Gdata_Calendar();
]]>
            </programlisting>
            <para>
                MagicCookie 認証は HTTP 接続で提供するものではなく、
                クエリを送信する際の可視性を指定するものです。
                以下にあるイベント取得の例を見てみましょう。
            </para>
        </sect3>
    </sect2>
    <sect2 id="zend.gdata.calendar_retrieval">
        <title>カレンダーリストの取得</title>
        <para>
            カレンダーサービスには、
            認証済みのユーザのカレンダーの一覧を取得する機能があります。
            これは Google Calendar の画面に表示される一覧と同じですが、
            "<code>hidden</code>" とマークされているものも取得できるという点が異なります。
        </para>
        <para>
            カレンダーリストは常に非公開なので、認証済み接続でアクセスする必要があります。
            別のユーザのカレンダーリストを取得したり、MagicCookie
            認証でアクセスしたりすることはできません。
            適切な認証情報を持たずにカレンダーリストにアクセスしようとすると、
            その処理は失敗し、ステータスコード 401 (Authentication Required) を返します。
        </para>
        <programlisting role="php"><![CDATA[
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Calendar($client);

try {
    $listFeed= $service->getCalendarListFeed();
} catch (Zend_Gdata_App_Exception $e) {
    echo "エラー: " . $e->getMessage();
}
]]>
        </programlisting>
        <para>
            <code>getCalendarListFeed()</code> をコールすると
            <classname>Zend_Gdata_Calendar_ListFeed</classname>
            の新しいインスタンスを作成します。この中には、使用できるカレンダーの一覧が
            <classname>Zend_Gdata_Calendar_ListEntry</classname>
            のインスタンスとして格納されています。
            フィードを取得したら、それを使用して中身を取得することができます。
        </para>
        <programlisting role="php"><![CDATA[
echo "<h1>カレンダーリストのフィード</h1>";
echo "<ul>";
foreach ($listFeed as $calendar) {
    echo "<li>" . $calendar->title .
         " (Event Feed: " . $calendar->id . ")</li>";
}
echo "</ul>";
]]>
        </programlisting>
    </sect2>
    <sect2 id="zend.gdata.event_retrieval">
        <title>イベントの取得</title>
        <para>
            カレンダーリストと同様、イベントも
            <classname>Zend_Gdata_Calendar</classname>
            クラスで取得することができます。
            返されるイベントリストの型は
            <classname>Zend_Gdata_Calendar_EventFeed</classname>
            で、各イベントは
            <classname>Zend_Gdata_Calendar_EventEntry</classname>
            のインスタンスとして格納されています。
            先ほどの例と同様の方法で、個々のイベントの情報を取得することができます。
        </para>
        <sect3 id="zend.gdata.event_retrieval.queries">
            <title>クエリ</title>
            <para>
                Calendar API でイベントを取得する際には、
                クエリ URL を用いてほしいイベントを指定します。
                <classname>Zend_Gdata_Calendar_EventQuery</classname> クラスは、
                指定したパラメータに基づいたクエリ URL
                を自動的に作成することでこの作業の手間を軽減します。
                使用できるパラメータの一覧は
                <ulink url="http://code.google.com/apis/gdata/reference.html#Queries">
                Google Data APIs Protocol Reference の Queries セクション</ulink>
                にあります。ここでは、そのうち特に重要な
                3 つのパラメータについて説明します。
            </para>
            <itemizedlist>
                <listitem>
                    <para>
                        <firstterm>User</firstterm>
                        は、誰のカレンダーを検索するのかをメールアドレスで指定します。
                        省略した場合は "default" を使用します。
                        これは、現在認証されているユーザ (認証済みの場合)
                        を表します。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Visibility</firstterm>
                        は、公開カレンダーと非公開カレンダーの
                        どちらを検索するのかを指定します。
                        未認証のセッションを使用していて
                        MagicCookie もない場合は、
                        公開フィードのみしか使用できません。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Projection</firstterm>
                        は、サーバから返されるデータの件数とフォーマットを指定します。
                        たいていの場合は "full" を指定することになるでしょう。
                        "basic" を指定すると、ほとんどのメタデータ情報を
                        各イベントの content フィールドの可読形式で格納します。
                        "composite" を指定すると、各イベントについてのコメントも情報に付加します。
                        "composite" は、"full"
                        よりも巨大になることもあります。
                    </para>
                </listitem>
            </itemizedlist>
        </sect3>
        <sect3 id="zend.gdata.event_retrieval.start_time">
            <title>開始時刻順によるイベントの取得</title>
            <para>
                以下の例は、
                <classname>Zend_Gdata_Query</classname> を使用して非公開フィードを指定しています。
                つまり、認証済みの接続が必要となります。
                認証に MagicCookie を使用している場合は、可視性は
                "<code>private-magicCookieValue</code>"
                としなければなりません。magicCookieValue
                のところは、Google Calendar で非公開
                XML アドレスを閲覧した際に取得したランダムな文字列となります。
                イベントは開始時刻の順に取得され、
                過去のイベントは返されません。
            </para>
            <programlisting role="php"><![CDATA[
$query = $service->newEventQuery();
$query->setUser('default');
// MagicCookie 認証の場合は
// $query->setVisibility('private-magicCookieValue') とします
$query->setVisibility('private');
$query->setProjection('full');
$query->setOrderby('starttime');
$query->setFutureevents('true');

// カレンダーサーバからイベントの一覧を取得します
try {
    $eventFeed = $service->getCalendarEventFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "エラー: " . $e->getMessage();
}

// リストの内容を順に取得し、HTML のリストとして出力します
echo "<ul>";
foreach ($eventFeed as $event) {
    echo "<li>" . $event->title . " (Event ID: " . $event->id . ")</li>";
}
echo "</ul>";
]]>
            </programlisting>
            <para>
                ID や author、when、event status、visibility、web content、
                そして content などのさまざまなプロパティが
                <classname>Zend_Gdata_Calendar_EventEntry</classname>
                で使用できます。プロパティの一覧は
                <ulink url="http://framework.zend.com/apidoc/core/">Zend Framework
                API ドキュメント</ulink>
                や
                <ulink url="http://code.google.com/apis/gdata/reference.html">Calendar Protocol Reference</ulink>
                を参照ください。
            </para>
        </sect3>
        <sect3 id="zend.gdata.event_retrieval.date_range">
            <title>指定した日付の範囲からのイベントの取得</title>
            <para>
                指定した範囲、たとえば 2006 年 12 月 1 日から
                2006 年 12 月 15 日までのすべてのイベントを表示するには、
                先ほどのサンプルに次の 2 行を追加します。
                "<code>$query->setFutureevents('true')</code>"
                を削除することを忘れないでください。
                <code>futureevents</code>
                を指定すると
                <code>startMin</code>
                や
                <code>startMax</code>
                を上書きしてしまうからです。
            </para>
            <programlisting role="php"><![CDATA[
$query->setStartMin('2006-12-01');
$query->setStartMax('2006-12-16');
]]>
            </programlisting>
            <para>
                <code>startMin</code>
                は範囲に含まれますが、
                <code>startMax</code>
                は含まれないことに注意しましょう。上の例の場合、
                2006-12-15 23:59:59 までのイベントが対象となります。
            </para>
        </sect3>
        <sect3 id="zend.gdata.event_retrieval.fulltext">
            <title>全文検索によるイベントの取得</title>
            <para>
                指定した単語、たとえば "dogfood"
                を含むすべてのイベントを表示するには、
                <code>setQuery()</code>
                メソッドでクエリを作成します。
            </para>
            <programlisting role="php"><![CDATA[
$query->setQuery("dogfood");
]]>
            </programlisting>
        </sect3>
        <sect3 id="zend.gdata.event_retrieval.individual">
            <title>特定のイベントの取得</title>
            <para>
                特定のイベントを取得する場合は、そのイベントの ID
                をクエリで指定します。そして
                <code>getCalendarEventFeed()</code>
                ではなく
                <code>getCalendarEventEntry()</code>
                をコールします。
            </para>
            <programlisting role="php"><![CDATA[
$query = $service->newEventQuery();
$query->setUser('default');
$query->setVisibility('private');
$query->setProjection('full');
$query->setEvent($eventId);

try {
    $event = $service->getCalendarEventEntry($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "エラー: " . $e->getMessage();
}
]]>
            </programlisting>
            <para>
                同様に、もしそのイベントの URL がわかっているのなら、
                それを直接 <code>getCalendarEntry()</code>
                に渡して特定のイベントを取得することもできます。
                この場合はクエリオブジェクトは不要です。
                必要な情報は、イベントの URL にすべて含まれているからです。
            </para>
            <programlisting role="php"><![CDATA[
$eventURL = "http://www.google.com/calendar/feeds/default/private"
          . "/full/g829on5sq4ag12se91d10uumko";

try {
    $event = $service->getCalendarEventEntry($eventURL);
} catch (Zend_Gdata_App_Exception $e) {
    echo "エラー: " . $e->getMessage();
}
]]>
            </programlisting>
        </sect3>
    </sect2>
    <sect2 id="zend.gdata.calendar.creating_events">
        <title>イベントの作成</title>
        <sect3 id="zend.gdata.calendar.creating_events.single">
            <title>一度だけのイベントの作成</title>
            <para>
                イベントをカレンダーに追加するには、
                <classname>Zend_Gdata_EventEntry</classname> のインスタンスを作成して
                そこに適切なデータを代入します。カレンダーサービスのインスタンス
                (<classname>Zend_Gdata_Calendar</classname>) はそのデータを XML
                に変換し、カレンダーサーバに POST します。
                イベントを作成するには、AuthSub 認証あるいは
                ClientAuth 認証でカレンダーサーバと接続する必要があります。
            </para>
            <para>最低限設定しなければならない属性は、次のとおりです。</para>
            <itemizedlist>
                <listitem>
                    <para>
                        <firstterm>Title</firstterm>
                        は、Google Calendar でイベントの見出しとして表示される内容です。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>When</firstterm>
                        は、そのイベントの期間を表します。
                        オプションで、リマインダーを関連付けることができます。
                        この属性については、次のセクションで詳しく説明します。
                    </para>
                </listitem>
            </itemizedlist>
            <para>その他、オプションで設定できる属性は次のようになります。</para>
            <itemizedlist>
                <listitem>
                    <para>
                        <firstterm>Author</firstterm>
                        は、そのイベントを作成したユーザについての情報です。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Content</firstterm>
                        は、イベントの詳細情報です。
                        Google Calendar でそのイベントの詳細情報を開いたときに表示されます。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>EventStatus</firstterm>
                        はそのイベントが確認済み (confirmed)
                        なのか仮の予定 (tentative) なのか、
                        あるいは取り消された (canceled) を表します。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Hidden</firstterm>
                        は、そのイベントを Google Calendar 上で非表示にします。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Transparency</firstterm>
                        は、そのイベントをユーザの予定表に反映させるかどうかを指定します。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>WebContent</firstterm>
                        は、そのイベント内で外部のコンテンツへのリンクを指定します。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Where</firstterm>
                        は、そのイベントの場所を指定します。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>Visibility</firstterm>
                        は、そのイベントを公開リスト上では非表示にします。
                    </para>
                </listitem>
            </itemizedlist>
            <para>
                イベントの属性の一覧は、
                <ulink url="http://framework.zend.com/apidoc/core/">Zend Framework API
                ドキュメント</ulink>
                および
                <ulink url="http://code.google.com/apis/gdata/reference.html">Calendar
                Protocol Reference</ulink>
                を参照ください。
                where のように複数の値を持つことのある属性は配列で実装しています。
                それにあわせて適切な形式にする必要があります。これらの属性には、
                パラメータとしてオブジェクトを渡さなければならないことに注意しましょう。
                文字列などを渡そうとすると、XML への変換時にエラーとなります。
            </para>
            <para>
                イベントの情報を設定したら、それをカレンダーサーバにアップロードします。
                アップロードするには、カレンダーサーバの
                <code>insertEvent()</code> 関数の引数としてそのイベントを渡します。
            </para>
            <programlisting role="php"><![CDATA[
// カレンダーサービスのマジックメソッドで、新規エントリを作成します
$event= $service->newEventEntry();

// イベントの情報を設定します
// 各属性は、対応するクラスのインスタンスとして作成されることに注意しましょう
$event->title = $service->newTitle("My Event");
$event->where = array($service->newWhere("Mountain View, California"));
$event->content =
    $service->newContent(" This is my awesome event. RSVP required.");

// RFC 3339 形式で日付を指定します
$startDate = "2008-01-20";
$startTime = "14:00";
$endDate = "2008-01-20";
$endTime = "16:00";
$tzOffset = "-08";

$when = $service->newWhen();
$when->startTime = "{$startDate}T{$startTime}:00.000{$tzOffset}:00";
$when->endTime = "{$endDate}T{$endTime}:00.000{$tzOffset}:00";
$event->when = array($when);

// イベントをカレンダーサーバにアップロードします
// サーバに記録したイベントのコピーが返されます
$newEvent = $service->insertEvent($event);
]]>
            </programlisting>
        </sect3>
        <sect3 id="zend.gdata.calendar.creating_events.schedulers_reminders">
            <title>イベントのスケジュールおよびリマインダー</title>
            <para>
                イベントの開始時刻と期間は <code>when</code> プロパティによって決まります。
                この中には
                <code>startTime</code>、<code>endTime</code>
                および <code>valueString</code>
                というプロパティが含まれます。
                <code>StartTime</code> および <code>EndTime</code>
                がイベントの期間を表します。一方 <code>valueString</code>
                は現在使われていません。
            </para>
            <para>
                全日のイベントを作成するには、
                <code>startTime</code>
                および
                <code>endTime</code>
                で日付のみを指定し、時刻は省略します。
                同様に、期間がゼロのイベントを作成する場合は
                <code>endTime</code> を省略します。
                すべての場合について、日付や時刻は
                <ulink url="http://www.ietf.org/rfc/rfc3339.txt">RFC3339</ulink>
                形式で指定しなければなりません。
            </para>
            <programlisting role="php"><![CDATA[
// 2007 年 12 月 5 日の午後 2 時 (UTC-8) から
// 1 時間のイベントを設定します
$when = $service->newWhen();
$when->startTime = "2007-12-05T14:00:00-08:00";
$when->endTime="2007-12-05T15:00:00:00-08:00";

// when プロパティをイベントに追加します
$event->when = array($when);
]]>
            </programlisting>
            <para>
                <code>when</code> 属性では、
                ユーザへのリマインダーをいつ送信するかを指定することもできます。
                リマインダーは配列形式で保存し、各イベントには
                5 つまでのリマインダーを関連づけることができます。
            </para>
            <para>
                <code>reminder</code> を指定するには、少なくともふたつの属性
                <code>method</code> と time を指定する必要があります。
                <code>method</code> には "alert"、"email"
                あるいは "sms" を文字列で指定します。time
                は整数値で指定します。
                <code>minutes</code>、<code>hours</code>、<code>days</code>
                を指定するか、あるいは
                <code>absoluteTime</code> を指定します。
                しかし、指定するのはこれらの中のどれかひとつのみとしなければなりません。
                複数の単位が必要な場合は、一番小さい単位に換算して指定します。
                たとえば、1 時間 30 分の場合は 90 分と指定しなければなりません。
            </para>
            <programlisting role="php"><![CDATA[
// 新しいリマインダーオブジェクトを作成します。
// 予定の 10 分前に、メールでメッセージを送るようにします
$reminder = $service->newReminder();
$reminder->method = "email";
$reminder->minutes = "10";

// 既存のイベントの when プロパティにリマインダーを適用します
$when = $event->when[0];
$when->reminders = array($reminder);
]]>
            </programlisting>
        </sect3>
        <sect3 id="zend.gdata.calendar.creating_events.recurring">
            <title>繰り返し発生するイベントの作成</title>
            <para>
                繰り返し発生するイベントの作成方法は、
                一回しか発生しないイベントの場合と同じです。
                ただ、when 属性の代わりに recurrence 属性を指定する必要があります。
                recurrence 属性は、そのイベントの繰り返しパターンを文字列で指定します。
                この文字列は、iCalendar の標準規格 (
                <ulink url="http://www.ietf.org/rfc/rfc2445.txt">RFC 2445</ulink>
                ) で定義されているものを使用します。
            </para>
            <para>
                繰り返しパターンの例外は、別途
                <code>recurrenceException</code> 属性で指定します。
                しかし、iCalendar の標準規格では第二の繰り返しパターンを定義することができます。
                どちらかを使用するといいでしょう。
            </para>
            <para>
                繰り返しパターンの解析は複雑なので、詳細はこのドキュメントでは扱いません。
                詳細な情報を知りたい場合は、
                <ulink url="http://code.google.com/apis/gdata/elements.html#gdRecurrence">Google
                Data APIs Developer Guide の Common Elements セクション</ulink>
                あるいは RFC 2445 を参照ください。
            </para>
            <programlisting role="php"><![CDATA[
 // カレンダーサービスのマジックメソッドで、新規エントリを作成します
$event= $service->newEventEntry();

// イベントの情報を設定します
// 各属性は、対応するクラスのインスタンスとして作成されることに注意しましょう
$event->title = $service->newTitle("My Recurring Event");
$event->where = array($service->newWhere("Palo Alto, California"));
$event->content =
    $service->newContent(' This is my other awesome event, ' .
                         ' occurring all-day every Tuesday from .
                         '2007-05-01 until 207-09-04. No RSVP required.');

// 繰り返しパターンの期間と頻度を指定します

$recurrence = "DTSTART;VALUE=DATE:20070501\r\n" .
        "DTEND;VALUE=DATE:20070502\r\n" .
        "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n";

$event->recurrence = $service->newRecurrence($recurrence);

// イベントをカレンダーサーバにアップロードします
// サーバに記録したイベントのコピーが返されます
$newEvent = $service->insertEvent($event);
]]>
            </programlisting>
        </sect3>
        <sect3 id="zend.gdata.calendar.creating_events.quickadd">
            <title>QuickAdd の使用法</title>
            <para>
                QuickAdd とは、自由形式のテキストでイベントを作成する機能のことです。
                たとえば、"Dinner at Joe's Diner on Thursday" という文字列を指定すると、
                タイトルが "Dinner"、場所が "Joe's Diner"、日付が "Thursday"
                のイベントが作成されます。QuickAdd 機能を使用するには、
                <code>QuickAdd</code> プロパティを "true" に設定し、
                テキストを <code>content</code> プロパティに指定します。
            </para>
            <programlisting role="php"><![CDATA[
// カレンダーサービスのマジックメソッドで、新規エントリを作成します
$event= $service->newEventEntry();

// イベントの情報を設定します
$event->content= $service->newContent("Dinner at Joe's Diner on Thursday");
$event->quickAdd = $service->newQuickAdd("true");

// イベントをカレンダーサーバにアップロードします
// サーバに記録したイベントのコピーが返されます
$newEvent = $service->insertEvent($event);
]]>
            </programlisting>
        </sect3>
    </sect2>
    <sect2 id="zend.gdata.calendar.modifying_events">
        <title>イベントの変更</title>
        <para>
            イベントのインスタンスを取得したら、
            新しいイベントを作成する場合と同じようにしてその属性を変更できます。
            変更が完了したら、そのイベントの <code>save()</code>
            メソッドをコールすると、変更内容をカレンダーサーバにアップロードします。
            そして、更新後のイベントのコピーを返します。
        </para>
        <para>
            イベントを取得した後で別のユーザがそのイベントを変更していた場合、
            <code>save()</code> は失敗し、ステータスコード 409 (Conflict)
            を返します。これを解決するには、
            変更を加える直前に最新のコピーを取得する必要があります。
        </para>
        <programlisting role="php"><![CDATA[
// ユーザのイベントリストから最初のイベントを取得します
$event = $eventFeed[0];

// タイトルを変更します
$event->title = $service->newTitle("Woof!");

// 変更をサーバにアップロードします
try {
    $event->save();
} catch (Zend_Gdata_App_Exception $e) {
    echo "エラー: " . $e->getMessage();
}
]]>
        </programlisting>
    </sect2>
    <sect2 id="zend.gdata.calendar.deleting_events">
        <title>イベントの削除</title>
        <para>
            カレンダーのイベントを削除する方法には二通りあります。
            ひとつはカレンダーサービスの <code>delete()</code>
            メソッドにそのイベントの編集用 URL を指定する方法、
            もうひとつはそのイベント自身の <code>delete()</code>
            メソッドをコールすることです。
        </para>
        <para>
            どちらの場合も、クエリのパラメータ <code>updateMin</code>
            を指定した場合は削除後もそのイベントが
            プライベートイベントフィードとして残ります。
            削除されたイベントと通常のイベントを区別するには
            <code>eventStatus</code> プロパティを確認します。
            削除されたイベントは、このプロパティが
            "http://schemas.google.com/g/2005#event.canceled"
            に設定されています。
        </para>
        <programlisting role="php"><![CDATA[
// 方法 1: イベントを直接削除します
$event->delete();
]]>
        </programlisting>
        <programlisting role="php"><![CDATA[
// 方法 2: カレンダーサービスに、
// 削除したいイベントの編集 URL を渡します
$service->delete($event->getEditLink()->href);
]]>
        </programlisting>
    </sect2>
    <sect2 id="zend.gdata.calendar.comments">
        <title>イベントのコメントへのアクセス</title>
        <para>
            full イベントビューでは、コメントはイベントのエントリに保存されません。
            その代わりとして、各イベントにはコメントの URL が含まれており、
            それを使用して手動でコメントを取得することになります。
        </para>
        <para>
            コメントの操作方法は、イベントの場合とよく似ています。
            ただ、使用するフィードクラスやエントリクラスは異なります。
            またイベントのメタデータにある where や when
            といったプロパティはコメントにはありません。コメントの発言者は
            <code>author</code> プロパティに、そしてコメントの本文は
            <code>content</code> プロパティに格納されます。
        </para>
        <programlisting role="php"><![CDATA[
// コメントの URL を、フィードリストの最初のイベントから取得します
$event = $eventFeed[0];
$commentUrl = $event->comments->feedLink->url;

// そのイベントのコメント一覧を取得します
try {
$commentFeed = $service->getFeed($commentUrl);
} catch (Zend_Gdata_App_Exception $e) {
    echo "エラー: " . $e->getMessage();
}

// 各コメントを HTML のリストで出力します
echo "<ul>";
foreach ($commentFeed as $comment) {
    echo "<li><em>Comment By: " . $comment->author->name "</em><br/>" .
         $comment->content . "</li>";
}
echo "</ul>";
]]>
        </programlisting>
    </sect2>
</sect1>
