PHP 4/5 class library for Google Data APIs

I made this library before the release of Zend Google Data Client Library. Zend's library is dedicated to PHP 5. If you use PHP 5, you should use Zend's instead.

In fact, this library was made to be used in my application of Google Calendar for Japanese web-capable cellphones. The application is a more practical example of the usage of this library.


Download ZIP archive

Contents of the archive

Overview

The Google_GData class provides basic functions to communicate with the API of Google Data (GData for short) compliant services such as Google Calendar, Blogger or Google Base. The class is based upon the Google_Account class which works with Google's account authentication APIs - ClientLogin and AuthSub.
The class requires PEAR HTTP_Request class as well as its dependencies. It also requires OpenSSL to have HTTPS communication with account authentication APIs.

The Google_Calendar and the Google_Blogger are an extended class of the Google_GData, specific to each service for more convenient use.

Sample Applications

There are two sample applications in the archive.

Basic Usage

The following might be the simplest example to get a Google Calendar feed with ClientLogin authentication.

$username = 'example@gmail.com';
$password = 'password';

$service = new Google_Calendar;
if (!$service->requestClientLogin($username, $password)) {
  exit($service->getResponseBody());
}
if (!$service->requestFeed()) {
  exit($service->getResponseBody());
}
header('Content-Type:application/xml;charset=UTF-8');
echo $service->getResponseBody();

Create an Instance of the Class

Here is a code to create an instance of Google_GData class to work with Google Calendar Data API for example. The first parameter of the constructor is the service name used for the ClientLogin authentication and the second is the scope URL for the AuthSub. The setFeedUrl method sets the default URL for requesting a feed and inserting an entry.

$service = new Google_GData('cl', 'http://www.google.com/calendar/feeds/');
$service->setFeedUrl('http://www.google.com/calendar/feeds/default/private/full');

The above code can be simplified as following when use the extended Google_Calendar class instead.

$service = new Google_Calendar;

Account Authentication

Most requests to the GData APIs require authentication. To be authenticated, the client application is sending a temporary character string called ‘token’ instead of actual username and password. The token is issued via an account authentication API. There are two different APIs - ClientLogin and AuthSub. You may run test.php to see the key difference of these two APIs.

ClientLogin

Here is an example to acquire a ClientLogin token.

$service = new Google_Calendar;
if (!$service->requestClientLogin('example@gmail.com', 'password')) {
  exit($service->getResponseBody());
}
echo "ClientLogin token is $service->token";

The requestClientLogin method returns TRUE if succeeded and returns FALSE if failed. The token property and the authType property are set if succeeded. You may refer keyValuePairs hashed property to look into the response body in either case. Also you may use getResponseCode, getResponseHeader and getResponseBody to have the complete response of the last request.

The ClientLogin can be full-automated and potentially has a risk of bots attack. If the Google suspects that the request is an illegal intrusion, it may respond a Captcha challenge which requires a human interaction.
Here is an example to handle this response. This will show the user the Captcha image and an input field for the answer to the Captcha. When the user submits the answer, the application will call requestClientLogin again with the Captcha token (in the following example, the value of the ‘captcha_token’ field) and the answer as the third and forth parameter of the method.

if (!$service->requestClientLogin('example@gmail.com', 'password')) {
  if (isset($service->keyValuePairs['error'])
    and $service->keyValuePairs['error'] == 'CaptchaRequired'
    and isset($service->keyValuePairs['captchaurl'])
    and isset($service->keyValuePairs['captchatoken'])) {
    $captcha_url = $service->keyValuePairs['captchaurl'];
    if (0 !== strpos('http', $captcha_url)) {
      $captcha_url = "https://www.google.com/accounts/$captcha_url";
    }
    $captcha_token = $service->keyValuePairs['captchatoken'];
    echo <<<HTML
......
<p>Type the characters you see in the picture below.</p>

<img src="$captcha_url" width="200" height="70" alt="Visual verification" />
<input type="hidden" name="captcha_token" value="$captcha_token" />
<input type="text" name="captcha_answer" value="" />
......
HTML;
  }
}

AuthSub

To work with the AuthSub, you need first to invite a user to the Access Request page of the Google Accounts website.

<p>Please click the link below to proceed to the Google Accounts website,
and grant www.abcd.com to access your Google Calendar.<br />
www.abcd.com will not have access to your password or any personal information.</p>

<p><a href="<?php
  $service = new Google_Calendar;
  echo $service->getAuthSubRequestUrl('http://www.abcd.com/gcal/auth.php')
?>">Access Request at Google Accounts website</a></p>

When the user clicks the ‘Grant Access’ button on the page, it will redirect to the URL specified as the first parameter of the getAuthSubRequestUrl method above, with an additional token parameter in the query string. The value of this parameter is a one-time/single-use token.
The web application that handles this response may have following code to exchange the single-use token with a multi-use session token.

$service = new Google_Calendar;
if (!$service->requestAuthSubSessionToken($_GET['token'])) {
  exit($service->getResponseBody());
}
echo "AuthSub session token is $service->token";

The AuthSub does not allow more than ten valid tokens per user, per web application to be outstanding at any one time. So you may need to revoke the existing token before requesting another.
The requestAuthSubRevokeToken method is to revoke a valid AuthSub token. To get to know if the token is valid, use requestAuthSubTokenInfo method.

if ($service->requestAuthSubTokenInfo($token)) {
  $service->requestAuthSubRevokeToken($token);
  echo("Token $token has been revoked and is no longer valid.");
}

Assign Stored Token

