/library/spoon/rest/client.php

https://github.com/decthomas/forkcms · PHP · 271 lines · 92 code · 50 blank · 129 comment · 19 complexity · 7f3eed944036fe07451bc955ff854f19 MD5 · raw file

  1. <?php
  2. /**
  3. * Spoon Library
  4. *
  5. * This source file is part of the Spoon Library. More information,
  6. * documentation and tutorials can be found @ http://www.spoon-library.com
  7. *
  8. * @package spoon
  9. * @subpackage rest
  10. *
  11. *
  12. * @author Davy Hellemans <davy@spoon-library.com>
  13. * @since 1.1.2
  14. */
  15. /**
  16. * This base class provides all the methods used by a REST-client.
  17. *
  18. * @package spoon
  19. * @subpackage rest
  20. *
  21. *
  22. * @author Tijs Verkoyen <tijs@spoon-library.com>
  23. * @author Bram Van Damme <bramus@bram.us>
  24. * @since 1.1.1
  25. */
  26. class SpoonRESTClient
  27. {
  28. /**
  29. * The headers
  30. *
  31. * @var array
  32. */
  33. private $headers = array();
  34. /**
  35. * The port
  36. *
  37. * @var int
  38. */
  39. private $port = 80;
  40. /**
  41. * The timeout in seconds
  42. *
  43. * @var int
  44. */
  45. private $timeout = 10;
  46. /**
  47. * The user-agent
  48. *
  49. * @var string
  50. */
  51. private $userAgent;
  52. /**
  53. * Make the call.
  54. *
  55. * @return string
  56. * @param string $url The url to call.
  57. * @param array[optional] $parameters The parameters to pass.
  58. * @param string[optional] $method The HTTP-method to use, possible values are: GET, POST.
  59. * @param array[optional] $cURLOptions Optional extra cURL-options.
  60. */
  61. public function execute($url, array $parameters = null, $method = 'GET', array $cURLOptions = null)
  62. {
  63. // check if curl is available
  64. if(!function_exists('curl_init')) throw new SpoonFileException('This method requires cURL (http://php.net/curl), it seems like the extension isn\'t installed.');
  65. // init var
  66. $allowedMethods = array('GET', 'POST', 'DELETE');
  67. // redefine
  68. $url = (string) $url;
  69. $parameters = (array) $parameters;
  70. $method = strtoupper((string) $method);
  71. // validate
  72. if(!in_array($method, $allowedMethods)) throw new SpoonRESTException('Invalid method (' . $method . '). Possible methods are: ' . implode(', ', $allowedMethods) . '.');
  73. // init curl options
  74. $options[CURLOPT_PORT] = $this->getPort();
  75. $options[CURLOPT_USERAGENT] = $this->getUserAgent();
  76. $options[CURLOPT_TIMEOUT] = $this->getTimeout();
  77. $options[CURLOPT_RETURNTRANSFER] = true;
  78. // any extra curl options provided?
  79. if($cURLOptions !== null)
  80. {
  81. // loop the extra options, and set 'm
  82. foreach($cURLOptions as $key => $value) $options[$key] = $value;
  83. }
  84. // set headers
  85. $headers = $this->getCustomHeaders();
  86. if(!empty($headers)) $options[CURLOPT_HTTPHEADER] = $headers;
  87. // specific when using GET
  88. if($method == 'GET')
  89. {
  90. // init var
  91. $queryString = '';
  92. // loop parameters and append them to the url
  93. foreach($parameters as $key => $value) $queryString .= '&' . $key . '=' . urlencode($value);
  94. // cleanup
  95. $queryString = trim($queryString, '&');
  96. // is there really a querystring
  97. if($queryString != '')
  98. {
  99. // find ? in url
  100. if(strpos($url, '?') > 0) $url .= '&' . $queryString;
  101. else $url .= '?' . $queryString;
  102. }
  103. }
  104. // specific when using POST
  105. if($method == 'POST' || $method == 'DELETE')
  106. {
  107. $options[CURLOPT_POST] = true;
  108. $options[CURLOPT_POSTFIELDS] = $parameters;
  109. }
  110. // custom requests
  111. if($method === 'DELETE')
  112. {
  113. $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
  114. }
  115. // init curl
  116. $curl = curl_init($url);
  117. // set options
  118. curl_setopt_array($curl, $options);
  119. // execute
  120. $response = curl_exec($curl);
  121. $headers = curl_getinfo($curl);
  122. // fetch errors
  123. $errorNumber = curl_errno($curl);
  124. $errorMessage = curl_error($curl);
  125. // close curl
  126. curl_close($curl);
  127. // validate errors
  128. if($errorNumber != 0) throw new SpoonRESTException('An error occured with the following message: (' . $errorNumber . ')' . $errorMessage . '.');
  129. // validate headers
  130. if($headers['http_code'] != 200) throw new SpoonRESTException('Invalid headers, a header with status-code ' . $headers['http_code'] . ' was returned.');
  131. // return the response
  132. return (string) $response;
  133. }
  134. /**
  135. * Get the headers.
  136. *
  137. * @return array
  138. */
  139. public function getCustomHeaders()
  140. {
  141. return $this->headers;
  142. }
  143. /**
  144. * Get the port that will be used.
  145. *
  146. * @return int
  147. */
  148. public function getPort()
  149. {
  150. return $this->port;
  151. }
  152. /**
  153. * Get the timeout in seconds that will be used.
  154. *
  155. * @return int
  156. */
  157. public function getTimeout()
  158. {
  159. return $this->timeout;
  160. }
  161. /**
  162. * Get the user-agent that will be used. Keep in mind that a spoon header will be prepended.
  163. *
  164. * @return string
  165. */
  166. public function getUserAgent()
  167. {
  168. // prepend SpoonHeader
  169. $userAgent = 'Spoon ' . SPOON_VERSION . '/';
  170. $userAgent .= ($this->userAgent === null) ? 'SpoonRESTClient' : $this->userAgent;
  171. // return
  172. return $userAgent;
  173. }
  174. /**
  175. * Add custom headers that will be sent with each request.
  176. *
  177. * @param array $headers The header, passed as key-value pairs.
  178. */
  179. public function setCustomHeader(array $headers)
  180. {
  181. foreach($headers as $name => $value) $this->headers[(string) $name] = (string) $value;
  182. }
  183. /**
  184. * Set the port for the REST-server, default is 80.
  185. *
  186. * @param int $port The port to connect on.
  187. */
  188. public function setPort($port)
  189. {
  190. $this->port = (int) $port;
  191. }
  192. /**
  193. * Set timeout.
  194. *
  195. * @param int $seconds The maximum number of seconds that the operation can last.
  196. */
  197. public function setTimeout($seconds)
  198. {
  199. $this->timeout = (int) $seconds;
  200. }
  201. /**
  202. * Set a custom user-agent.
  203. *
  204. * @param string $userAgent The UserAgent that will be used. It will look like "Spoon <Spoon version>/<your useragent>".
  205. */
  206. public function setUserAgent($userAgent)
  207. {
  208. $this->userAgent = (string) $userAgent;
  209. }
  210. }
  211. /**
  212. * This exception is used to handle REST related exceptions.
  213. *
  214. * @package spoon
  215. * @subpackage rest
  216. *
  217. *
  218. * @author Tijs Verkoyen <tijs@spoon-library.com>
  219. * @since 1.1.1
  220. */
  221. class SpoonRESTException extends SpoonException {}