TigerZF
🌐Español

37.10. Uso de Picasa Web Albums

Picasa Web Albums es un servicio que permite a los usuarios mantener álbumes de sus propias imágenes, y explorar los álbumes y las imágenes de otros. La API ofrece una interfaz programática a este servicio, que permite a los usuarios añadir, actualizar y eliminar elementos de sus álbumes, además de proporcionar la posibilidad de etiquetar y comentar fotografías.

El acceso a álbumes y fotografías públicas no está restringido por cuenta; sin embargo, el usuario debe haber iniciado sesión para el acceso que no sea de solo lectura.

Para más información sobre la API, incluidas las instrucciones para habilitar el acceso a la API, consulte el resumen de la API de datos de Picasa Web Albums.

[Note] Autenticación

La API proporciona autenticación mediante AuthSub (recomendado) y ClientAuth. Las conexiones HTTP deben autenticarse para tener soporte de escritura, pero las conexiones no autenticadas tienen acceso de solo lectura.

37.10.1. Conexión al servicio

La API de Picasa Web Albums, como todas las APIs de GData, está basada en el Atom Publishing Protocol (APP), un formato basado en XML para gestionar recursos basados en la web. El tráfico entre un cliente y los servidores se produce mediante HTTP y permite tanto conexiones autenticadas como no autenticadas.

Antes de que pueda producirse cualquier transacción, es necesario establecer esta conexión. Crear una conexión a los servidores de Picasa implica dos pasos: crear un cliente HTTP y vincular una instancia del servicio Zend_Gdata_Photos a dicho cliente.

37.10.1.1. Autenticación

La API de Google Picasa permite el acceso tanto a feeds de fotos públicos como privados. Los feeds públicos no requieren autenticación, pero son de solo lectura y ofrecen una funcionalidad reducida. Los feeds privados ofrecen la funcionalidad más completa, pero requieren una conexión autenticada a los servidores de Picasa. Hay tres esquemas de autenticación admitidos por Google Picasa:

  • ClientAuth proporciona autenticación directa mediante nombre de usuario/contraseña con los servidores de Picasa. Dado que este esquema requiere que los usuarios proporcionen su contraseña a su aplicación, esta autenticación solo se recomienda cuando otros esquemas de autenticación resultan insuficientes.

  • AuthSub permite la autenticación con los servidores de Picasa a través de un servidor proxy de Google. Esto proporciona el mismo nivel de conveniencia que ClientAuth pero sin el riesgo de seguridad, lo que lo convierte en una opción ideal para aplicaciones basadas en web.

La biblioteca Zend_Gdata proporciona soporte para ambos esquemas de autenticación. El resto de este capítulo asumirá que está familiarizado con los esquemas de autenticación disponibles y con cómo crear una conexión autenticada apropiada. Para más información, consulte la sección de Autenticación de este manual o el resumen de autenticación en la Guía del desarrollador de la API de Google Data.

37.10.1.2. Creación de una instancia del servicio

Con el fin de interactuar con los servidores, esta biblioteca proporciona la clase de servicio Zend_Gdata_Photos. Esta clase proporciona una interfaz común a los modelos de Google Data y del Atom Publishing Protocol y ayuda a gestionar las peticiones hacia y desde los servidores.

Una vez decidido el esquema de autenticación, el siguiente paso es crear una instancia de Zend_Gdata_Photos. El constructor de la clase toma una instancia de Zend_Http_Client como único argumento. Esto proporciona una interfaz para la autenticación AuthSub y ClientAuth, ya que ambas requieren la creación de un cliente HTTP autenticado especial. Si no se proporciona ningún argumento, se creará automáticamente una instancia no autenticada de Zend_Http_Client.

El siguiente ejemplo muestra cómo crear una clase de servicio usando autenticación ClientAuth:

// Parameters for ClientAuth authentication
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "sample.user@gmail.com";
$pass = "pa$$w0rd";

// Create an authenticated HTTP client
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);

// Create an instance of the service
$service = new Zend_Gdata_Photos($client);

Se puede crear una instancia de servicio usando AuthSub de una forma similar, aunque ligeramente más extensa:

session_start();

/**
 * Returns the full URL of the current page, based upon env variables
 *
 * Env variables used:
 * $_SERVER['HTTPS'] = (on|off|)
 * $_SERVER['HTTP_HOST'] = value of the Host: header
 * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443)
 * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request
 *
 * @return string Current URL
 */
function getCurrentUrl()
{
    global $_SERVER;

    /**
     * Filter php_self to avoid a security vulnerability.
     */
    $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['SERVER_PORT'] != '' &&
        (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
        ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
            $port = ':' . $_SERVER['SERVER_PORT'];
    } else {
        $port = '';
    }
    return $protocol . $host . $port . $php_request_uri;
}

