<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 17175 -->
<sect1 id="zend.gdata.gbase">
    <title>Google Base の使用法</title>
    <para>
        Google Base データ <acronym>API</acronym> は、開発者が以下のことを行えるように設計されています。
        <itemizedlist>
            <listitem>
                <para>
                    Google Base のデータに対して問い合わせを行うアプリケーションやマッシュアップを作成する
                </para>
                </listitem>
            <listitem>
                <para>
                    Google Base のアイテムをプログラム上で登録したり管理したりする
                </para>
            </listitem>
        </itemizedlist>
    </para>
    <para>
        アイテムのフィードには二種類があります。snippets フィードと customer items フィードです。
        snippets フィードにはすべての Google Base のデータが含まれ、
        認証なしで誰でも問い合わせることができます。
        customer items フィードは特定の顧客に特化したデータの一部で、
        そのカスタマー/オーナーだけがフィードにアクセスしてデータを追加、更新、削除することができます。
        どちらのフィードに対しても、クエリの作成方法は同じです。
    </para>
    <para>
        Google Base <acronym>API</acronym> についての詳細は
        <ulink url="http://code.google.com/apis/base/">http://code.google.com/apis/base</ulink>
        を参照ください。
    </para>
    <sect2 id="zend.gdata.gbase.connect">
        <title>Base サービスへの接続</title>
        <para>
            Google Base <acronym>API</acronym> は、他の GData <acronym>API</acronym> と同様に Atom Publishing Protocol (APP)
            を使用しています。これは、ウェブベースのリソースを扱うための
            XML 形式のフォーマットです。クライアントと Booble Base サーバとの間は
            <acronym>HTTP</acronym> による通信を行い、認証済みの接続と未認証の接続の両方に対応しています。
        </para>
        <para>
            トランザクションを実行するには、まずこの接続を作成する必要があります。
            Base サーバへの接続を作成するには、次の二段階の手順を踏みます。
            まずは <acronym>HTTP</acronym> クライアントを作成し、それから <classname>Zend_Gdata_Gbase</classname>
            サービスのインスタンスをそのクライアントにバインドします。
        </para>
        <sect3 id="zend.gdata.gbase.connect.authentication">
            <title>認証</title>
            <para>
                Google Base <acronym>API</acronym> は、公開 (public) フィードと非公開 (private)
                フィードの両方にアクセスすることができます。
                公開フィードへのアクセスには認証は不要です。
                しかし読み込み専用のアクセスとなり、機能も制限されます。
                非公開フィードに対してはほぼすべての機能を使用できますが、
                Base サーバに対する認証済みの接続が必要となります。
                Google Base がサポートする認証方式には三種類あります。
            </para>
            <itemizedlist>
                <listitem>
                    <para>
                        <firstterm>ClientAuth</firstterm>
                        は、ユーザ名/パスワードによる認証を Base サーバに対して直接行います。
                        この方式では、アプリケーションが直接パスワードを扱う必要があります。
                        したがって、この認証方式を使うのは、他の方式が使えない場合のみにしましょう。
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <firstterm>AuthSub</firstterm>
                        は、Google プロキシサーバを経由した認証を行います。
                        ClientAuth と同じくらい簡単に使用でき、セキュリティのリスクもありません。
                        ウェブベースのアプリケーションでは、これが最も望ましい方式です。
                    </para>
                </listitem>
            </itemizedlist>
            <para>
                <classname>Zend_Gdata</classname> ライブラリは、これら三種類の認証方式にすべて対応しています。
                本章のこれ以降では、読者が認証方式についてよく知っていること、
                そして認証済み接続の作成方法を知っていることを前提として説明を進めます。
                詳細な情報は、<xref linkend="zend.gdata.introduction.authentication" />
                あるいは
                <ulink url="http://code.google.com/apis/gdata/auth.html">Google Data <acronym>API</acronym> Developer's Guide
                の Authentication Overview</ulink>
                を参照ください。
            </para>
        </sect3>
        <sect3 id="zend.gdata.gbase.connect.service">
            <title>サービスのインスタンスの作成</title>
            <para>
                Google Base に対する作業を行うために
                <classname>Zend_Gdata_Gbase</classname> サービスクラスが用意されています。
                このクラスは Google Data および Atom Publishing Protocol
                に対する共通のインターフェイスを提供し、
                Base サーバとの間のリクエストのやりとりを支援します。
            </para>
            <para>
                使用する認証方式が決まったら、次に行うのは
                <classname>Zend_Gdata_Gbase</classname> のインスタンスを作成することです。
                このクラスの引数には <classname>Zend_Http_Client</classname>
                のインスタンスを指定します。これが AuthSub および ClientAuth
                認証へのインターフェイスとなる認証済みの <acronym>HTTP</acronym> クライアントです。
                引数を省略した場合は、未認証の
                <classname>Zend_Http_Client</classname> のインスタンスを自動的に作成します。
            </para>
            <para>
                以下の例は、ClientAuth 認証を使用した Base サービスクラスを作成するものです。
            </para>
            <programlisting language="php"><![CDATA[
// ClientAuth 認証用のパラメータ
$service = Zend_Gdata_Gbase::AUTH_SERVICE_NAME;
$user = "sample.user@gmail.com";
$pass = "pa$$w0rd";

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

// Base サービスのインスタンスを作成します
$service = new Zend_Gdata_Gbase($client);
]]></programlisting>
<para>AuthSub を使用した Base サービスの作成方法も同様ですが、少し冗長になります。</para>
<programlisting language="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/base/feeds/items/";
        $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;
}

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

