/includes/API.php

https://github.com/Heello/heello-php · PHP · 217 lines · 139 code · 32 blank · 46 comment · 28 complexity · 7eb2fdf0262dce4a03486f0d6347ba55 MD5 · raw file

  1. <?
  2. /*
  3. * TwitPic API for PHP
  4. * Copyright 2010 Ryan LeFevre - @meltingice
  5. * PHP version 5.3.0+
  6. *
  7. * Licensed under the New BSD License, more info in LICENSE file
  8. * included with this software.
  9. *
  10. * Source code is hosted at http://github.com/meltingice/TwitPic-API-for-PHP
  11. */
  12. namespace Heello;
  13. class API {
  14. const SECURE = true;
  15. const DOMAIN = "api.heello.com";
  16. const VERSION = 1;
  17. private static $API_PATH;
  18. private $api = array();
  19. private $category = null;
  20. private $method = null;
  21. private $format = null;
  22. public function __construct() {
  23. self::$API_PATH = dirname(__FILE__) . '/../api/api.json';
  24. $jsonApi = json_decode(file_get_contents(self::$API_PATH));
  25. foreach ($jsonApi as $endpoint => $actions) {
  26. $this->api[$endpoint] = array();
  27. foreach ($actions as $action => $options) {
  28. $this->api[$endpoint][$action] = $options;
  29. }
  30. }
  31. }
  32. /*
  33. * This function handles the API category that is
  34. * being called and if valid, returns $this so that
  35. * the __call() function can be called next.
  36. */
  37. public function __get($key) {
  38. return $this->api_category($key);
  39. }
  40. /*
  41. * The __call() function handles accessing the API
  42. * method.
  43. */
  44. public function __call($method, $args) {
  45. return $this->api_method($method, $args);
  46. }
  47. /*
  48. * Executes an API call only after the category and method
  49. * have been validated.
  50. */
  51. private function execute($method_args) {
  52. $this->validate_args($method_args);
  53. $options = $this->endpoint_options();
  54. $request = null;
  55. if ($options->method == 'POST') {
  56. $request = new Request(Request::POST, $this->get_request_url($method_args));
  57. } elseif ($options->method == 'DELETE') {
  58. $request = new Request(Request::DELETE, $this->get_request_url($method_args));
  59. } elseif ($options->method == 'PUT') {
  60. $request = new Request(Request::PUT, $this->get_request_url($method_args));
  61. } else { // assume GET?
  62. $request = new Request(Request::GET, $this->get_request_url($method_args));
  63. }
  64. $request->addAttachments($method_args,$options);
  65. $request->addParameters($method_args);
  66. $response = null;
  67. try {
  68. $response = $request->send($this->requires_authentication());
  69. } catch (ExpiredAccessTokenException $e) {
  70. $this->refresh_access_token();
  71. $response = $request->send($this->requires_authentication());
  72. }
  73. $this->reset_parameters();
  74. return $response;
  75. }
  76. private function refresh_access_token() {
  77. $request = new Request(Request::POST, '/oauth/token');
  78. $client = Client::config()->get_client();
  79. $token = Client::config()->get_tokens();
  80. $request->addParameter('client_id', $client['id']);
  81. $request->addParameter('client_secret', $client['secret']);
  82. $request->addParameter('redirect_uri', Client::config()->get_redirect_url());
  83. $request->addParameter('response_type', 'token');
  84. $request->addParameter('refresh_token', $token['refresh']);
  85. $request->addParameter('grant_type', 'refresh_token');
  86. $response = $request->send();
  87. Client::config()->set_access_token($response->access_token);
  88. Client::config()->set_refresh_token($response->refresh_token);
  89. Client::config()->execute_refresh_token_callback();
  90. }
  91. /*
  92. * Validates all of the arguments given to the API
  93. * call and makes sure that required args are present.
  94. */
  95. private function validate_args($args) {
  96. $options = $this->endpoint_options();
  97. if (!isset($options->required_params)) return;
  98. foreach ($options->required_params as $param) {
  99. if ($param == "access_token"){
  100. $tokens = Client::config()->get_tokens();
  101. if (!$tokens['access']){
  102. throw new APIException("Missing required parameter '{$param}' for {$this->category}/{$this->method}");
  103. }
  104. } elseif ($param == "key"){
  105. $client_config = Client::config()->get_client();
  106. if (!$client_config['id']){
  107. throw new APIException("Missing required parameter '{$param}' for {$this->category}/{$this->method}");
  108. }
  109. } elseif ($param == "secret"){
  110. $client_config = Client::config()->get_client();
  111. if (!$client_config['secret']){
  112. throw new APIException("Missing required parameter '{$param}' for {$this->category}/{$this->method}");
  113. }
  114. } elseif (!array_key_exists($param, $args) || !$args[$param]) {
  115. throw new APIException("Missing required parameter '{$param}' for {$this->category}/{$this->method}");
  116. }
  117. }
  118. }
  119. /*
  120. * Checks to see if this API call requires authentication,
  121. * and if we have all the required info.
  122. */
  123. private function requires_authentication() {
  124. $options = $this->endpoint_options();
  125. /* if auth_required is not set, assume false */
  126. if (!isset($options->requires_auth)) return false;
  127. elseif ($options->requires_auth == false) return false;
  128. if (Client::config()->mode() != Config::READWRITE) {
  129. throw new APIException("API call {$this->category}/{$this->method} requires authentication.");
  130. }
  131. return true;
  132. }
  133. /*
  134. * Builds the API request URL
  135. */
  136. private function get_request_url($args) {
  137. $options = $this->endpoint_options();
  138. if (!isset($options->url)) {
  139. return "/{$this->category}/{$this->method}";
  140. }
  141. $url = "{$this->category}/{$options->url}";
  142. if (strpos($url, ":") !== false) {
  143. $url = preg_replace_callback('/(:[A-Za-z]+)/', function ($matches) use ($args) {
  144. $argname = substr($matches[0], 1);
  145. return $args[$argname];
  146. }, $url);
  147. }
  148. return $url;
  149. }
  150. private function reset_parameters() {
  151. $this->category = null;
  152. $this->method = null;
  153. }
  154. /*
  155. * Gets the current API call
  156. */
  157. private function endpoint_options() {
  158. return $this->api[$this->category][$this->method];
  159. }
  160. /*
  161. * Checks to make sure the API category in use
  162. * is valid and returns $this.
  163. */
  164. private function api_category($category) {
  165. if (!isset($this->api[$category])) {
  166. throw new APIException('API category not found');
  167. }
  168. $this->category = $category;
  169. return $this;
  170. }
  171. /*
  172. * Checks to make sure the API method for this category
  173. * is defined and begins the execution of the API call.
  174. */
  175. private function api_method($method, $args) {
  176. if (is_null($this->category)) {
  177. throw new APIException('Error');
  178. } elseif (!isset($this->api[$this->category][$method])) {
  179. throw new APIException("API method not found for {$this->category} endpoint.");
  180. }
  181. $this->method = $method;
  182. if (count($args) > 0) $args = $args[0];
  183. return $this->execute($args);
  184. }
  185. }