PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Services/Digg2.php

https://github.com/Chetna/Services_Digg2
PHP | 453 lines | 160 code | 34 blank | 259 comment | 8 complexity | b8f282fb22e4fce5b368f7a8d209ed02 MD5 | raw file
  1. <?php
  2. /**
  3. * Services_Digg2
  4. *
  5. * PHP Version 5.2.0+
  6. *
  7. * @category Services
  8. * @package Services_Digg2
  9. * @author Bill Shupp <hostmaster@shupp.org>
  10. * @copyright 2010 Digg, Inc.
  11. * @license http://www.opensource.org/licenses/bsd-license.php FreeBSD
  12. * @link http://github.com/digg/services_digg2
  13. */
  14. /**
  15. * Required files
  16. */
  17. require_once 'HTTP/Request2.php';
  18. require_once 'Services/Digg2/Exception.php';
  19. require_once 'HTTP/OAuth.php';
  20. require_once 'HTTP/OAuth/Consumer.php';
  21. require_once 'HTTP/OAuth/Consumer/Request.php';
  22. /**
  23. * Services_Digg2
  24. *
  25. * A simple pass-through layer for accessing Digg's second generation API.
  26. *
  27. * Anonymous request for popular stories:
  28. * <code>
  29. * require_once 'Services/Digg2.php';
  30. *
  31. * $digg = new Services_Digg2;
  32. * try {
  33. * $results = $digg->story->getPopular();
  34. * } catch (Services_Digg2_Exception $e) {
  35. * echo $e->getMessage();
  36. * }
  37. *
  38. * var_dump($results);
  39. * </code>
  40. *
  41. *
  42. * Authenticated request for digging a story
  43. * <code>
  44. * require_once 'Services/Digg2.php';
  45. * require_once 'HTTP/OAuth/Consumer.php';
  46. *
  47. * $digg = new Services_Digg2;
  48. * $oauth = new HTTP_OAuth_Consumer('key', 'secret', 'token', 'token_secret');
  49. * $digg->accept($oauth);
  50. *
  51. * try {
  52. * $result = $digg->story->digg(array('story_id' => 12345));
  53. * } catch (Services_Digg2_Exception $e) {
  54. * echo $e->getMessage();
  55. * }
  56. *
  57. * var_dump($result);
  58. * </code>
  59. *
  60. * See {@link http://digg.com/api} for API documentation.
  61. *
  62. * @category Services
  63. * @package Services_Digg2
  64. * @author Bill Shupp <hostmaster@shupp.org>
  65. * @copyright 2010 Digg, Inc.
  66. * @license http://www.opensource.org/licenses/bsd-license.php FreeBSD
  67. * @link http://github.com/digg/services_digg2
  68. */
  69. class Services_Digg2
  70. {
  71. /**
  72. * URI of API. You shouldn't need to change this unless you work at Digg.
  73. *
  74. * @see getURI()
  75. * @see setURI()
  76. * @var string
  77. */
  78. protected $uri = 'http://services.digg.com';
  79. /**
  80. * Version to use in API calls
  81. *
  82. * @var mixed
  83. */
  84. protected $version = '2.0';
  85. /**
  86. * Supported version numbers
  87. *
  88. * @var $versions
  89. */
  90. protected $versions = array('1.0', '2.0');
  91. /**
  92. * Current group requested. i.e., $digg->story->getAll(), the group is "story".
  93. *
  94. * @see __get(), __call()
  95. * @var string
  96. */
  97. protected $currentGroup = null;
  98. /**
  99. * Stores an optional custom instance of HTTP_Request2. Use this if you want
  100. * to set HTTP_Request2 options, like timeouts, etc.
  101. *
  102. * @see accept(), getHTTPRequest2()
  103. * @var HTTP_Request2
  104. */
  105. protected $HTTPRequest2 = null;
  106. /**
  107. * Stores an instance of HTTP_OAuth_Consumer
  108. *
  109. * @see accept(), getHTTPOAuthConsumer()
  110. * @var HTTP_OAuth_Consumer|null
  111. */
  112. protected $HTTPOAuthConsumer = null;
  113. /**
  114. * Methods that require POST and OAuth
  115. *
  116. * @var array
  117. */
  118. protected $writeMethods = array(
  119. 'story.digg',
  120. 'story.bury',
  121. 'story.hide',
  122. 'comment.digg',
  123. 'comment.bury',
  124. 'comment.post',
  125. 'user.follow',
  126. 'user.unfollow',
  127. 'getSavedStories',
  128. 'saveStory',
  129. 'removeStory',
  130. 'oauth.verify'
  131. );
  132. /**
  133. * Last response object
  134. *
  135. * @see getLastResponse()
  136. * @var HTTP_Request2_Response
  137. */
  138. protected $lastResponse = null;
  139. /**
  140. * Sets the URI. You'll probably never use this unless you work at Digg.
  141. *
  142. * @param string $uri The Digg API URI
  143. *
  144. * @see getURI()
  145. * @see $uri
  146. * @throws Services_Digg2_Exception on invalid URI
  147. * @return void
  148. */
  149. public function setURI($uri)
  150. {
  151. if (!filter_var($uri, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)) {
  152. throw new Services_Digg2_Exception('Invalid URI: ' . $uri);
  153. }
  154. $this->uri = $uri;
  155. }
  156. /**
  157. * Gets the Digg API URI
  158. *
  159. * @return string
  160. */
  161. public function getURI()
  162. {
  163. return $this->uri;
  164. }
  165. /**
  166. * Accepts HTTP_OAuth_Consumer (for writeable endpoints), or a custom instance
  167. * of HTTP_Request2. The latter is useful if you want to use custom config
  168. * options, adapters, etc, for HTTP_Request2.
  169. *
  170. * @param mixed $object HTTP_OAuth_Consumer instance or custom instance of
  171. * HTTP_Request2
  172. *
  173. * @see getHTTPRequest2(), getHTTPOAuthConsumer()
  174. * @return void
  175. */
  176. public function accept($object)
  177. {
  178. switch (get_class($object)) {
  179. case 'HTTP_Request2':
  180. $this->HTTPRequest2 = $object;
  181. break;
  182. case 'HTTP_OAuth_Consumer':
  183. $this->HTTPOAuthConsumer = $object;
  184. break;
  185. default:
  186. throw new Services_Digg2_Exception(
  187. 'Only HTTP_Request2 and HTTP_OAuth_Consumer may be accepted'
  188. );
  189. }
  190. }
  191. /**
  192. * Gets an instance of HTTP_Request2. If $HTTPRequest2 is not aleady set,
  193. * an instance will be created, set, and returned.
  194. *
  195. * @see accept()
  196. * @return HTTP_Request2
  197. */
  198. public function getHTTPRequest2()
  199. {
  200. if (!$this->HTTPRequest2 instanceof HTTP_Request2) {
  201. $this->HTTPRequest2 = new HTTP_Request2;
  202. $this->HTTPRequest2->setConfig(array('connect_timeout' => 3,
  203. 'timeout' => 3));
  204. }
  205. return $this->HTTPRequest2;
  206. }
  207. /**
  208. * Gets $this->HTTPOAuthConsumer, regardless of whether it is set or not.
  209. *
  210. * @return void
  211. */
  212. public function getHTTPOAuthConsumer()
  213. {
  214. return $this->HTTPOAuthConsumer;
  215. }
  216. /**
  217. * Sets the version of the API to use.
  218. *
  219. * @param mixed $version Version to use, defaults to 1.0
  220. *
  221. * @see getVersion()
  222. * @throws Services_Digg2_Exception on invalid version
  223. * @return void
  224. */
  225. public function setVersion($version)
  226. {
  227. if (!in_array($version, $this->versions)) {
  228. throw new Services_Digg2_Exception("Invalid version: $version");
  229. }
  230. $this->version = $version;
  231. }
  232. /**
  233. * Gets the current version setting (i.e. 1.0).
  234. *
  235. * @see setVersion()
  236. * @return string
  237. */
  238. public function getVersion()
  239. {
  240. return $this->version;
  241. }
  242. /**
  243. * Represents an API "group", and provides a pass-through to __call().
  244. *
  245. * The example below calls story.getInfo(). The object spacing is needed
  246. * because member variables in PHP cannot have '.' in them.
  247. * <code>
  248. * $digg = new Services_Digg2()
  249. * $story = $digg->story->getInfo(array('story_id' => 12345));
  250. * </code>
  251. *
  252. * See {@link http://digg.com/api} for API documentation.
  253. *
  254. * @param string $group The name of the API "group"
  255. *
  256. * @see __call()
  257. * @return Services_Digg2 (current instance)
  258. */
  259. public function __get($group)
  260. {
  261. $this->currentGroup = $group;
  262. return $this;
  263. }
  264. /**
  265. * Concatenates the current group and a method, then adds it as the 'method'
  266. * key of the arguments array, and finally passes to sendRequest(). No local
  267. * validation is done. Any errors are passed back from the Digg API.
  268. *
  269. * See {@link http://digg.com/api} for API documentation.
  270. *
  271. * @param string $name Method name (i.e. getInfo())
  272. * @param array $args Array of arguments. 'method' key will be overwritten.
  273. *
  274. * @see __get()
  275. * @throws Services_Digg2_Exception (indirectly) on anything but a 2XX response
  276. * @return result of sendRequest()
  277. */
  278. public function __call($name, array $args = array())
  279. {
  280. if (count($args)) {
  281. $args = $args[0];
  282. }
  283. return $this->sendRequest($name, $args);
  284. }
  285. /**
  286. * Sends a request to the Digg API.
  287. *
  288. * @param array $args Array of arguments, includeing the method.
  289. *
  290. * @ignore
  291. * @throws Services_Digg2_Exception on error
  292. * @return stdObject response
  293. */
  294. protected function sendRequest($method, array $args)
  295. {
  296. $method = $this->currentGroup . '.' . $method;
  297. $httpMethod = in_array($method, $this->writeMethods) ?
  298. HTTP_Request2::METHOD_POST : HTTP_Request2::METHOD_GET;
  299. $this->getHTTPRequest2()->setMethod($httpMethod);
  300. // Hard coding json for now
  301. $args['type'] = 'json';
  302. $this->getHTTPRequest2()->setHeader('Accept: application/json');
  303. $uri = $this->getURI() . '/' . $this->getVersion() . '/'
  304. . $method;
  305. if ($this->getHTTPOAuthConsumer() instanceof HTTP_OAuth_Consumer) {
  306. try {
  307. return $this->parseResponse($this->sendOAuthRequest($uri, $args));
  308. } catch (HTTP_OAuth_Exception $e) {
  309. throw new Services_Digg2_Exception($e->getMessage(), $e->getCode());
  310. }
  311. }
  312. try {
  313. return $this->parseResponse($this->sendAnonymousRequest($uri, $args));
  314. } catch (HTTP_Request2_Exception $e) {
  315. throw new Services_Digg2_Exception($e->getMessage(), $e->getCode());
  316. }
  317. }
  318. /**
  319. * Sends an OAuth request to the Digg API
  320. *
  321. * @param string $uri The URI to talk to
  322. * @param array $args An array of arguments
  323. *
  324. * @ignore
  325. * @return HTTP_Request2_Response
  326. */
  327. protected function sendOAuthRequest($uri, array $args)
  328. {
  329. $oauth = $this->getHTTPOAuthConsumer();
  330. // Use the same instance of HTTP_Request2
  331. $consumerRequest = new HTTP_OAuth_Consumer_Request;
  332. $consumerRequest->accept($this->getHTTPRequest2());
  333. $oauth->accept($consumerRequest);
  334. return $oauth->sendRequest($uri, $args)->getResponse();
  335. }
  336. /**
  337. * Sends an anonymous GET request to the Digg API.
  338. *
  339. * @param string $uri The Digg API URI
  340. * @param array $args An array of arguments
  341. *
  342. * @ignore
  343. * @return void
  344. */
  345. protected function sendAnonymousRequest($uri, $args)
  346. {
  347. $req = $this->getHTTPRequest2();
  348. $parts = array();
  349. foreach ($args as $param => $value) {
  350. $parts[] = urlencode($param) . '=' . urlencode($value);
  351. }
  352. $req->setUrl($uri .= '?' . implode('&', $parts));
  353. return $req->send();
  354. }
  355. /**
  356. * Parses the response, returning stdClass of the reponse body
  357. *
  358. * @param HTTP_Request2_Response $response The HTTP_Request2 response
  359. *
  360. * @ignore
  361. * @throws Services_Digg2_Exception on a non-2XX response
  362. * @return stdClass (decoded json)
  363. */
  364. protected function parseResponse(HTTP_Request2_Response $response)
  365. {
  366. $this->lastResponse = $response;
  367. $body = json_decode($response->getBody());
  368. if (!is_object($body)) {
  369. throw new Services_Digg2_Exception(
  370. 'Unabled to decode result: ' . $response->getBody()
  371. );
  372. }
  373. $status = $response->getStatus();
  374. $message = $status . ' - ' . $response->getReasonPhrase();
  375. if (strncmp($status, '2', 1) !== 0) {
  376. throw new Services_Digg2_Exception($message,
  377. $body->code,
  378. $status);
  379. }
  380. return $body;
  381. }
  382. /**
  383. * Returns the current group being selected.
  384. *
  385. * @ignore
  386. * @see $currentGroups
  387. * @see __get()
  388. * @return string
  389. */
  390. protected function getCurrentGroup()
  391. {
  392. return $this->currentGroup;
  393. }
  394. /**
  395. * Returns the last HTTP_Request2_Response object. Defaults to null if no
  396. * API request has been made yet. Handy if you want to look at the X-RateLimit
  397. * headers, like so:
  398. *
  399. * <code>
  400. * require_once 'Services/Digg2.php';
  401. *
  402. * $digg = new Services_Digg2;
  403. * $popular = $digg->story->getPopular();
  404. * $current = $digg->getLastResponse()->getHeader('X-RateLimit-current');
  405. * $max = $digg->getLastResponse()->getHeader('X-RateLimit-max');
  406. * $reset = $digg->getLastResponse()->getHeader('X-RateLimit-reset');
  407. *
  408. * echo "I've used $current of my $max allowed requests. This rate limit period
  409. * resets in $reset seconds";
  410. * </code>
  411. *
  412. * @return HTTP_Request2_Response|null
  413. */
  414. public function getLastResponse()
  415. {
  416. return $this->lastResponse;
  417. }
  418. }
  419. ?>