// http://code.google.com/apis/gdata/reference.html#Queriesthat
// より、ユーザは正規のセッションを保持しています。そこで
// AuthSub セッショントークンを保存します
session_start();

// Base サービスのインスタンスを作成し、必要に応じて
// AuthSub サーバにリダイレクトします
$service = new Zend_Gdata_Gbase(getAuthSubHttpClient());
]]></programlisting>
<para>最後に、snippets フィード用の未認証のサーバを作成する方法を示します。</para>
<programlisting language="php"><![CDATA[
// Base サービスのインスタンスを、未認証の HTTP クライアントで作成します
$service = new Zend_Gdata_Gbase();
]]></programlisting>
        </sect3>
    </sect2>
    <sect2 id="zend.gdata.gbase.retrieve">
        <title>アイテムの取得</title>
        <para>
            customer items フィードや snippets フィードに問い合わせて、
            アイテムを取得することができます。
            これは、まずクエリを送信して
            返ってきたフィードを順に取得するという二段階の手順で行います。
        </para>
        <sect3 id="zend.gdata.gbase.retrieve.query">
            <title>構造化クエリの送信</title>
            <para>
                構造化クエリを送信することで、あなた自身の customer items
                フィードや公開 snippets フィードの内容を問い合わせることができます。
            </para>
            <para>
                Base <acronym>API</acronym> でデータを取得する際には、特別な構造のクエリ <acronym>URL</acronym>
                を使用してどんなイベントがほしいのかを指定します。
                <classname>Zend_Gdata_Gbase_ItemQuery</classname> および
                <classname>Zend_Gdata_Gbase_SnippetQuery</classname>
                クラスのおかげで、この作業が簡単にできるようになります。
                パラメータを指定すると、これらのクラスがクエリ URL を作成してくれるのです。
            </para>
            <sect4 id="zend.gdata.gbase.retrieve.query.customeritems">
                <title>Customer Items フィードに対する問い合わせ</title>
                <para>
                    customer items フィードに対するクエリを実行するには
                    <methodname>newItemQuery()</methodname> メソッドおよび <methodname>getGbaseItemFeed()</methodname>
                    メソッドを実行します。
                </para>
                <programlisting language="php"><![CDATA[
$service = new Zend_Gdata_Gbase($client);
$query = $service->newItemQuery();
$query->setBq('[title:Programming]');
$query->setOrderBy('modification_time');
$query->setSortOrder('descending');
$query->setMaxResults('5');
$feed = $service->getGbaseItemFeed($query);
]]></programlisting>
                <para>
                    使用できるパラメータの一覧は、Customer Items フィードのドキュメントにある
                    <ulink url="http://code.google.com/apis/base/items-feed.html#QueParameters">
                    クエリパラメータのセクション</ulink> を参照ください。
                </para>
            </sect4>
            <sect4 id="zend.gdata.gbase.retrieve.query.snippets">
                <title>Snippets フィードに対する問い合わせ</title>
                <para>
                    公開 snippets フィードに対するクエリを実行するには
                    <methodname>newSnippetQuery()</methodname> メソッドおよび
                    <methodname>getGbaseSnippetFeed()</methodname> メソッドを実行します。
                </para>
                <programlisting language="php"><![CDATA[
$service = new Zend_Gdata_Gbase();
$query = $service->newSnippetQuery();
$query->setBq('[title:Programming]');
$query->setOrderBy('modification_time');
$query->setSortOrder('descending');
$query->setMaxResults('5');
$feed = $service->getGbaseSnippetFeed($query);
]]></programlisting>
                <para>
                    使用できるパラメータの一覧は、Snippets フィードのドキュメントにある
                    <ulink url="http://code.google.com/apis/base/snippets-feed.html#Parameters">
                    クエリパラメータのセクション</ulink> を参照ください。
                </para>
            </sect4>
        </sect3>
        <sect3 id="zend.gdata.gbase.retrieve.iterate">
            <title>アイテムに対する順次処理</title>
            <para>
                Google Base のアイテムには、<code>&lt;g:main_ingredient&gt;</code>
                や <code>&lt;g:weight&gt;</code> といったアイテム固有の属性が含まれています。
            </para>
            <para>
                指定したアイテムのすべての属性を順に処理するには、
                <methodname>getGbaseAttributes()</methodname> を実行してその結果を処理します。
            </para>
            <programlisting language="php"><![CDATA[
foreach ($feed->entries as $entry) {
  // すべての属性を取得し、各属性について名前とテキスト値を表示します
  $baseAttributes = $entry->getGbaseAttributes();
  foreach ($baseAttributes as $attr) {
    echo "属性 " . $attr->name . " : " . $attr->text . "<br>";
  }
}
]]></programlisting>
            <para>
                あるいは、特定の属性の名前を指定してそれにマッチする結果を取得することもできます。
            </para>
            <programlisting language="php"><![CDATA[
foreach ($feed->entries as $entry) {
  // すべての主原料 <g:main_ingredient> を表示します
  $baseAttributes = $entry->getGbaseAttribute("main_ingredient");
  foreach ($baseAttributes as $attr) {
    echo "主原料: " . $attr->text . "<br>";
  }
}
]]></programlisting>
        </sect3>
    </sect2>
    <sect2 id="zend.gdata.gbase.crud">
        <title>Customer Items の追加、更新、削除</title>
        <para>
            カスタマー/オーナーは、自分自身の Customer Items
            フィードに対する追加、更新あるいは削除を行うことができます。
            これらの操作は、公開 snippets フィードに対して行うことはできません。
        </para>
        <para>
            実際に処理を行う前に、どのような操作が行われるのかを確かめることができます。
            その場合は dry-run フラグ (<code>$dryRun</code>) を <constant>TRUE</constant>
            に設定します。期待通りの結果が得られることを確認したら、このフラグを
            <constant>FALSE</constant> にして実際の操作を行います。
        </para>
        <sect3 id="zend.gdata.gbase.crud.insert">
            <title>アイテムの追加</title>
            <para>
                アイテムを追加するには、Base サービスの
                <methodname>insertGbaseItem()</methodname> メソッドを使用します。
            </para>
            <programlisting language="php"><![CDATA[
$service = new Zend_Gdata_Gbase($client);
$newEntry = $service->newItemEntry();

// タイトルを追加します
$title = "PHP Developer Handbook";
$newEntry->title = $service->newTitle(trim($title));

// コンテンツを追加します
$content = "Essential handbook for PHP developers.";
$newEntry->content = $service->newContent($content);
$newEntry->content->type = 'text';

// 製品の型を定義します
$itemType = "Products";
$newEntry->itemType = $itemType;

// アイテム固有の属性を追加します
$newEntry->addGbaseAttribute("product_type", "book", "text");
$newEntry->addGbaseAttribute("price", "12.99 USD", "floatUnit");
$newEntry->addGbaseAttribute("quantity", "10", "int");
$newEntry->addGbaseAttribute("weight", "2.2 lbs", "numberUnit");
$newEntry->addGbaseAttribute("condition", "New", "text");
$newEntry->addGbaseAttribute("author", "John Doe", "text");
$newEntry->addGbaseAttribute("edition", "First Edition", "text");
$newEntry->addGbaseAttribute("pages", "253", "number");
$newEntry->addGbaseAttribute("publisher", "My Press", "text");
$newEntry->addGbaseAttribute("year", "2007", "number");
$newEntry->addGbaseAttribute("payment_accepted", "Google Checkout", "text");

$dryRun = true;
$createdEntry = $service->insertGbaseItem($newEntry, $dryRun);
]]></programlisting>
        </sect3>
        <sect3 id="zend.gdata.gbase.crud.modify">
            <title>アイテムの変更</title>
            <para>
                アイテムの各属性要素の値を変更することができます。
            </para>
            <programlisting language="php"><![CDATA[
// タイトルを更新します
$newTitle = "PHP Developer Handbook Second Edition";
$entry->title = $service->newTitle($newTitle);

// <g:price> 属性を探し、価格を更新します
$baseAttributes = $entry->getGbaseAttribute("price");
if (is_object($baseAttributes[0])) {
  $newPrice = "16.99 USD";
  $baseAttributes[0]->text = $newPrice;
}

// <g:pages> 属性を探し、ページ数を更新します
$baseAttributes = $entry->getGbaseAttribute("pages");
if (is_object($baseAttributes[0])) {
  $newPages = "278";
  $baseAttributes[0]->text = $newPages;

  // 属性の型を "number" から "int" に変更します
  if ($baseAttributes[0]->type == "number") {
    $newType = "int";
    $baseAttributes[0]->type = $newType;
  }
}

// <g:label> 属性を削除します
$baseAttributes = $entry->getGbaseAttribute("label");
foreach ($baseAttributes as $note) {
  $entry->removeGbaseAttribute($note);
}

// 新たな属性を追加します
$entry->addGbaseAttribute("note", "PHP 5", "text");
$entry->addGbaseAttribute("note", "Web Programming", "text");

// エントリオブジェクトの save() を実行して変更内容を保存します
$dryRun = true;
$entry->save($dryRun);

// あるいは、サービスオブジェクトの updateGbaseItem() をコールして変更を保存します
// $dryRun = true;
// $service->updateGbaseItem($entry, $dryRun);
]]></programlisting>
            <para>
                変更した後は、<classname>Zend_Gdata_Gbase_ItemEntry</classname>
                オブジェクトの <methodname>save($dryRun)</methodname> メソッドを実行するか
                <classname>Zend_Gdata_Gbase</classname> オブジェクトの
                <methodname>updateGbaseItem($entry, $dryRun)</methodname>
                メソッドをコールしてその内容を保存する必要があります。
            </para>
        </sect3>
        <sect3 id="zend.gdata.gbase.crud.delete">
            <title>アイテムの削除</title>
            <para>
                アイテムを削除するには、<methodname>deleteGbaseItem()</methodname>
                メソッドをコールします。
            </para>
            <programlisting language="php"><![CDATA[
$dryRun = false;
$service->deleteGbaseItem($entry, $dryRun);
]]></programlisting>
            <para>
                あるいは、<classname>Zend_Gdata_Gbase_ItemEntry</classname> オブジェクトの
                <methodname>delete()</methodname> を実行することもできます。
            </para>
            <programlisting language="php"><![CDATA[
$dryRun = false;
$entry->delete($dryRun);
]]></programlisting>
        </sect3>
    </sect2>
</sect1>