You may store the acquired multi-use token somewhere (e.g. in PHP session or in web browser's cookie) for reuse in later sessions. The setToken method assigns the token value to the class instance. In the following example, the token is expected to be stored in the PHP session. The second parameter of the method is the name of the authentication API and the value shall be either ‘clientlogin’ or ‘authsub’.

session_start();
$service = new Google_Calendar;
if (isset($_SESSION['token'])) {
  $service->setToken($_SESSION['token'], 'authsub');
}

Please note that token is unique to each service API. If your application will communicate with multiple service APIs, you may need to acquire tokens of each service API.

Request a Feed

The following code will display the Atom 1.0 format Google Calendar GData feed with default criteria.
In this example, the token is expected to be acquired already via AuthSub and stored in the PHP session.

session_start();
$service = new Google_Calendar;
$service->setToken($_SESSION['token'], 'authsub');

if (!$service->requestFeed()) {
  exit($service->getResponseBody());
}
header('Content-Type:application/xml;charset=UTF-8');
echo $service->getResponseBody();

Set Search Criteria

To have a set of entries that match specified criteria, set an array that contains query parameters as the first parameter of the requestFeed method. The following example will show the first ten entries that contain the exact phrase ‘Elizabeth Bennet’ and the word ‘Darcy’ but do not contain the word ‘Austen’, in the order of the event start datetime.

$queries = array(
  'q' => '"Elizabeth Bennet" Darcy -Austen',
  'max-results' => 10,
  'orderby' => 'starttime',
  'start-min' => date('Y-m-d\TH:i:s+09:00', time())
);
$service->requestFeed($queries);

See ‘Queries’ section of the Google Data APIs Protocol document for GData common query parameters. And see the document of each service API for the service specific parameters.

Some parameters such as category or entry ID shall be embedded in the feed URL. In this case, you need to set the feed URL as the second parameter of the requestFeed method, or use setFeedUrl method before calling the requestFeed.

$queries = array();
$feed_url = 'http://www.google.com/calendar/feeds/default/private/full/abcd';
$service->requestFeed($queries, $feed_url);

This technique is also applied if you need to request a feed of non-default calendar or to change the visibility or the projection value of the calendar feed URL.

Set Additional Headers

Some service APIs require additional HTTP headers to be requested. For example, Google Base Data API requires X-Google-Key header with the value of ‘key=API_key’ (API_key is the API key issued when you sign up for an API key).
In this case, use setAdditionalHeader method to set the necessary headers before calling the methods that will access to the API.

$service = new Google_GData(NULL, 'http://www.google.com/base/feeds/items');
$service->setFeedUrl('http://www.google.com/base/feeds/items');
$service->setAdditionalHeader('X-Google-Key', 'key=API_key');

The gbase_demo_alt.php is the sample application to access the Google Base Data API.

Parse Feed

The class itself does not offer a way to either parse or create the feed. You may use various XML parsers such as expat, SimpleXML or DOM/DOM XML. You may even use regular expressions to get necessary part of the feed.

Insert, Update or Delete an Entry

To insert an entry, use the insert method. This method requires Atom 1.0 format GData feed data as the first parameter. No method to create the feed is provided in the class. Do it in your own way.
In this example, the token is expected to be acquired already via AuthSub and stored in the PHP session.

session_start();
$service = new Google_Calendar;
$service->setToken($_SESSION['token'], 'authsub');

$entry = <<<GDATA
<entry
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:gd="http://schemas.google.com/g/2005">
  <category
    scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/g/2005#event">
  </category>
  <title type="text">Tennis with Beth</title>
  <content type="text">Meet for a quick lesson.</content>
  <gd:where valueString="Rolling Lawn Courts">
  </gd:where>
  <gd:when
    startTime="2006-10-07T15:00:00+09:00"
    endTime="2006-10-07T17:00:00+09:00">
  </gd:when>
</entry>
GDATA;

if (!$service->insert($entry)) {
  exit($service->getResponseBody());
}
echo 'Event inserted.';

The update method is to update an existing entry with two parameters - GData feed data and the edit URL. The edit URL is the HREF value of the LINK REL="EDIT" element of the target entry.
The following example changes the start and end time of the existing entry of Google Calendar.

$entry = <<<GDATA
<entry
    xmlns="http://www.w3.org/2005/Atom"
    xmlns:gd="http://schemas.google.com/g/2005">
  <category
    scheme="http://schemas.google.com/g/2005#kind"
    term="http://schemas.google.com/g/2005#event">
  </category>
  <gd:when
    startTime="2006-10-07T14:00:00+09:00"
    endTime="2006-10-07T18:00:00+09:00">
  </gd:when>
</entry>
GDATA;

$edit_url = 'http://www.google.com/calendar/feeds/default/private/full/abcd/1234';

if (!$service->update($entry, $edit_url)) {
  exit($service->getResponseBody());
}
echo 'Event updated.';

The edit URL is also required to delete an entry as the parameter of the delete method.

$edit_url = 'http://www.google.com/calendar/feeds/default/private/full/abcd/1234';

if (!$service->delete($edit_url)) {
  exit($service->getResponseBody());
}
echo 'Event deleted.';

Note: If a firewall or something disallows HTTP DELETE method fo you, you should modify GData.php to perform delete. See the comment in the file.

The GData APIs offer batch processing to execute multiple operations in one request. See Batch Processing with Google Data APIs for details. The gbase_demo_alt.php has an example of the batch.

Request a Calendar List Feed

To get a list of calendars of the user, use requestFeedList of Google_Calendar extended class.

session_start();
$service = new Google_Calendar;
$service->setToken($_SESSION['token'], 'authsub');

if (!$service->requestFeedList()) {
  exit($service->getResponseBody());
}
header('Content-Type:application/xml;charset=UTF-8');
echo $service->getResponseBody();

This is very similar to requesting a calendar feed, but the responded GData feed contains a set of the calendar list associated with the user.


Author: http://www.rcdtokyo.com/ucb/

日本語 document is also available online.