[MANUAL] English:
[zend.git] / documentation / manual / en / module_specs / Zend_Gdata_Photos.xml
blobc9b69e183c49f989d7457ba9588bb2a819781549
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.gdata.photos">
4     <title>Using Picasa Web Albums</title>
6     <para>
7         Picasa Web Albums is a service which allows users to maintain albums of
8         their own pictures, and browse the albums and pictures of others.
9         The <acronym>API</acronym> offers a programmatic interface to this service, allowing
10         users to add to, update, and remove from their albums, as well as
11         providing the ability to tag and comment on photos.
12     </para>
14     <para>
15         Access to public albums and photos is not restricted by account,
16         however, a user must be logged in for non-read-only access.
17     </para>
19     <para>
20         For more information on the <acronym>API</acronym>, including
21         instructions for enabling <acronym>API</acronym> access, refer to the <ulink
22         url="http://code.google.com/apis/picasaweb/overview.html">Picasa
23         Web Albums Data <acronym>API</acronym> Overview</ulink>.
24     </para>
26     <note>
27         <title>Authentication</title>
29         <para>
30             The <acronym>API</acronym> provides authentication via AuthSub (recommended)
31             and ClientAuth. <acronym>HTTP</acronym> connections must be authenticated for write
32             support, but non-authenticated connections have read-only access.
33         </para>
34     </note>
36     <sect2 id="zend.gdata.photos.connecting">
37         <title>Connecting To The Service</title>
39         <para>
40             The Picasa Web Albums <acronym>API</acronym>, like all GData <acronym>API</acronym>s, is
41             based off of the Atom Publishing Protocol (APP), an <acronym>XML</acronym> based format
42             for managing web-based resources. Traffic between a client and the servers occurs over
43             <acronym>HTTP</acronym> and allows for both authenticated and unauthenticated
44             connections.
45         </para>
47         <para>
48             Before any transactions can occur, this connection needs to be made. Creating a
49             connection to the Picasa servers involves two steps: creating an <acronym>HTTP</acronym>
50             client and binding a <classname>Zend_Gdata_Photos</classname>
51             service instance to that client.
52         </para>
54         <sect3 id="zend.gdata.photos.connecting.authentication">
55             <title>Authentication</title>
57             <para>
58                 The Google Picasa <acronym>API</acronym> allows access to both public and private
59                 photo feeds. Public feeds do not require authentication, but are read-only and offer
60                 reduced functionality. Private feeds offers the most complete functionality but
61                 requires an authenticated connection to the Picasa servers. There are three
62                 authentication schemes that are supported by Google Picasa :
63             </para>
65             <itemizedlist>
66                 <listitem>
67                     <para>
68                         <firstterm>ClientAuth</firstterm>
69                         provides direct username/password authentication to the
70                         Picasa servers. Since this scheme requires that users
71                         provide your application with their password, this
72                         authentication is only recommended when other
73                         authentication schemes are insufficient.
74                     </para>
75                 </listitem>
77                 <listitem>
78                     <para>
79                         <firstterm>AuthSub</firstterm>
80                         allows authentication to the Picasa servers via a
81                         Google proxy server. This provides the same level of
82                         convenience as ClientAuth but without the security
83                         risk, making this an ideal choice for web-based
84                         applications.
85                     </para>
86                 </listitem>
87             </itemizedlist>
89             <para>
90                 The
91                 <classname>Zend_Gdata</classname>
92                 library provides support for both authentication schemes.
93                 The rest of this chapter will assume that you are familiar the
94                 authentication schemes available and how to create an
95                 appropriate authenticated connection. For more information,
96                 please see section the
97                 <link linkend="zend.gdata.introduction.authentication">Authentication section</link>
98                 of this manual or the <ulink
99                     url="http://code.google.com/apis/gdata/auth.html">Authentication Overview in the
100                     Google Data <acronym>API</acronym> Developer's Guide</ulink>.
101             </para>
102         </sect3>
104         <sect3 id="zend.gdata.photos.connecting.service">
105             <title>Creating A Service Instance</title>
107             <para>
108                 In order to interact with the servers, this library provides the
109                 <classname>Zend_Gdata_Photos</classname> service class. This class provides a common
110                 interface to the Google Data and Atom Publishing Protocol models and assists in
111                 marshaling requests to and from the servers.
112             </para>
114             <para>
115                 Once deciding on an authentication scheme, the next step is to create an instance of
116                 <classname>Zend_Gdata_Photos</classname>. The class constructor takes an instance of
117                 <classname>Zend_Http_Client</classname> as a single argument. This provides an
118                 interface for AuthSub and ClientAuth authentication, as both of these require
119                 creation of a special authenticated <acronym>HTTP</acronym> client. If no arguments
120                 are provided, an unauthenticated instance of <classname>Zend_Http_Client</classname>
121                 will be automatically created.
122             </para>
124             <para>
125                 The example below shows how to create a service class using ClientAuth
126                 authentication:
127             </para>
129             <programlisting language="php"><![CDATA[
130 // Parameters for ClientAuth authentication
131 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
132 $user = "sample.user@gmail.com";
133 $pass = "pa$$w0rd";
135 // Create an authenticated HTTP client
136 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
138 // Create an instance of the service
139 $service = new Zend_Gdata_Photos($client);
140 ]]></programlisting>
142             <para>
143                 A service instance using AuthSub can be created in a similar, though slightly more
144                 lengthy fashion:
145             </para>
147             <programlisting language="php"><![CDATA[
148 session_start();
151  * Returns the full URL of the current page, based upon env variables
153  * Env variables used:
154  * $_SERVER['HTTPS'] = (on|off|)
155  * $_SERVER['HTTP_HOST'] = value of the Host: header
156  * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443)
157  * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request
159  * @return string Current URL
160  */
161 function getCurrentUrl()
163     global $_SERVER;
165     /**
166      * Filter php_self to avoid a security vulnerability.
167      */
168     $php_request_uri = htmlentities(substr($_SERVER['REQUEST_URI'], 0,
169     strcspn($_SERVER['REQUEST_URI'], "\n\r")), ENT_QUOTES);
171     if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
172         $protocol = 'https://';
173     } else {
174         $protocol = 'http://';
175     }
176     $host = $_SERVER['HTTP_HOST'];
177     if ($_SERVER['SERVER_PORT'] != '' &&
178         (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
179         ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
180             $port = ':' . $_SERVER['SERVER_PORT'];
181     } else {
182         $port = '';
183     }
184     return $protocol . $host . $port . $php_request_uri;
188  * Returns the AuthSub URL which the user must visit to authenticate requests
189  * from this application.
191  * Uses getCurrentUrl() to get the next URL which the user will be redirected
192  * to after successfully authenticating with the Google service.
194  * @return string AuthSub URL
195  */
196 function getAuthSubUrl()
198     $next = getCurrentUrl();
199     $scope = 'http://picasaweb.google.com/data';
200     $secure = false;
201     $session = true;
202     return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure,
203         $session);
207  * Returns a HTTP client object with the appropriate headers for communicating
208  * with Google using AuthSub authentication.
210  * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after
211  * it is obtained. The single use token supplied in the URL when redirected
212  * after the user succesfully authenticated to Google is retrieved from the
213  * $_GET['token'] variable.
215  * @return Zend_Http_Client
216  */
217 function getAuthSubHttpClient()
219     global $_SESSION, $_GET;
220     if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) {
221         $_SESSION['sessionToken'] =
222             Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
223     }
224     $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
225     return $client;
229  * Create a new instance of the service, redirecting the user
230  * to the AuthSub server if necessary.
231  */
232 $service = new Zend_Gdata_Photos(getAuthSubHttpClient());
233 ]]></programlisting>
235             <para>
236                 Finally, an unauthenticated server can be created for use with public feeds:
237             </para>
239             <programlisting language="php"><![CDATA[
240 // Create an instance of the service using an unauthenticated HTTP client
241 $service = new Zend_Gdata_Photos();
242 ]]></programlisting>
243         </sect3>
244     </sect2>
246     <sect2 id="zend.gdata.photos.queries">
247         <title>Understanding and Constructing Queries</title>
249         <para>
250             The primary method to request data from the service is by constructing a query. There
251             are query classes for each of the following types:
252         </para>
254         <itemizedlist>
255             <listitem>
256                 <para>
257                     <firstterm>User</firstterm> is used to specify the user whose data is being
258                     searched for, and is specified as a username. if no user is provided, "default"
259                     will be used instead to indicate the currently authenticated user (if
260                     authenticated).
261                 </para>
262             </listitem>
264             <listitem>
265                 <para>
266                     <firstterm>Album</firstterm> is used to specify the album which is being
267                     searched for, and is specified as either an id, or an album name.
268                 </para>
269             </listitem>
271             <listitem>
272                 <para>
273                     <firstterm>Photo</firstterm> is used to specify the photo which is being
274                     searched for, and is specified as an id.
275                 </para>
276             </listitem>
277         </itemizedlist>
279         <para>A new <code>UserQuery</code> can be constructed as followed:</para>
281         <programlisting language="php"><![CDATA[
282 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
283 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
284 $service = new Zend_Gdata_Photos($client);
286 $query = new Zend_Gdata_Photos_UserQuery();
287 $query->setUser("sample.user");
288 ]]></programlisting>
290         <para>
291             for each query, a number of parameters limiting the search can be requested, or
292             specified, with get(Parameter) and set(Parameter), respectively. They are as follows:
293         </para>
295         <itemizedlist>
296             <listitem>
297                 <para>
298                     <firstterm>Projection</firstterm> sets the format of the data returned in the
299                     feed, as either "api" or "base". Normally, "api" is desired. The default is
300                     "api".
301                 </para>
302             </listitem>
304             <listitem>
305                 <para>
306                     <firstterm>Type</firstterm> sets the type of element to be returned, as either
307                     "feed" or "entry". The default is "feed".
308                 </para>
309             </listitem>
311             <listitem>
312                 <para>
313                     <firstterm>Access</firstterm> sets the visibility of items to be returned, as
314                     "all", "public", or "private". The default is "all". Non-public elements will
315                     only be returned if the query is searching for the authenticated user.
316                 </para>
317             </listitem>
319             <listitem>
320                 <para>
321                     <firstterm>Tag</firstterm> sets a tag filter for returned items. When a tag is
322                     set, only items tagged with this value will return.
323                 </para>
324             </listitem>
326             <listitem>
327                 <para>
328                     <firstterm>Kind</firstterm> sets the kind of elements to return. When kind is
329                     specified, only entries that match this value will be returned.
330                 </para>
331             </listitem>
333             <listitem>
334                 <para>
335                     <firstterm>ImgMax</firstterm> sets the maximum image size for entries returned.
336                     Only image entries smaller than this value will be returned.
337                 </para>
338             </listitem>
340             <listitem>
341                 <para>
342                     <firstterm>Thumbsize</firstterm> sets the thumbsize of entries that are
343                     returned. Any retrieved entry will have a thumbsize equal to this value.
344                 </para>
345             </listitem>
347             <listitem>
348                 <para>
349                     <firstterm>User</firstterm> sets the user whose data is being searched for. The
350                     default is "default".
351                 </para>
352             </listitem>
354             <listitem>
355                 <para>
356                     <firstterm>AlbumId</firstterm> sets the id of the album being searched for. This
357                     element only applies to album and photo queries. In the case of photo queries,
358                     this specifies the album that contains the requested photo. The album id is
359                     mutually exclusive with the album's name. Setting one unsets the other.
360                 </para>
361             </listitem>
363             <listitem>
364                 <para>
365                     <firstterm>AlbumName</firstterm> sets the name of the album being searched for.
366                     This element only applies to the album and photo queries. In the case of photo
367                     queries, this specifies the album that contains the requested photo. The album
368                     name is mutually exclusive with the album's id. Setting one unsets the other.
369                 </para>
370             </listitem>
372             <listitem>
373                 <para>
374                     <firstterm>PhotoId</firstterm> sets the id of the photo being searched for. This
375                     element only applies to photo queries.
376                 </para>
377             </listitem>
378         </itemizedlist>
379     </sect2>
381     <sect2 id="zend.gdata.photos.retrieval">
382         <title>Retrieving Feeds And Entries</title>
384         <para>
385             The service has functions to retrieve a feed, or individual entries, for users, albums,
386             and individual photos.
387         </para>
389         <sect3 id="zend.gdata.photos.user_retrieval">
390             <title>Retrieving A User</title>
392             <para>
393                 The service supports retrieving a user feed and list of the user's content. If the
394                 requested user is also the authenticated user, entries marked as
395                 "<code>hidden</code>" will also be returned.
396             </para>
398             <para>
399                 The user feed can be accessed by passing the username to the
400                 <code>getUserFeed</code> method:
401             </para>
403             <programlisting language="php"><![CDATA[
404 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
405 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
406 $service = new Zend_Gdata_Photos($client);
408 try {
409     $userFeed = $service->getUserFeed("sample.user");
410 } catch (Zend_Gdata_App_Exception $e) {
411     echo "Error: " . $e->getMessage();
413 ]]></programlisting>
415             <para>Or, the feed can be accessed by constructing a query, first:</para>
417             <programlisting language="php"><![CDATA[
418 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
419 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
420 $service = new Zend_Gdata_Photos($client);
422 $query = new Zend_Gdata_Photos_UserQuery();
423 $query->setUser("sample.user");
425 try {
426     $userFeed = $service->getUserFeed(null, $query);
427 } catch (Zend_Gdata_App_Exception $e) {
428     echo "Error: " . $e->getMessage();
430 ]]></programlisting>
432             <para>
433                 Constructing a query also provides the ability to request a user entry object:
434             </para>
436             <programlisting language="php"><![CDATA[
437 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
438 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
439 $service = new Zend_Gdata_Photos($client);
441 $query = new Zend_Gdata_Photos_UserQuery();
442 $query->setUser("sample.user");
443 $query->setType("entry");
445 try {
446     $userEntry = $service->getUserEntry($query);
447 } catch (Zend_Gdata_App_Exception $e) {
448     echo "Error: " . $e->getMessage();
450 ]]></programlisting>
451         </sect3>
453         <sect3 id="zend.gdata.photos.album_retrieval">
454             <title>Retrieving An Album</title>
456             <para>
457                 The service supports retrieving an album feed and a list of the album's content.
458             </para>
460             <para>
461                 The album feed is accessed by constructing a query object and passing it to
462                 <code>getAlbumFeed</code>:
463             </para>
465             <programlisting language="php"><![CDATA[
466 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
467 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
468 $service = new Zend_Gdata_Photos($client);
470 $query = new Zend_Gdata_Photos_AlbumQuery();
471 $query->setUser("sample.user");
472 $query->setAlbumId("1");
474 try {
475     $albumFeed = $service->getAlbumFeed($query);
476 } catch (Zend_Gdata_App_Exception $e) {
477     echo "Error: " . $e->getMessage();
479 ]]></programlisting>
481             <para>
482                 Alternatively, the query object can be given an album name with
483                 <code>setAlbumName</code>. Setting the album name is mutually exclusive with setting
484                 the album id, and setting one will unset the other.
485             </para>
487             <para>
488                 Constructing a query also provides the ability to request an album entry object:
489             </para>
491             <programlisting language="php"><![CDATA[
492 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
493 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
494 $service = new Zend_Gdata_Photos($client);
496 $query = new Zend_Gdata_Photos_AlbumQuery();
497 $query->setUser("sample.user");
498 $query->setAlbumId("1");
499 $query->setType("entry");
501 try {
502     $albumEntry = $service->getAlbumEntry($query);
503 } catch (Zend_Gdata_App_Exception $e) {
504     echo "Error: " . $e->getMessage();
506 ]]></programlisting>
507         </sect3>
509         <sect3 id="zend.gdata.photos.photo_retrieval">
510             <title>Retrieving A Photo</title>
512             <para>
513                 The service supports retrieving a photo feed and a list of associated comments and
514                 tags.
515             </para>
517             <para>
518                 The photo feed is accessed by constructing a query object and passing it to
519                 <code>getPhotoFeed</code>:
520             </para>
522             <programlisting language="php"><![CDATA[
523 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
524 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
525 $service = new Zend_Gdata_Photos($client);
527 $query = new Zend_Gdata_Photos_PhotoQuery();
528 $query->setUser("sample.user");
529 $query->setAlbumId("1");
530 $query->setPhotoId("100");
532 try {
533     $photoFeed = $service->getPhotoFeed($query);
534 } catch (Zend_Gdata_App_Exception $e) {
535     echo "Error: " . $e->getMessage();
537 ]]></programlisting>
539             <para>
540                 Constructing a query also provides the ability to request a photo entry object:
541             </para>
543             <programlisting language="php"><![CDATA[
544 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
545 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
546 $service = new Zend_Gdata_Photos($client);
548 $query = new Zend_Gdata_Photos_PhotoQuery();
549 $query->setUser("sample.user");
550 $query->setAlbumId("1");
551 $query->setPhotoId("100");
552 $query->setType("entry");
554 try {
555     $photoEntry = $service->getPhotoEntry($query);
556 } catch (Zend_Gdata_App_Exception $e) {
557     echo "Error: " . $e->getMessage();
559 ]]></programlisting>
560         </sect3>
562         <sect3 id="zend.gdata.photos.comment_retrieval">
563             <title>Retrieving A Comment</title>
565             <para>
566                 The service supports retrieving comments from a feed of a different type. By setting
567                 a query to return a kind of "comment", a feed request can return comments associated
568                 with a specific user, album, or photo.
569             </para>
571             <para>
572                 Performing an action on each of the comments on a given photo can be accomplished
573                 as follows:
574             </para>
576             <programlisting language="php"><![CDATA[
577 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
578 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
579 $service = new Zend_Gdata_Photos($client);
581 $query = new Zend_Gdata_Photos_PhotoQuery();
582 $query->setUser("sample.user");
583 $query->setAlbumId("1");
584 $query->setPhotoId("100");
585 $query->setKind("comment");
587 try {
588     $photoFeed = $service->getPhotoFeed($query);
590     foreach ($photoFeed as $entry) {
591         if ($entry instanceof Zend_Gdata_Photos_CommentEntry) {
592             // Do something with the comment
593         }
594     }
595 } catch (Zend_Gdata_App_Exception $e) {
596     echo "Error: " . $e->getMessage();
598 ]]></programlisting>
599         </sect3>
601         <sect3 id="zend.gdata.photos.tag_retrieval">
602             <title>Retrieving A Tag</title>
604             <para>
605                 The service supports retrieving tags from a feed of a different type. By setting a
606                 query to return a kind of "tag", a feed request can return tags associated with a
607                 specific photo.
608             </para>
610             <para>
611                 Performing an action on each of the tags on a given photo can be accomplished as
612                 follows:
613             </para>
615             <programlisting language="php"><![CDATA[
616 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
617 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
618 $service = new Zend_Gdata_Photos($client);
620 $query = new Zend_Gdata_Photos_PhotoQuery();
621 $query->setUser("sample.user");
622 $query->setAlbumId("1");
623 $query->setPhotoId("100");
624 $query->setKind("tag");
626 try {
627     $photoFeed = $service->getPhotoFeed($query);
629     foreach ($photoFeed as $entry) {
630         if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
631             // Do something with the tag
632         }
633     }
634 } catch (Zend_Gdata_App_Exception $e) {
635     echo "Error: " . $e->getMessage();
637 ]]></programlisting>
638         </sect3>
639     </sect2>
641     <sect2 id="zend.gdata.photos.creation">
642         <title>Creating Entries</title>
644         <para>The service has functions to create albums, photos, comments, and tags.</para>
646         <sect3 id="zend.gdata.photos.album_creation">
647             <title>Creating An Album</title>
649             <para>The service supports creating a new album for an authenticated user:</para>
651             <programlisting language="php"><![CDATA[
652 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
653 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
654 $service = new Zend_Gdata_Photos($client);
656 $entry = new Zend_Gdata_Photos_AlbumEntry();
657 $entry->setTitle($service->newTitle("test album"));
659 $service->insertAlbumEntry($entry);
660 ]]></programlisting>
661         </sect3>
663         <sect3 id="zend.gdata.photos.photo_creation">
664             <title>Creating A Photo</title>
666             <para>The service supports creating a new photo for an authenticated user:</para>
668             <programlisting language="php"><![CDATA[
669 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
670 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
671 $service = new Zend_Gdata_Photos($client);
673 // $photo is the name of a file uploaded via an HTML form
675 $fd = $service->newMediaFileSource($photo["tmp_name"]);
676 $fd->setContentType($photo["type"]);
678 $entry = new Zend_Gdata_Photos_PhotoEntry();
679 $entry->setMediaSource($fd);
680 $entry->setTitle($service->newTitle($photo["name"]));
682 $albumQuery = new Zend_Gdata_Photos_AlbumQuery;
683 $albumQuery->setUser("sample.user");
684 $albumQuery->setAlbumId("1");
686 $albumEntry = $service->getAlbumEntry($albumQuery);
688 $service->insertPhotoEntry($entry, $albumEntry);
689 ]]></programlisting>
690         </sect3>
692         <sect3 id="zend.gdata.photos.comment_creation">
693             <title>Creating A Comment</title>
695             <para>The service supports creating a new comment for a photo:</para>
697             <programlisting language="php"><![CDATA[
698 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
699 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
700 $service = new Zend_Gdata_Photos($client);
702 $entry = new Zend_Gdata_Photos_CommentEntry();
703 $entry->setTitle($service->newTitle("comment"));
704 $entry->setContent($service->newContent("comment"));
706 $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
707 $photoQuery->setUser("sample.user");
708 $photoQuery->setAlbumId("1");
709 $photoQuery->setPhotoId("100");
710 $photoQuery->setType('entry');
712 $photoEntry = $service->getPhotoEntry($photoQuery);
714 $service->insertCommentEntry($entry, $photoEntry);
715 ]]></programlisting>
716         </sect3>
718         <sect3 id="zend.gdata.photos.tag_creation">
719             <title>Creating A Tag</title>
721             <para>The service supports creating a new tag for a photo:</para>
723             <programlisting language="php"><![CDATA[
724 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
725 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
726 $service = new Zend_Gdata_Photos($client);
728 $entry = new Zend_Gdata_Photos_TagEntry();
729 $entry->setTitle($service->newTitle("tag"));
731 $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
732 $photoQuery->setUser("sample.user");
733 $photoQuery->setAlbumId("1");
734 $photoQuery->setPhotoId("100");
735 $photoQuery->setType('entry');
737 $photoEntry = $service->getPhotoEntry($photoQuery);
739 $service->insertTagEntry($entry, $photoEntry);
740 ]]></programlisting>
741         </sect3>
742     </sect2>
744     <sect2 id="zend.gdata.photos.deletion">
745         <title>Deleting Entries</title>
747         <para>The service has functions to delete albums, photos, comments, and tags.</para>
749         <sect3 id="zend.gdata.photos.album_deletion">
750             <title>Deleting An Album</title>
752             <para>The service supports deleting an album for an authenticated user:</para>
754             <programlisting language="php"><![CDATA[
755 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
756 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
757 $service = new Zend_Gdata_Photos($client);
759 $albumQuery = new Zend_Gdata_Photos_AlbumQuery;
760 $albumQuery->setUser("sample.user");
761 $albumQuery->setAlbumId("1");
762 $albumQuery->setType('entry');
764 $entry = $service->getAlbumEntry($albumQuery);
766 $service->deleteAlbumEntry($entry, true);
767 ]]></programlisting>
768         </sect3>
770         <sect3 id="zend.gdata.photos.photo_deletion">
771             <title>Deleting A Photo</title>
773             <para>The service supports deleting a photo for an authenticated user:</para>
775             <programlisting language="php"><![CDATA[
776 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
777 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
778 $service = new Zend_Gdata_Photos($client);
780 $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
781 $photoQuery->setUser("sample.user");
782 $photoQuery->setAlbumId("1");
783 $photoQuery->setPhotoId("100");
784 $photoQuery->setType('entry');
786 $entry = $service->getPhotoEntry($photoQuery);
788 $service->deletePhotoEntry($entry, true);
789 ]]></programlisting>
790         </sect3>
792         <sect3 id="zend.gdata.photos.comment_deletion">
793             <title>Deleting A Comment</title>
795             <para>The service supports deleting a comment for an authenticated user:</para>
797             <programlisting language="php"><![CDATA[
798 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
799 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
800 $service = new Zend_Gdata_Photos($client);
802 $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
803 $photoQuery->setUser("sample.user");
804 $photoQuery->setAlbumId("1");
805 $photoQuery->setPhotoId("100");
806 $photoQuery->setType('entry');
808 $path = $photoQuery->getQueryUrl() . '/commentid/' . "1000";
810 $entry = $service->getCommentEntry($path);
812 $service->deleteCommentEntry($entry, true);
813 ]]></programlisting>
814         </sect3>
816         <sect3 id="zend.gdata.photos.tag_deletion">
817             <title>Deleting A Tag</title>
819             <para>The service supports deleting a tag for an authenticated user:</para>
821             <programlisting language="php"><![CDATA[
822 $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
823 $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
824 $service = new Zend_Gdata_Photos($client);
826 $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
827 $photoQuery->setUser("sample.user");
828 $photoQuery->setAlbumId("1");
829 $photoQuery->setPhotoId("100");
830 $photoQuery->setKind("tag");
831 $query = $photoQuery->getQueryUrl();
833 $photoFeed = $service->getPhotoFeed($query);
835 foreach ($photoFeed as $entry) {
836     if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
837         if ($entry->getContent() == $tagContent) {
838             $tagEntry = $entry;
839         }
840     }
843 $service->deleteTagEntry($tagEntry, true);
844 ]]></programlisting>
845         </sect3>
847         <sect3 id="zend.gdata.photos.optimistic_concurrenty">
848             <title>Optimistic Concurrency (Notes On Deletion)</title>
850             <para>
851                 GData feeds, including those of the Picasa Web Albums service, implement optimistic
852                 concurrency, a versioning system that prevents users from overwriting changes,
853                 inadvertently. When deleting a entry through the service class, if the entry has
854                 been modified since it was last fetched, an exception will be thrown, unless
855                 explicitly set otherwise (in which case the deletion is retried on the updated
856                 entry).
857             </para>
859             <para>
860                 An example of how to handle versioning during a deletion is shown by
861                 <code>deleteAlbumEntry</code>:
862             </para>
864             <programlisting language="php"><![CDATA[
865 // $album is the albumEntry to be deleted
866 try {
867     $this->delete($album);
868 } catch (Zend_Gdata_App_HttpException $e) {
869     if ($e->getMessage()->getStatus() === 409) {
870         $entry =
871             new Zend_Gdata_Photos_AlbumEntry($e->getMessage()->getBody());
872         $this->delete($entry->getLink('edit')->href);
873     } else {
874         throw $e;
875     }
877 ]]></programlisting>
878         </sect3>
879     </sect2>
880 </sect1>