1<?php 2/* 3 * Copyright 2010 Google Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18// Check for the json extension, the Google APIs PHP Client won't function 19// without it. 20if (! function_exists('json_decode')) { 21 throw new Exception('Google PHP API Client requires the JSON PHP extension'); 22} 23 24if (! function_exists('http_build_query')) { 25 throw new Exception('Google PHP API Client requires http_build_query()'); 26} 27 28if (! ini_get('date.timezone') && function_exists('date_default_timezone_set')) { 29 date_default_timezone_set('UTC'); 30} 31 32// hack around with the include paths a bit so the library 'just works' 33set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path()); 34 35require_once "config.php"; 36// If a local configuration file is found, merge it's values with the default configuration 37if (file_exists(dirname(__FILE__) . '/local_config.php')) { 38 $defaultConfig = $apiConfig; 39 require_once (dirname(__FILE__) . '/local_config.php'); 40 $apiConfig = array_merge($defaultConfig, $apiConfig); 41} 42 43// Include the top level classes, they each include their own dependencies 44require_once 'service/Google_Model.php'; 45require_once 'service/Google_Service.php'; 46require_once 'service/Google_ServiceResource.php'; 47require_once 'auth/Google_AssertionCredentials.php'; 48require_once 'auth/Google_Signer.php'; 49require_once 'auth/Google_P12Signer.php'; 50require_once 'service/Google_BatchRequest.php'; 51require_once 'external/URITemplateParser.php'; 52require_once 'auth/Google_Auth.php'; 53require_once 'cache/Google_Cache.php'; 54require_once 'io/Google_IO.php'; 55require_once('service/Google_MediaFileUpload.php'); 56 57/** 58 * The Google API Client 59 * http://code.google.com/p/google-api-php-client/ 60 * 61 * @author Chris Chabot <chabotc@google.com> 62 * @author Chirag Shah <chirags@google.com> 63 */ 64class Google_Client { 65 /** 66 * @static 67 * @var Google_Auth $auth 68 */ 69 static $auth; 70 71 /** 72 * @static 73 * @var Google_IO $io 74 */ 75 static $io; 76 77 /** 78 * @static 79 * @var Google_Cache $cache 80 */ 81 static $cache; 82 83 /** 84 * @static 85 * @var boolean $useBatch 86 */ 87 static $useBatch = false; 88 89 /** @var array $scopes */ 90 protected $scopes = array(); 91 92 /** @var bool $useObjects */ 93 protected $useObjects = false; 94 95 // definitions of services that are discovered. 96 protected $services = array(); 97 98 // Used to track authenticated state, can't discover services after doing authenticate() 99 private $authenticated = false; 100 101 public function __construct($config = array()) { 102 global $apiConfig; 103 $apiConfig = array_merge($apiConfig, $config); 104 self::$cache = new $apiConfig['cacheClass'](); 105 self::$auth = new $apiConfig['authClass'](); 106 self::$io = new $apiConfig['ioClass'](); 107 } 108 109 /** 110 * Add a service 111 */ 112 public function addService($service, $version = false) { 113 global $apiConfig; 114 if ($this->authenticated) { 115 throw new Google_Exception('Cant add services after having authenticated'); 116 } 117 $this->services[$service] = array(); 118 if (isset($apiConfig['services'][$service])) { 119 // Merge the service descriptor with the default values 120 $this->services[$service] = array_merge($this->services[$service], $apiConfig['services'][$service]); 121 } 122 } 123 124 public function authenticate($code = null) { 125 $service = $this->prepareService(); 126 $this->authenticated = true; 127 return self::$auth->authenticate($service, $code); 128 } 129 130 /** 131 * @return array 132 * @visible For Testing 133 */ 134 public function prepareService() { 135 $service = array(); 136 $scopes = array(); 137 if ($this->scopes) { 138 $scopes = $this->scopes; 139 } else { 140 foreach ($this->services as $key => $val) { 141 if (isset($val['scope'])) { 142 if (is_array($val['scope'])) { 143 $scopes = array_merge($val['scope'], $scopes); 144 } else { 145 $scopes[] = $val['scope']; 146 } 147 } else { 148 $scopes[] = 'https://www.googleapis.com/auth/' . $key; 149 } 150 unset($val['discoveryURI']); 151 unset($val['scope']); 152 $service = array_merge($service, $val); 153 } 154 } 155 $service['scope'] = implode(' ', $scopes); 156 return $service; 157 } 158 159 /** 160 * Set the OAuth 2.0 access token using the string that resulted from calling authenticate() 161 * or Google_Client#getAccessToken(). 162 * @param string $accessToken JSON encoded string containing in the following format: 163 * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", 164 * "expires_in":3600, "id_token":"TOKEN", "created":1320790426} 165 */ 166 public function setAccessToken($accessToken) { 167 if ($accessToken == null || 'null' == $accessToken) { 168 $accessToken = null; 169 } 170 self::$auth->setAccessToken($accessToken); 171 } 172 173 /** 174 * Set the type of Auth class the client should use. 175 * @param string $authClassName 176 */ 177 public function setAuthClass($authClassName) { 178 self::$auth = new $authClassName(); 179 } 180 181 /** 182 * Construct the OAuth 2.0 authorization request URI. 183 * @return string 184 */ 185 public function createAuthUrl() { 186 $service = $this->prepareService(); 187 return self::$auth->createAuthUrl($service['scope']); 188 } 189 190 /** 191 * Get the OAuth 2.0 access token. 192 * @return string $accessToken JSON encoded string in the following format: 193 * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", 194 * "expires_in":3600,"id_token":"TOKEN", "created":1320790426} 195 */ 196 public function getAccessToken() { 197 $token = self::$auth->getAccessToken(); 198 return (null == $token || 'null' == $token) ? null : $token; 199 } 200 201 /** 202 * Returns if the access_token is expired. 203 * @return bool Returns True if the access_token is expired. 204 */ 205 public function isAccessTokenExpired() { 206 return self::$auth->isAccessTokenExpired(); 207 } 208 209 /** 210 * Set the developer key to use, these are obtained through the API Console. 211 * @see http://code.google.com/apis/console-help/#generatingdevkeys 212 * @param string $developerKey 213 */ 214 public function setDeveloperKey($developerKey) { 215 self::$auth->setDeveloperKey($developerKey); 216 } 217 218 /** 219 * Set OAuth 2.0 "state" parameter to achieve per-request customization. 220 * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2 221 * @param string $state 222 */ 223 public function setState($state) { 224 self::$auth->setState($state); 225 } 226 227 /** 228 * @param string $accessType Possible values for access_type include: 229 * {@code "offline"} to request offline access from the user. (This is the default value) 230 * {@code "online"} to request online access from the user. 231 */ 232 public function setAccessType($accessType) { 233 self::$auth->setAccessType($accessType); 234 } 235 236 /** 237 * @param string $approvalPrompt Possible values for approval_prompt include: 238 * {@code "force"} to force the approval UI to appear. (This is the default value) 239 * {@code "auto"} to request auto-approval when possible. 240 */ 241 public function setApprovalPrompt($approvalPrompt) { 242 self::$auth->setApprovalPrompt($approvalPrompt); 243 } 244 245 /** 246 * Set the application name, this is included in the User-Agent HTTP header. 247 * @param string $applicationName 248 */ 249 public function setApplicationName($applicationName) { 250 global $apiConfig; 251 $apiConfig['application_name'] = $applicationName; 252 } 253 254 /** 255 * Set the OAuth 2.0 Client ID. 256 * @param string $clientId 257 */ 258 public function setClientId($clientId) { 259 global $apiConfig; 260 $apiConfig['oauth2_client_id'] = $clientId; 261 self::$auth->clientId = $clientId; 262 } 263 264 /** 265 * Get the OAuth 2.0 Client ID. 266 */ 267 public function getClientId() { 268 return self::$auth->clientId; 269 } 270 271 /** 272 * Set the OAuth 2.0 Client Secret. 273 * @param string $clientSecret 274 */ 275 public function setClientSecret($clientSecret) { 276 global $apiConfig; 277 $apiConfig['oauth2_client_secret'] = $clientSecret; 278 self::$auth->clientSecret = $clientSecret; 279 } 280 281 /** 282 * Get the OAuth 2.0 Client Secret. 283 */ 284 public function getClientSecret() { 285 return self::$auth->clientSecret; 286 } 287 288 /** 289 * Set the OAuth 2.0 Redirect URI. 290 * @param string $redirectUri 291 */ 292 public function setRedirectUri($redirectUri) { 293 global $apiConfig; 294 $apiConfig['oauth2_redirect_uri'] = $redirectUri; 295 self::$auth->redirectUri = $redirectUri; 296 } 297 298 /** 299 * Get the OAuth 2.0 Redirect URI. 300 */ 301 public function getRedirectUri() { 302 return self::$auth->redirectUri; 303 } 304 305 /** 306 * Fetches a fresh OAuth 2.0 access token with the given refresh token. 307 * @param string $refreshToken 308 * @return void 309 */ 310 public function refreshToken($refreshToken) { 311 self::$auth->refreshToken($refreshToken); 312 } 313 314 /** 315 * Revoke an OAuth2 access token or refresh token. This method will revoke the current access 316 * token, if a token isn't provided. 317 * @throws Google_AuthException 318 * @param string|null $token The token (access token or a refresh token) that should be revoked. 319 * @return boolean Returns True if the revocation was successful, otherwise False. 320 */ 321 public function revokeToken($token = null) { 322 self::$auth->revokeToken($token); 323 } 324 325 /** 326 * Verify an id_token. This method will verify the current id_token, if one 327 * isn't provided. 328 * @throws Google_AuthException 329 * @param string|null $token The token (id_token) that should be verified. 330 * @return Google_LoginTicket Returns an apiLoginTicket if the verification was 331 * successful. 332 */ 333 public function verifyIdToken($token = null) { 334 return self::$auth->verifyIdToken($token); 335 } 336 337 /** 338 * @param Google_AssertionCredentials $creds 339 * @return void 340 */ 341 public function setAssertionCredentials(Google_AssertionCredentials $creds) { 342 self::$auth->setAssertionCredentials($creds); 343 } 344 345 /** 346 * This function allows you to overrule the automatically generated scopes, 347 * so that you can ask for more or less permission in the auth flow 348 * Set this before you call authenticate() though! 349 * @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/moderator') 350 */ 351 public function setScopes($scopes) { 352 $this->scopes = is_string($scopes) ? explode(" ", $scopes) : $scopes; 353 } 354 355 /** 356 * Returns the list of scopes set on the client 357 * @return array the list of scopes 358 * 359 */ 360 public function getScopes() { 361 return $this->scopes; 362 } 363 364 /** 365 * If 'plus.login' is included in the list of requested scopes, you can use 366 * this method to define types of app activities that your app will write. 367 * You can find a list of available types here: 368 * @link https://developers.google.com/+/api/moment-types 369 * 370 * @param array $requestVisibleActions Array of app activity types 371 */ 372 public function setRequestVisibleActions($requestVisibleActions) { 373 self::$auth->requestVisibleActions = 374 join(" ", $requestVisibleActions); 375 } 376 377 /** 378 * Declare if objects should be returned by the api service classes. 379 * 380 * @param boolean $useObjects True if objects should be returned by the service classes. 381 * False if associative arrays should be returned (default behavior). 382 * @experimental 383 */ 384 public function setUseObjects($useObjects) { 385 global $apiConfig; 386 $apiConfig['use_objects'] = $useObjects; 387 } 388 389 /** 390 * Declare if objects should be returned by the api service classes. 391 * 392 * @param boolean $useBatch True if the experimental batch support should 393 * be enabled. Defaults to False. 394 * @experimental 395 */ 396 public function setUseBatch($useBatch) { 397 self::$useBatch = $useBatch; 398 } 399 400 /** 401 * @static 402 * @return Google_Auth the implementation of apiAuth. 403 */ 404 public static function getAuth() { 405 return Google_Client::$auth; 406 } 407 408 /** 409 * @static 410 * @return Google_IO the implementation of apiIo. 411 */ 412 public static function getIo() { 413 return Google_Client::$io; 414 } 415 416 /** 417 * @return Google_Cache the implementation of apiCache. 418 */ 419 public function getCache() { 420 return Google_Client::$cache; 421 } 422} 423 424// Exceptions that the Google PHP API Library can throw 425class Google_Exception extends Exception {} 426class Google_AuthException extends Google_Exception {} 427class Google_CacheException extends Google_Exception {} 428class Google_IOException extends Google_Exception {} 429class Google_ServiceException extends Google_Exception { 430 /** 431 * Optional list of errors returned in a JSON body of an HTTP error response. 432 */ 433 protected $errors = array(); 434 435 /** 436 * Override default constructor to add ability to set $errors. 437 * 438 * @param string $message 439 * @param int $code 440 * @param Exception|null $previous 441 * @param [{string, string}] errors List of errors returned in an HTTP 442 * response. Defaults to []. 443 */ 444 public function __construct($message, $code = 0, Exception $previous = null, 445 $errors = array()) { 446 if(version_compare(PHP_VERSION, '5.3.0') >= 0) { 447 parent::__construct($message, $code, $previous); 448 } else { 449 parent::__construct($message, $code); 450 } 451 452 $this->errors = $errors; 453 } 454 455 /** 456 * An example of the possible errors returned. 457 * 458 * { 459 * "domain": "global", 460 * "reason": "authError", 461 * "message": "Invalid Credentials", 462 * "locationType": "header", 463 * "location": "Authorization", 464 * } 465 * 466 * @return [{string, string}] List of errors return in an HTTP response or []. 467 */ 468 public function getErrors() { 469 return $this->errors; 470 } 471} 472