/**
 * Returns the AuthSub URL which the user must visit to authenticate requests
 * from this application.
 *
 * Uses getCurrentUrl() to get the next URL which the user will be redirected
 * to after successfully authenticating with the Google service.
 *
 * @return string AuthSub URL
 */
function getAuthSubUrl()
{
    $next = getCurrentUrl();
    $scope = 'http://picasaweb.google.com/data';
    $secure = false;
    $session = true;
    return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure,
        $session);
}

/**
 * Returns a HTTP client object with the appropriate headers for communicating
 * with Google using AuthSub authentication.
 *
 * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after
 * it is obtained. The single use token supplied in the URL when redirected
 * after the user succesfully authenticated to Google is retrieved from the
 * $_GET['token'] variable.
 *
 * @return Zend_Http_Client
 */
function getAuthSubHttpClient()
{
    global $_SESSION, $_GET;
    if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) {
        $_SESSION['sessionToken'] =
            Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
    }
    $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
    return $client;
}

/**
 * Create a new instance of the service, redirecting the user
 * to the AuthSub server if necessary.
 */
$service = new Zend_Gdata_Photos(getAuthSubHttpClient());

Finalmente, se puede crear un servidor no autenticado para su uso con feeds públicos:

// Create an instance of the service using an unauthenticated HTTP client
$service = new Zend_Gdata_Photos();

37.10.2. Comprensión y construcción de consultas

El método principal para solicitar datos al servicio es construir una consulta. Hay clases de consulta para cada uno de los siguientes tipos:

  • User se usa para especificar el usuario cuyos datos se están buscando, y se especifica como un nombre de usuario. Si no se proporciona ningún usuario, se usará "default" en su lugar para indicar al usuario autenticado actualmente (si está autenticado).

  • Album se usa para especificar el álbum que se está buscando, y se especifica como un id o como un nombre de álbum.

  • Photo se usa para especificar la fotografía que se está buscando, y se especifica como un id.

Una nueva UserQuery puede construirse de la siguiente manera:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_UserQuery();
$query->setUser("sample.user");

para cada consulta, se puede solicitar o especificar un número de parámetros que limitan la búsqueda, con get(Parámetro) y set(Parámetro), respectivamente. Son los siguientes:

  • Projection establece el formato de los datos devueltos en el feed, ya sea como "api" o "base". Normalmente se desea "api". El valor por defecto es "api".

  • Type establece el tipo de elemento a devolver, ya sea "feed" o "entry". El valor por defecto es "feed".

  • Access establece la visibilidad de los elementos a devolver, como "all", "public" o "private". El valor por defecto es "all". Los elementos no públicos solo se devolverán si la consulta está buscando al usuario autenticado.

  • Tag establece un filtro de etiquetas para los elementos devueltos. Cuando se establece una etiqueta, solo se devolverán los elementos etiquetados con ese valor.

  • Kind establece el tipo de elementos a devolver. Cuando se especifica kind, solo se devolverán las entradas que coincidan con este valor.

  • ImgMax establece el tamaño máximo de imagen para las entradas devueltas. Solo se devolverán las entradas de imagen más pequeñas que este valor.

  • Thumbsize establece el tamaño de miniatura de las entradas que se devuelven. Cualquier entrada recuperada tendrá un tamaño de miniatura igual a este valor.

  • User establece el usuario cuyos datos se están buscando. El valor por defecto es "default".

  • AlbumId establece el id del álbum que se está buscando. Este elemento solo se aplica a las consultas de álbum y de fotografía. En el caso de las consultas de fotografía, esto especifica el álbum que contiene la fotografía solicitada. El id del álbum es mutuamente excluyente con el nombre del álbum. Establecer uno anula el otro.

  • AlbumName establece el nombre del álbum que se está buscando. Este elemento solo se aplica a las consultas de álbum y de fotografía. En el caso de las consultas de fotografía, esto especifica el álbum que contiene la fotografía solicitada. El nombre del álbum es mutuamente excluyente con el id del álbum. Establecer uno anula el otro.

  • PhotoId establece el id de la fotografía que se está buscando. Este elemento solo se aplica a las consultas de fotografía.

37.10.3. Recuperación de feeds y entradas

El servicio dispone de funciones para recuperar un feed, o entradas individuales, para usuarios, álbumes y fotografías individuales.

37.10.3.1. Recuperación de un usuario

El servicio permite recuperar un feed de usuario y una lista del contenido del usuario. Si el usuario solicitado es también el usuario autenticado, también se devolverán las entradas marcadas como "ocultas".

