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