/core/Google/Client.php

  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. require_once realpath(dirname(__FILE__) . '/../../autoload.php'); 
  19.  
  20. /** 
  21. * The Google API Client 
  22. * http://code.google.com/p/google-api-php-client/ 
  23. * 
  24. * @author Chris Chabot <chabotc@google.com> 
  25. * @author Chirag Shah <chirags@google.com> 
  26. */ 
  27. class GoogleGAL_Client 
  28. const LIBVER = "1.1.1"; 
  29. const USER_AGENT_SUFFIX = "google-api-php-client/"; 
  30. /** 
  31. * @var GoogleGAL_Auth_Abstract $auth 
  32. */ 
  33. private $auth; 
  34.  
  35. /** 
  36. * @var GoogleGAL_IO_Abstract $io 
  37. */ 
  38. private $io; 
  39.  
  40. /** 
  41. * @var GoogleGAL_Cache_Abstract $cache 
  42. */ 
  43. private $cache; 
  44.  
  45. /** 
  46. * @var GoogleGAL_Config $config 
  47. */ 
  48. private $config; 
  49.  
  50. /** 
  51. * @var GoogleGAL_Logger_Abstract $logger 
  52. */ 
  53. private $logger; 
  54.  
  55. /** 
  56. * @var boolean $deferExecution 
  57. */ 
  58. private $deferExecution = false; 
  59.  
  60. /** @var array $scopes */ 
  61. // Scopes requested by the client 
  62. protected $requestedScopes = array(); 
  63.  
  64. // definitions of services that are discovered. 
  65. protected $services = array(); 
  66.  
  67. // Used to track authenticated state, can't discover services after doing authenticate() 
  68. private $authenticated = false; 
  69.  
  70. /** 
  71. * Construct the Google Client. 
  72. * 
  73. * @param $config GoogleGAL_Config or string for the ini file to load 
  74. */ 
  75. public function __construct($config = null) 
  76. if (is_string($config) && strlen($config)) { 
  77. $config = new GoogleGAL_Config($config); 
  78. } else if ( !($config instanceof GoogleGAL_Config)) { 
  79. $config = new GoogleGAL_Config(); 
  80.  
  81. if ($this->isAppEngine()) { 
  82. // Automatically use Memcache if we're in AppEngine. 
  83. $config->setCacheClass('GoogleGAL_Cache_Memcache'); 
  84.  
  85. if (version_compare(phpversion(), "5.3.4", "<=") || $this->isAppEngine()) { 
  86. // Automatically disable compress.zlib, as currently unsupported. 
  87. $config->setClassConfig('GoogleGAL_Http_Request', 'disable_gzip', true); 
  88.  
  89. if ($config->getIoClass() == GoogleGAL_Config::USE_AUTO_IO_SELECTION) { 
  90. if (function_exists('curl_version') && function_exists('curl_exec') 
  91. && !$this->isAppEngine()) { 
  92. $config->setIoClass("GoogleGAL_IO_Curl"); 
  93. } else { 
  94. $config->setIoClass("GoogleGAL_IO_Stream"); 
  95.  
  96. $this->config = $config; 
  97.  
  98. /** 
  99. * Get a string containing the version of the library. 
  100. * 
  101. * @return string 
  102. */ 
  103. public function getLibraryVersion() 
  104. return self::LIBVER; 
  105.  
  106. /** 
  107. * Attempt to exchange a code for an valid authentication token. 
  108. * Helper wrapped around the OAuth 2.0 implementation. 
  109. * 
  110. * @param $code string code from accounts.google.com 
  111. * @return string token 
  112. */ 
  113. public function authenticate($code) 
  114. $this->authenticated = true; 
  115. return $this->getAuth()->authenticate($code); 
  116.  
  117. /** 
  118. * Set the auth config from the JSON string provided. 
  119. * This structure should match the file downloaded from 
  120. * the "Download JSON" button on in the Google Developer 
  121. * Console. 
  122. * @param string $json the configuration json 
  123. * @throws GoogleGAL_Exception 
  124. */ 
  125. public function setAuthConfig($json) 
  126. $data = json_decode($json); 
  127. $key = isset($data->installed) ? 'installed' : 'web'; 
  128. if (!isset($data->$key)) { 
  129. throw new GoogleGAL_Exception("Invalid client secret JSON file."); 
  130. $this->setClientId($data->$key->client_id); 
  131. $this->setClientSecret($data->$key->client_secret); 
  132. if (isset($data->$key->redirect_uris)) { 
  133. $this->setRedirectUri($data->$key->redirect_uris[0]); 
  134.  
  135. /** 
  136. * Set the auth config from the JSON file in the path 
  137. * provided. This should match the file downloaded from 
  138. * the "Download JSON" button on in the Google Developer 
  139. * Console. 
  140. * @param string $file the file location of the client json 
  141. */ 
  142. public function setAuthConfigFile($file) 
  143. $this->setAuthConfig(file_get_contents($file)); 
  144.  
  145. /** 
  146. * @throws GoogleGAL_Auth_Exception 
  147. * @return array 
  148. * @visible For Testing 
  149. */ 
  150. public function prepareScopes() 
  151. if (empty($this->requestedScopes)) { 
  152. throw new GoogleGAL_Auth_Exception("No scopes specified"); 
  153. $scopes = implode(' ', $this->requestedScopes); 
  154. return $scopes; 
  155.  
  156. /** 
  157. * Set the OAuth 2.0 access token using the string that resulted from calling createAuthUrl() 
  158. * or GoogleGAL_Client#getAccessToken(). 
  159. * @param string $accessToken JSON encoded string containing in the following format: 
  160. * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer",  
  161. * "expires_in":3600, "id_token":"TOKEN", "created":1320790426} 
  162. */ 
  163. public function setAccessToken($accessToken) 
  164. if ($accessToken == 'null') { 
  165. $accessToken = null; 
  166. $this->getAuth()->setAccessToken($accessToken); 
  167.  
  168.  
  169.  
  170. /** 
  171. * Set the authenticator object 
  172. * @param GoogleGAL_Auth_Abstract $auth 
  173. */ 
  174. public function setAuth(GoogleGAL_Auth_Abstract $auth) 
  175. $this->config->setAuthClass(get_class($auth)); 
  176. $this->auth = $auth; 
  177.  
  178. /** 
  179. * Set the IO object 
  180. * @param GoogleGAL_IO_Abstract $io 
  181. */ 
  182. public function setIo(GoogleGAL_IO_Abstract $io) 
  183. $this->config->setIoClass(get_class($io)); 
  184. $this->io = $io; 
  185.  
  186. /** 
  187. * Set the Cache object 
  188. * @param GoogleGAL_Cache_Abstract $cache 
  189. */ 
  190. public function setCache(GoogleGAL_Cache_Abstract $cache) 
  191. $this->config->setCacheClass(get_class($cache)); 
  192. $this->cache = $cache; 
  193.  
  194. /** 
  195. * Set the Logger object 
  196. * @param GoogleGAL_Logger_Abstract $logger 
  197. */ 
  198. public function setLogger(GoogleGAL_Logger_Abstract $logger) 
  199. $this->config->setLoggerClass(get_class($logger)); 
  200. $this->logger = $logger; 
  201.  
  202. /** 
  203. * Construct the OAuth 2.0 authorization request URI. 
  204. * @return string 
  205. */ 
  206. public function createAuthUrl() 
  207. $scopes = $this->prepareScopes(); 
  208. return $this->getAuth()->createAuthUrl($scopes); 
  209.  
  210. /** 
  211. * Get the OAuth 2.0 access token. 
  212. * @return string $accessToken JSON encoded string in the following format: 
  213. * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer",  
  214. * "expires_in":3600, "id_token":"TOKEN", "created":1320790426} 
  215. */ 
  216. public function getAccessToken() 
  217. $token = $this->getAuth()->getAccessToken(); 
  218. // The response is json encoded, so could be the string null. 
  219. // It is arguable whether this check should be here or lower 
  220. // in the library. 
  221. return (null == $token || 'null' == $token || '[]' == $token) ? null : $token; 
  222.  
  223. /** 
  224. * Get the OAuth 2.0 refresh token. 
  225. * @return string $refreshToken refresh token or null if not available 
  226. */ 
  227. public function getRefreshToken() 
  228. return $this->getAuth()->getRefreshToken(); 
  229.  
  230. /** 
  231. * Returns if the access_token is expired. 
  232. * @return bool Returns True if the access_token is expired. 
  233. */ 
  234. public function isAccessTokenExpired() 
  235. return $this->getAuth()->isAccessTokenExpired(); 
  236.  
  237. /** 
  238. * Set OAuth 2.0 "state" parameter to achieve per-request customization. 
  239. * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2 
  240. * @param string $state 
  241. */ 
  242. public function setState($state) 
  243. $this->getAuth()->setState($state); 
  244.  
  245. /** 
  246. * @param string $accessType Possible values for access_type include: 
  247. * {@code "offline"} to request offline access from the user. 
  248. * {@code "online"} to request online access from the user. 
  249. */ 
  250. public function setAccessType($accessType) 
  251. $this->config->setAccessType($accessType); 
  252.  
  253. /** 
  254. * @param string $approvalPrompt Possible values for approval_prompt include: 
  255. * {@code "force"} to force the approval UI to appear. (This is the default value) 
  256. * {@code "auto"} to request auto-approval when possible. 
  257. */ 
  258. public function setApprovalPrompt($approvalPrompt) 
  259. $this->config->setApprovalPrompt($approvalPrompt); 
  260.  
  261. /** 
  262. * Set the login hint, email address or sub id. 
  263. * @param string $loginHint 
  264. */ 
  265. public function setLoginHint($loginHint) 
  266. $this->config->setLoginHint($loginHint); 
  267.  
  268. /** 
  269. * Set the application name, this is included in the User-Agent HTTP header. 
  270. * @param string $applicationName 
  271. */ 
  272. public function setApplicationName($applicationName) 
  273. $this->config->setApplicationName($applicationName); 
  274.  
  275. /** 
  276. * Set the OAuth 2.0 Client ID. 
  277. * @param string $clientId 
  278. */ 
  279. public function setClientId($clientId) 
  280. $this->config->setClientId($clientId); 
  281.  
  282. /** 
  283. * Set the OAuth 2.0 Client Secret. 
  284. * @param string $clientSecret 
  285. */ 
  286. public function setClientSecret($clientSecret) 
  287. $this->config->setClientSecret($clientSecret); 
  288.  
  289. /** 
  290. * Set the OAuth 2.0 Redirect URI. 
  291. * @param string $redirectUri 
  292. */ 
  293. public function setRedirectUri($redirectUri) 
  294. $this->config->setRedirectUri($redirectUri); 
  295.  
  296. /** 
  297. * If 'plus.login' is included in the list of requested scopes, you can use 
  298. * this method to define types of app activities that your app will write. 
  299. * You can find a list of available types here: 
  300. * @link https://developers.google.com/+/api/moment-types 
  301. * 
  302. * @param array $requestVisibleActions Array of app activity types 
  303. */ 
  304. public function setRequestVisibleActions($requestVisibleActions) 
  305. if (is_array($requestVisibleActions)) { 
  306. $requestVisibleActions = join(" ", $requestVisibleActions); 
  307. $this->config->setRequestVisibleActions($requestVisibleActions); 
  308.  
  309. /** 
  310. * Set the developer key to use, these are obtained through the API Console. 
  311. * @see http://code.google.com/apis/console-help/#generatingdevkeys 
  312. * @param string $developerKey 
  313. */ 
  314. public function setDeveloperKey($developerKey) 
  315. $this->config->setDeveloperKey($developerKey); 
  316.  
  317. /** 
  318. * Set the hd (hosted domain) parameter streamlines the login process for 
  319. * Google Apps hosted accounts. By including the domain of the user, you 
  320. * restrict sign-in to accounts at that domain. 
  321. * @param $hd string - the domain to use. 
  322. */ 
  323. public function setHostedDomain($hd) 
  324. $this->config->setHostedDomain($hd); 
  325.  
  326. /** 
  327. * Set the prompt hint. Valid values are none, consent and select_account. 
  328. * If no value is specified and the user has not previously authorized 
  329. * access, then the user is shown a consent screen. 
  330. * @param $prompt string 
  331. */ 
  332. public function setPrompt($prompt) 
  333. $this->config->setPrompt($prompt); 
  334.  
  335. /** 
  336. * openid.realm is a parameter from the OpenID 2.0 protocol, not from OAuth 
  337. * 2.0. It is used in OpenID 2.0 requests to signify the URL-space for which 
  338. * an authentication request is valid. 
  339. * @param $realm string - the URL-space to use. 
  340. */ 
  341. public function setOpenidRealm($realm) 
  342. $this->config->setOpenidRealm($realm); 
  343.  
  344. /** 
  345. * If this is provided with the value true, and the authorization request is 
  346. * granted, the authorization will include any previous authorizations 
  347. * granted to this user/application combination for other scopes. 
  348. * @param $include boolean - the URL-space to use. 
  349. */ 
  350. public function setIncludeGrantedScopes($include) 
  351. $this->config->setIncludeGrantedScopes($include); 
  352.  
  353. /** 
  354. * Fetches a fresh OAuth 2.0 access token with the given refresh token. 
  355. * @param string $refreshToken 
  356. */ 
  357. public function refreshToken($refreshToken) 
  358. $this->getAuth()->refreshToken($refreshToken); 
  359.  
  360. /** 
  361. * Revoke an OAuth2 access token or refresh token. This method will revoke the current access 
  362. * token, if a token isn't provided. 
  363. * @throws GoogleGAL_Auth_Exception 
  364. * @param string|null $token The token (access token or a refresh token) that should be revoked. 
  365. * @return boolean Returns True if the revocation was successful, otherwise False. 
  366. */ 
  367. public function revokeToken($token = null) 
  368. return $this->getAuth()->revokeToken($token); 
  369.  
  370. /** 
  371. * Verify an id_token. This method will verify the current id_token, if one 
  372. * isn't provided. 
  373. * @throws GoogleGAL_Auth_Exception 
  374. * @param string|null $token The token (id_token) that should be verified. 
  375. * @return GoogleGAL_Auth_LoginTicket Returns an apiLoginTicket if the verification was 
  376. * successful. 
  377. */ 
  378. public function verifyIdToken($token = null) 
  379. return $this->getAuth()->verifyIdToken($token); 
  380.  
  381. /** 
  382. * Verify a JWT that was signed with your own certificates. 
  383. * 
  384. * @param $id_token string The JWT token 
  385. * @param $cert_location array of certificates 
  386. * @param $audience string the expected consumer of the token 
  387. * @param $issuer string the expected issuer, defaults to Google 
  388. * @param [$max_expiry] the max lifetime of a token, defaults to MAX_TOKEN_LIFETIME_SECS 
  389. * @return mixed token information if valid, false if not 
  390. */ 
  391. public function verifySignedJwt($id_token, $cert_location, $audience, $issuer, $max_expiry = null) 
  392. $auth = new GoogleGAL_Auth_OAuth2($this); 
  393. $certs = $auth->retrieveCertsFromLocation($cert_location); 
  394. return $auth->verifySignedJwtWithCerts($id_token, $certs, $audience, $issuer, $max_expiry); 
  395.  
  396. /** 
  397. * @param $creds GoogleGAL_Auth_AssertionCredentials 
  398. */ 
  399. public function setAssertionCredentials(GoogleGAL_Auth_AssertionCredentials $creds) 
  400. $this->getAuth()->setAssertionCredentials($creds); 
  401.  
  402. /** 
  403. * Set the scopes to be requested. Must be called before createAuthUrl(). 
  404. * Will remove any previously configured scopes. 
  405. * @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.login',  
  406. * 'https://www.googleapis.com/auth/moderator') 
  407. */ 
  408. public function setScopes($scopes) 
  409. $this->requestedScopes = array(); 
  410. $this->addScope($scopes); 
  411.  
  412. /** 
  413. * This functions adds a scope to be requested as part of the OAuth2.0 flow. 
  414. * Will append any scopes not previously requested to the scope parameter. 
  415. * A single string will be treated as a scope to request. An array of strings 
  416. * will each be appended. 
  417. * @param $scope_or_scopes string|array e.g. "profile" 
  418. */ 
  419. public function addScope($scope_or_scopes) 
  420. if (is_string($scope_or_scopes) && !in_array($scope_or_scopes, $this->requestedScopes)) { 
  421. $this->requestedScopes[] = $scope_or_scopes; 
  422. } else if (is_array($scope_or_scopes)) { 
  423. foreach ($scope_or_scopes as $scope) { 
  424. $this->addScope($scope); 
  425.  
  426. /** 
  427. * Returns the list of scopes requested by the client 
  428. * @return array the list of scopes 
  429. * 
  430. */ 
  431. public function getScopes() 
  432. return $this->requestedScopes; 
  433.  
  434. /** 
  435. * Declare whether batch calls should be used. This may increase throughput 
  436. * by making multiple requests in one connection. 
  437. * 
  438. * @param boolean $useBatch True if the batch support should 
  439. * be enabled. Defaults to False. 
  440. */ 
  441. public function setUseBatch($useBatch) 
  442. // This is actually an alias for setDefer. 
  443. $this->setDefer($useBatch); 
  444.  
  445. /** 
  446. * Declare whether making API calls should make the call immediately, or 
  447. * return a request which can be called with ->execute(); 
  448. * 
  449. * @param boolean $defer True if calls should not be executed right away. 
  450. */ 
  451. public function setDefer($defer) 
  452. $this->deferExecution = $defer; 
  453.  
  454. /** 
  455. * Helper method to execute deferred HTTP requests. 
  456. * 
  457. * @param $request GoogleGAL_Http_Request|GoogleGAL_Http_Batch 
  458. * @throws GoogleGAL_Exception 
  459. * @return object of the type of the expected class or array. 
  460. */ 
  461. public function execute($request) 
  462. if ($request instanceof GoogleGAL_Http_Request) { 
  463. $request->setUserAgent( 
  464. $this->getApplicationName() 
  465. . " " . self::USER_AGENT_SUFFIX 
  466. . $this->getLibraryVersion() 
  467. ); 
  468. if (!$this->getClassConfig("GoogleGAL_Http_Request", "disable_gzip")) { 
  469. $request->enableGzip(); 
  470. $request->maybeMoveParametersToBody(); 
  471. return GoogleGAL_Http_REST::execute($this, $request); 
  472. } else if ($request instanceof GoogleGAL_Http_Batch) { 
  473. return $request->execute(); 
  474. } else { 
  475. throw new GoogleGAL_Exception("Do not know how to execute this type of object."); 
  476.  
  477. /** 
  478. * Whether or not to return raw requests 
  479. * @return boolean 
  480. */ 
  481. public function shouldDefer() 
  482. return $this->deferExecution; 
  483.  
  484. /** 
  485. * @return GoogleGAL_Auth_Abstract Authentication implementation 
  486. */ 
  487. public function getAuth() 
  488. if (!isset($this->auth)) { 
  489. $class = $this->config->getAuthClass(); 
  490. $this->auth = new $class($this); 
  491. return $this->auth; 
  492.  
  493. /** 
  494. * @return GoogleGAL_IO_Abstract IO implementation 
  495. */ 
  496. public function getIo() 
  497. if (!isset($this->io)) { 
  498. $class = $this->config->getIoClass(); 
  499. $this->io = new $class($this); 
  500. return $this->io; 
  501.  
  502. /** 
  503. * @return GoogleGAL_Cache_Abstract Cache implementation 
  504. */ 
  505. public function getCache() 
  506. if (!isset($this->cache)) { 
  507. $class = $this->config->getCacheClass(); 
  508. $this->cache = new $class($this); 
  509. return $this->cache; 
  510.  
  511. /** 
  512. * @return GoogleGAL_Logger_Abstract Logger implementation 
  513. */ 
  514. public function getLogger() 
  515. if (!isset($this->logger)) { 
  516. $class = $this->config->getLoggerClass(); 
  517. $this->logger = new $class($this); 
  518. return $this->logger; 
  519.  
  520. /** 
  521. * Retrieve custom configuration for a specific class. 
  522. * @param $class string|object - class or instance of class to retrieve 
  523. * @param $key string optional - key to retrieve 
  524. * @return array 
  525. */ 
  526. public function getClassConfig($class, $key = null) 
  527. if (!is_string($class)) { 
  528. $class = get_class($class); 
  529. return $this->config->getClassConfig($class, $key); 
  530.  
  531. /** 
  532. * Set configuration specific to a given class. 
  533. * $config->setClassConfig('GoogleGAL_Cache_File',  
  534. * array('directory' => '/tmp/cache')); 
  535. * @param $class string|object - The class name for the configuration 
  536. * @param $config string key or an array of configuration values 
  537. * @param $value string optional - if $config is a key, the value 
  538. * 
  539. */ 
  540. public function setClassConfig($class, $config, $value = null) 
  541. if (!is_string($class)) { 
  542. $class = get_class($class); 
  543. $this->config->setClassConfig($class, $config, $value); 
  544.  
  545.  
  546. /** 
  547. * @return string the base URL to use for calls to the APIs 
  548. */ 
  549. public function getBasePath() 
  550. return $this->config->getBasePath(); 
  551.  
  552. /** 
  553. * @return string the name of the application 
  554. */ 
  555. public function getApplicationName() 
  556. return $this->config->getApplicationName(); 
  557.  
  558. /** 
  559. * Are we running in Google AppEngine? 
  560. * return bool 
  561. */ 
  562. public function isAppEngine() 
  563. return (isset($_SERVER['SERVER_SOFTWARE']) && 
  564. strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine') !== false); 
.