Se puede acceder al feed de usuario pasando el nombre de usuario al método getUserFeed():

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

try {
    $userFeed = $service->getUserFeed("sample.user");
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

O bien, se puede acceder al feed construyendo primero una consulta:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_UserQuery();
$query->setUser("sample.user");

try {
    $userFeed = $service->getUserFeed(null, $query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

Construir una consulta también proporciona la posibilidad de solicitar un objeto de entrada de usuario:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_UserQuery();
$query->setUser("sample.user");
$query->setType("entry");

try {
    $userEntry = $service->getUserEntry($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

37.10.3.2. Recuperación de un álbum

El servicio permite recuperar un feed de álbum y una lista del contenido del álbum.

Se accede al feed de álbum construyendo un objeto de consulta y pasándolo a getAlbumFeed():

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_AlbumQuery();
$query->setUser("sample.user");
$query->setAlbumId("1");

try {
    $albumFeed = $service->getAlbumFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

Alternativamente, se le puede dar al objeto de consulta un nombre de álbum con setAlbumName(). Establecer el nombre del álbum es mutuamente excluyente con establecer el id del álbum, y establecer uno anulará el otro.

Construir una consulta también proporciona la posibilidad de solicitar un objeto de entrada de álbum:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_AlbumQuery();
$query->setUser("sample.user");
$query->setAlbumId("1");
$query->setType("entry");

try {
    $albumEntry = $service->getAlbumEntry($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

37.10.3.3. Recuperación de una fotografía

El servicio permite recuperar un feed de fotografía y una lista de los comentarios y etiquetas asociados.

Se accede al feed de fotografía construyendo un objeto de consulta y pasándolo a getPhotoFeed():

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_PhotoQuery();
$query->setUser("sample.user");
$query->setAlbumId("1");
$query->setPhotoId("100");

try {
    $photoFeed = $service->getPhotoFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

Construir una consulta también proporciona la posibilidad de solicitar un objeto de entrada de fotografía:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_PhotoQuery();
$query->setUser("sample.user");
$query->setAlbumId("1");
$query->setPhotoId("100");
$query->setType("entry");

try {
    $photoEntry = $service->getPhotoEntry($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

37.10.3.4. Recuperación de un comentario

El servicio permite recuperar comentarios de un feed de un tipo distinto. Estableciendo una consulta para devolver un kind de "comment", una petición de feed puede devolver comentarios asociados con un usuario, álbum o fotografía específicos.

Realizar una acción sobre cada uno de los comentarios de una fotografía dada puede lograrse de la siguiente manera:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_PhotoQuery();
$query->setUser("sample.user");
$query->setAlbumId("1");
$query->setPhotoId("100");
$query->setKind("comment");

try {
    $photoFeed = $service->getPhotoFeed($query);

    foreach ($photoFeed as $entry) {
        if ($entry instanceof Zend_Gdata_Photos_CommentEntry) {
            // Do something with the comment
        }
    }
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

37.10.3.5. Recuperación de una etiqueta

El servicio permite recuperar etiquetas de un feed de un tipo distinto. Estableciendo una consulta para devolver un kind de "tag", una petición de feed puede devolver etiquetas asociadas con una fotografía específica.

Realizar una acción sobre cada una de las etiquetas de una fotografía dada puede lograrse de la siguiente manera:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$query = new Zend_Gdata_Photos_PhotoQuery();
$query->setUser("sample.user");
$query->setAlbumId("1");
$query->setPhotoId("100");
$query->setKind("tag");

try {
    $photoFeed = $service->getPhotoFeed($query);

    foreach ($photoFeed as $entry) {
        if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
            // Do something with the tag
        }
    }
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getMessage();
}

37.10.4. Creación de entradas

El servicio dispone de funciones para crear álbumes, fotografías, comentarios y etiquetas.

37.10.4.1. Creación de un álbum

El servicio permite crear un nuevo álbum para un usuario autenticado:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$entry = new Zend_Gdata_Photos_AlbumEntry();
$entry->setTitle($service->newTitle("test album"));

$service->insertAlbumEntry($entry);

37.10.4.2. Creación de una fotografía

El servicio permite crear una nueva fotografía para un usuario autenticado:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

// $photo is the name of a file uploaded via an HTML form

$fd = $service->newMediaFileSource($photo["tmp_name"]);
$fd->setContentType($photo["type"]);

$entry = new Zend_Gdata_Photos_PhotoEntry();
$entry->setMediaSource($fd);
$entry->setTitle($service->newTitle($photo["name"]));

$albumQuery = new Zend_Gdata_Photos_AlbumQuery;
$albumQuery->setUser("sample.user");
$albumQuery->setAlbumId("1");

$albumEntry = $service->getAlbumEntry($albumQuery);

$service->insertPhotoEntry($entry, $albumEntry);

37.10.4.3. Creación de un comentario

El servicio permite crear un nuevo comentario para una fotografía:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$entry = new Zend_Gdata_Photos_CommentEntry();
$entry->setTitle($service->newTitle("comment"));
$entry->setContent($service->newContent("comment"));

$photoQuery = new Zend_Gdata_Photos_PhotoQuery;
$photoQuery->setUser("sample.user");
$photoQuery->setAlbumId("1");
$photoQuery->setPhotoId("100");
$photoQuery->setType('entry');

$photoEntry = $service->getPhotoEntry($photoQuery);

$service->insertCommentEntry($entry, $photoEntry);

37.10.4.4. Creación de una etiqueta

El servicio permite crear una nueva etiqueta para una fotografía:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$entry = new Zend_Gdata_Photos_TagEntry();
$entry->setTitle($service->newTitle("tag"));

$photoQuery = new Zend_Gdata_Photos_PhotoQuery;
$photoQuery->setUser("sample.user");
$photoQuery->setAlbumId("1");
$photoQuery->setPhotoId("100");
$photoQuery->setType('entry');

$photoEntry = $service->getPhotoEntry($photoQuery);

$service->insertTagEntry($entry, $photoEntry);

37.10.5. Eliminación de entradas

El servicio dispone de funciones para eliminar álbumes, fotografías, comentarios y etiquetas.

37.10.5.1. Eliminación de un álbum

El servicio permite eliminar un álbum de un usuario autenticado:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$albumQuery = new Zend_Gdata_Photos_AlbumQuery;
$albumQuery->setUser("sample.user");
$albumQuery->setAlbumId("1");
$albumQuery->setType('entry');

$entry = $service->getAlbumEntry($albumQuery);

$service->deleteAlbumEntry($entry, true);

37.10.5.2. Eliminación de una fotografía

El servicio permite eliminar una fotografía de un usuario autenticado:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$photoQuery = new Zend_Gdata_Photos_PhotoQuery;
$photoQuery->setUser("sample.user");
$photoQuery->setAlbumId("1");
$photoQuery->setPhotoId("100");
$photoQuery->setType('entry');

$entry = $service->getPhotoEntry($photoQuery);

$service->deletePhotoEntry($entry, true);

37.10.5.3. Eliminación de un comentario

El servicio permite eliminar un comentario de un usuario autenticado:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$photoQuery = new Zend_Gdata_Photos_PhotoQuery;
$photoQuery->setUser("sample.user");
$photoQuery->setAlbumId("1");
$photoQuery->setPhotoId("100");
$photoQuery->setType('entry');

$path = $photoQuery->getQueryUrl() . '/commentid/' . "1000";

$entry = $service->getCommentEntry($path);

$service->deleteCommentEntry($entry, true);

37.10.5.4. Eliminación de una etiqueta

El servicio permite eliminar una etiqueta de un usuario autenticado:

$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Photos($client);

$photoQuery = new Zend_Gdata_Photos_PhotoQuery;
$photoQuery->setUser("sample.user");
$photoQuery->setAlbumId("1");
$photoQuery->setPhotoId("100");
$photoQuery->setKind("tag");
$query = $photoQuery->getQueryUrl();

$photoFeed = $service->getPhotoFeed($query);

foreach ($photoFeed as $entry) {
    if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
        if ($entry->getContent() == $tagContent) {
            $tagEntry = $entry;
        }
    }
}

$service->deleteTagEntry($tagEntry, true);

37.10.5.5. Concurrencia optimista (notas sobre la eliminación)

Los feeds de GData, incluidos los del servicio Picasa Web Albums, implementan concurrencia optimista, un sistema de versionado que impide que los usuarios sobrescriban cambios de forma inadvertida. Al eliminar una entrada mediante la clase de servicio, si la entrada ha sido modificada desde que se recuperó por última vez, se lanzará una excepción, a menos que se especifique explícitamente lo contrario (en cuyo caso la eliminación se reintenta sobre la entrada actualizada).

Un ejemplo de cómo gestionar el versionado durante una eliminación se muestra en deleteAlbumEntry():

// $album is the albumEntry to be deleted
try {
    $this->delete($album);
} catch (Zend_Gdata_App_HttpException $e) {
    if ($e->getMessage()->getStatus() === 409) {
        $entry =
            new Zend_Gdata_Photos_AlbumEntry($e->getMessage()->getBody());
        $this->delete($entry->getLink('edit')->href);
    } else {
        throw $e;
    }
}