Commit aec4292c authored by Dave Cooper's avatar Dave Cooper Committed by Eloy Lafuente
Browse files

MDL-49519 libraries: Updated google-api-php-client to 1.1.2

parent ca66bc38
This diff is collapsed.
......@@ -12,6 +12,8 @@ This library is in Beta. We're comfortable enough with the stability and feature
* [PHP 5.2.1 or higher](http://www.php.net/)
* [PHP JSON extension](http://php.net/manual/en/book.json.php)
*Note*: some features (service accounts and id token verification) require PHP 5.3.0 and above due to cryptographic algorithm requirements.
## Developer Documentation ##
http://developers.google.com/api-client-library/php
......@@ -23,11 +25,13 @@ For the latest installation and setup instructions, see [the documentation](http
See the examples/ directory for examples of the key client features.
```PHP
<?php
require_once 'Google/Client.php';
require_once 'Google/Service/Books.php';
require_once 'google-api-php-client/autoload.php'; // or wherever autoload.php is located
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey("YOUR_APP_KEY");
$service = new Google_Service_Books($client);
$optParams = array('filter' => 'free-ebooks');
$results = $service->volumes->listVolumes('Henry David Thoreau', $optParams);
......@@ -35,6 +39,7 @@ See the examples/ directory for examples of the key client features.
foreach ($results as $item) {
echo $item['volumeInfo']['title'], "<br /> \n";
}
```
## Frequently Asked Questions ##
......@@ -57,6 +62,16 @@ When we started working on the 1.0.0 branch we knew there were several fundament
The _Service classes are generally automatically generated from the API discovery documents: https://developers.google.com/discovery/. Sometimes new features are added to APIs with unusual names, which can cause some unexpected or non-standard style naming in the PHP classes.
### How do I deal with non-JSON response types? ###
Some services return XML or similar by default, rather than JSON, which is what the library supports. You can request a JSON response by adding an 'alt' argument to optional params that is normally the last argument to a method call:
```
$opt_params = array(
'alt' => "json"
);
```
## Code Quality ##
Copy the ruleset.xml in style/ into a new directory named GAPI/ in your
......
<?php
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function google_api_php_client_autoload($className) {
$classPath = explode('_', $className);
if ($classPath[0] != 'Google') {
return;
}
if (count($classPath) > 3) {
// Maximum class file path depth in this project is 3.
$classPath = array_slice($classPath, 0, 3);
}
$filePath = dirname(__FILE__) . '/src/' . implode('/', $classPath) . '.php';
if (file_exists($filePath)) {
require_once($filePath);
}
}
spl_autoload_register('google_api_php_client_autoload');
Google APIs Client Library for PHP
==================================
Only the source and the README files have been kept in this directory:
Only the source, README and autoloader files have been kept in this directory:
- Copy /src/Google to /Google
- Copy /src/Google to /src/Google
- Copy /LICENSE to LICENSE
- Copy /README.md to README.md
- Copy /autoload.php to autoload.php
Here are the files that we have added.
......@@ -30,4 +31,4 @@ Repository: https://github.com/google/google-api-php-client
Documentation: https://developers.google.com/api-client-library/php/
Global documentation: https://developers.google.com
Downloaded version: 1.0.5-beta
Downloaded version: 1.1.2
......@@ -14,7 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once "Google/Http/Request.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* Abstract class for the Authentication in the API client
......
......@@ -22,8 +22,7 @@
*/
use google\appengine\api\app_identity\AppIdentityService;
require_once "Google/Auth/Abstract.php";
require_once "Google/Http/Request.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* Authentication via the Google App Engine App Identity service.
......@@ -31,7 +30,6 @@ require_once "Google/Http/Request.php";
class Google_Auth_AppIdentity extends Google_Auth_Abstract
{
const CACHE_PREFIX = "Google_Auth_AppIdentity::";
const CACHE_LIFETIME = 1500;
private $key = null;
private $client;
private $token = false;
......@@ -50,18 +48,22 @@ class Google_Auth_AppIdentity extends Google_Auth_Abstract
if ($this->token && $this->tokenScopes == $scopes) {
return $this->token;
}
$memcache = new Memcached();
$this->token = $memcache->get(self::CACHE_PREFIX . $scopes);
$cacheKey = self::CACHE_PREFIX;
if (is_string($scopes)) {
$cacheKey .= $scopes;
} else if (is_array($scopes)) {
$cacheKey .= implode(":", $scopes);
}
$this->token = $this->client->getCache()->get($cacheKey);
if (!$this->token) {
$this->token = AppIdentityService::getAccessToken($scopes);
if ($this->token) {
$memcache_key = self::CACHE_PREFIX;
if (is_string($scopes)) {
$memcache_key .= $scopes;
} else if (is_array($scopes)) {
$memcache_key .= implode(":", $scopes);
}
$memcache->set($memcache_key, $this->token, self::CACHE_LIFETIME);
$this->client->getCache()->set(
$cacheKey,
$this->token
);
}
}
$this->tokenScopes = $scopes;
......@@ -81,7 +83,7 @@ class Google_Auth_AppIdentity extends Google_Auth_Abstract
public function authenticatedRequest(Google_Http_Request $request)
{
$request = $this->sign($request);
return $this->io->makeRequest($request);
return $this->client->getIo()->makeRequest($request);
}
public function sign(Google_Http_Request $request)
......@@ -90,6 +92,9 @@ class Google_Auth_AppIdentity extends Google_Auth_Abstract
// No token, so nothing to do.
return $request;
}
$this->client->getLogger()->debug('App Identity authentication');
// Add the OAuth2 header to the request
$request->setRequestHeaders(
array('Authorization' => 'Bearer ' . $this->token['access_token'])
......
......@@ -15,9 +15,7 @@
* limitations under the License.
*/
require_once "Google/Auth/OAuth2.php";
require_once "Google/Signer/P12.php";
require_once "Google/Utils.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* Credentials object used for OAuth 2.0 Signed JWT assertion grants.
......
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
require_once "Google/Exception.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
class Google_Auth_Exception extends Google_Exception
{
......
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
require_once "Google/Auth/Exception.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* Class to hold information about an authenticated login.
......
......@@ -15,14 +15,7 @@
* limitations under the License.
*/
require_once "Google/Auth/Abstract.php";
require_once "Google/Auth/AssertionCredentials.php";
require_once "Google/Auth/Exception.php";
require_once "Google/Auth/LoginTicket.php";
require_once "Google/Client.php";
require_once "Google/Http/Request.php";
require_once "Google/Utils.php";
require_once "Google/Verifier/Pem.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* Authentication class that deals with the OAuth 2 web-server authentication flow
......@@ -119,12 +112,15 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
} else {
$decodedResponse = json_decode($response->getResponseBody(), true);
if ($decodedResponse != null && $decodedResponse['error']) {
$decodedResponse = $decodedResponse['error'];
$errorText = $decodedResponse['error'];
if (isset($decodedResponse['error_description'])) {
$errorText .= ": " . $decodedResponse['error_description'];
}
}
throw new Google_Auth_Exception(
sprintf(
"Error fetching OAuth2 access token, message: '%s'",
$decodedResponse
$errorText
),
$response->getResponseHttpCode()
);
......@@ -146,13 +142,18 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
'client_id' => $this->client->getClassConfig($this, 'client_id'),
'scope' => $scope,
'access_type' => $this->client->getClassConfig($this, 'access_type'),
'approval_prompt' => $this->client->getClassConfig($this, 'approval_prompt'),
);
$login_hint = $this->client->getClassConfig($this, 'login_hint');
if ($login_hint != '') {
$params['login_hint'] = $login_hint;
// Prefer prompt to approval prompt.
if ($this->client->getClassConfig($this, 'prompt')) {
$params = $this->maybeAddParam($params, 'prompt');
} else {
$params = $this->maybeAddParam($params, 'approval_prompt');
}
$params = $this->maybeAddParam($params, 'login_hint');
$params = $this->maybeAddParam($params, 'hd');
$params = $this->maybeAddParam($params, 'openid.realm');
$params = $this->maybeAddParam($params, 'include_granted_scopes');
// If the list of scopes contains plus.login, add request_visible_actions
// to auth URL.
......@@ -189,6 +190,15 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
return json_encode($this->token);
}
public function getRefreshToken()
{
if (array_key_exists('refresh_token', $this->token)) {
return $this->token['refresh_token'];
} else {
return null;
}
}
public function setState($state)
{
$this->state = $state;
......@@ -223,17 +233,21 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
if ($this->assertionCredentials) {
$this->refreshTokenWithAssertion();
} else {
$this->client->getLogger()->debug('OAuth2 access token expired');
if (! array_key_exists('refresh_token', $this->token)) {
throw new Google_Auth_Exception(
"The OAuth 2.0 access token has expired,"
." and a refresh token is not available. Refresh tokens"
." are not returned for responses that were auto-approved."
);
$error = "The OAuth 2.0 access token has expired,"
." and a refresh token is not available. Refresh tokens"
." are not returned for responses that were auto-approved.";
$this->client->getLogger()->error($error);
throw new Google_Auth_Exception($error);
}
$this->refreshToken($this->token['refresh_token']);
}
}
$this->client->getLogger()->debug('OAuth2 authentication');
// Add the OAuth2 header to the request
$request->setRequestHeaders(
array('Authorization' => 'Bearer ' . $this->token['access_token'])
......@@ -285,6 +299,7 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
}
}
$this->client->getLogger()->debug('OAuth2 access token expired');
$this->refreshTokenRequest(
array(
'grant_type' => 'assertion',
......@@ -304,6 +319,14 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
private function refreshTokenRequest($params)
{
if (isset($params['assertion'])) {
$this->client->getLogger()->info(
'OAuth2 access token refresh with Signed JWT assertion grants.'
);
} else {
$this->client->getLogger()->info('OAuth2 access token refresh');
}
$http = new Google_Http_Request(
self::OAUTH2_TOKEN_URI,
'POST',
......@@ -401,7 +424,9 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
/**
* Retrieve and cache a certificates file.
* @param $url location
*
* @param $url string location
* @throws Google_Auth_Exception
* @return array certificates
*/
public function retrieveCertsFromLocation($url)
......@@ -464,12 +489,13 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
/**
* Verifies the id token, returns the verified token contents.
*
* @param $jwt the token
* @param $jwt string the token
* @param $certs array of certificates
* @param $required_audience the expected consumer of the token
* @param $required_audience string the expected consumer of the token
* @param [$issuer] the expected issues, defaults to Google
* @param [$max_expiry] the max lifetime of a token, defaults to MAX_TOKEN_LIFETIME_SECS
* @return token information if valid, false if not
* @throws Google_Auth_Exception
* @return mixed token information if valid, false if not
*/
public function verifySignedJwtWithCerts(
$jwt,
......@@ -592,4 +618,16 @@ class Google_Auth_OAuth2 extends Google_Auth_Abstract
// All good.
return new Google_Auth_LoginTicket($envelope, $payload);
}
/**
* Add a parameter to the auth params if not empty string.
*/
private function maybeAddParam($params, $name)
{
$param = $this->client->getClassConfig($this, $name);
if ($param != '') {
$params[$name] = $param;
}
return $params;
}
}
......@@ -15,8 +15,7 @@
* limitations under the License.
*/
require_once "Google/Auth/Abstract.php";
require_once "Google/Http/Request.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* Simple API access implementation. Can either be used to make requests
......@@ -55,6 +54,9 @@ class Google_Auth_Simple extends Google_Auth_Abstract
{
$key = $this->client->getClassConfig($this, 'developer_key');
if ($key) {
$this->client->getLogger()->debug(
'Simple API Access developer key authentication'
);
$request->setQueryParam('key', $key);
}
return $request;
......
......@@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once "Google/Cache/Abstract.php";
require_once "Google/Cache/Exception.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/**
* A persistent storage class based on the APC cache, which is not
......@@ -28,11 +27,21 @@ require_once "Google/Cache/Exception.php";
*/
class Google_Cache_Apc extends Google_Cache_Abstract
{
/**
* @var Google_Client the current client
*/
private $client;
public function __construct(Google_Client $client)
{
if (! function_exists('apc_add') ) {
throw new Google_Cache_Exception("Apc functions not available");
$error = "Apc functions not available";
$client->getLogger()->error($error);
throw new Google_Cache_Exception($error);
}
$this->client = $client;
}
/**
......@@ -42,12 +51,26 @@ class Google_Cache_Apc extends Google_Cache_Abstract
{
$ret = apc_fetch($key);
if ($ret === false) {
$this->client->getLogger()->debug(
'APC cache miss',
array('key' => $key)
);
return false;
}
if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
$this->client->getLogger()->debug(
'APC cache miss (expired)',
array('key' => $key, 'var' => $ret)
);
$this->delete($key);
return false;
}
$this->client->getLogger()->debug(
'APC cache hit',
array('key' => $key, 'var' => $ret)
);
return $ret['data'];
}
......@@ -56,10 +79,21 @@ class Google_Cache_Apc extends Google_Cache_Abstract
*/
public function set($key, $value)
{
$rc = apc_store($key, array('time' => time(), 'data' => $value));
$var = array('time' => time(), 'data' => $value);
$rc = apc_store($key, $var);
if ($rc == false) {
$this->client->getLogger()->error(
'APC cache set failed',
array('key' => $key, 'var' => $var)
);
throw new Google_Cache_Exception("Couldn't store data");
}
$this->client->getLogger()->debug(
'APC cache set',
array('key' => $key, 'var' => $var)
);
}
/**
......@@ -68,6 +102,10 @@ class Google_Cache_Apc extends Google_Cache_Abstract
*/
public function delete($key)
{
$this->client->getLogger()->debug(
'APC cache delete',
array('key' => $key)
);
apc_delete($key);
}
}
......@@ -14,7 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once "Google/Exception.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
class Google_Cache_Exception extends Google_Exception
{
......
......@@ -15,8 +15,7 @@
* limitations under the License.
*/
require_once "Google/Cache/Abstract.php";
require_once "Google/Cache/Exception.php";
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
/*
* This class implements a basic on disk storage. While that does
......@@ -32,23 +31,37 @@ class Google_Cache_File extends Google_Cache_Abstract
private $path;
private $fh;
/**
* @var Google_Client the current client
*/
private $client;
public function __construct(Google_Client $client)
{
$this->path = $client->getClassConfig($this, 'directory');
$this->client = $client;
$this->path = $this->client->getClassConfig($this, 'directory');
}
public function get($key, $expiration = false)
{
$storageFile = $this->getCacheFile($key);
$data = false;
if (!file_exists($storageFile)) {
$this->client->getLogger()->debug(
'File cache miss',
array('key' => $key, 'file' => $storageFile)
);
return false;
}
if ($expiration) {
$mtime = filemtime($storageFile);
if ((time() - $mtime) >= $expiration) {
$this->client->getLogger()->debug(
'File cache miss (expired)',
array('key' => $key, 'file' => $storageFile)
);
$this->delete($key);
return false;
}
......@@ -60,6 +73,11 @@ class Google_Cache_File extends Google_Cache_Abstract
$this->unlock($storageFile);
}
$this->client->getLogger()->debug(
'File cache hit',
array('key' => $key, 'file' => $storageFile, 'var' => $data)
);
return $data;
}
......@@ -72,6 +90,16 @@ class Google_Cache_File extends Google_Cache_Abstract
$data = serialize($value);
$result = fwrite($this->fh, $data);
$this->unlock($storageFile);
$this->client->getLogger()->debug(
'File cache set',
array('key' => $key, 'file' => $storageFile, 'var' => $value)
);
} else {
$this->client->getLogger()->notice(
'File cache set failed',
array('key' => $key, 'file' => $storageFile)
);
}
}
......@@ -79,10 +107,19 @@ class Google_Cache_File extends Google_Cache_Abstract
{
$file = $this->getCacheFile($key);
if (file_exists($file) && !unlink($file)) {
$this->client->getLogger()->error(
'File cache delete failed',
array('key' => $key, 'file' => $file)
);
throw new Google_Cache_Exception("Cache file could not be deleted");
}
$this->client->getLogger()->debug(
'File cache delete',
array('key' => $key, 'file' => $file)
);
}
private function getWriteableCacheFile($file)
{
return $this->getCacheFile($file, true);
......@@ -92,7 +129,7 @@ class Google_Cache_File extends Google_Cache_Abstract
{
return $this->getCacheDir($file, $forWrite) . '/' . md5($file);
}
private function getCacheDir($file, $forWrite)
{
// use the first 2 characters of the hash as a directory prefix
......@@ -101,26 +138,34 @@ class Google_Cache_File extends Google_Cache_Abstract
$storageDir = $this->path . '/' . substr(md5($file), 0, 2);
if ($forWrite && ! is_dir($storageDir)) {
if (! mkdir($storageDir, 0755, true)) {
$this->client->getLogger()->error(
'File cache creation failed',
array('dir' => $storageDir)
);
throw new Google_Cache_Exception("Could not create storage directory: $storageDir");
}
}