PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/www/system/library/Zend/Service/Delicious.php

https://bitbucket.org/vmihailenco/zf-blog
PHP | 616 lines | 259 code | 92 blank | 265 comment | 41 complexity | 15f1d582db7e4aac8070ca4db015ef8f MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service
  17. * @subpackage Delicious
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Delicious.php 20096 2010-01-06 02:05:09Z bkarwin $
  21. */
  22. /**
  23. * @see Zend_Rest_Client
  24. */
  25. /**
  26. * @see Zend_Json_Decoder
  27. */
  28. /**
  29. * @see Zend_Service_Delicious_SimplePost
  30. */
  31. /**
  32. * @see Zend_Service_Delicious_Post
  33. */
  34. /**
  35. * @see Zend_Service_Delicious_PostList
  36. */
  37. /**
  38. * Zend_Service_Delicious is a concrete implementation of the del.icio.us web service
  39. *
  40. * @category Zend
  41. * @package Zend_Service
  42. * @subpackage Delicious
  43. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  44. * @license http://framework.zend.com/license/new-bsd New BSD License
  45. */
  46. class Zend_Service_Delicious
  47. {
  48. const API_URI = 'https://api.del.icio.us';
  49. const PATH_UPDATE = '/v1/posts/update';
  50. const PATH_TAGS = '/v1/tags/get';
  51. const PATH_TAG_RENAME = '/v1/tags/rename';
  52. const PATH_BUNDLES = '/v1/tags/bundles/all';
  53. const PATH_BUNDLE_DELETE = '/v1/tags/bundles/delete';
  54. const PATH_BUNDLE_ADD = '/v1/tags/bundles/set';
  55. const PATH_DATES = '/v1/posts/dates';
  56. const PATH_POST_DELETE = '/v1/posts/delete';
  57. const PATH_POSTS_GET = '/v1/posts/get';
  58. const PATH_POSTS_ALL = '/v1/posts/all';
  59. const PATH_POSTS_ADD = '/v1/posts/add';
  60. const PATH_POSTS_RECENT = '/v1/posts/recent';
  61. const JSON_URI = 'http://del.icio.us';
  62. const JSON_POSTS = '/feeds/json/%s/%s';
  63. const JSON_TAGS = '/feeds/json/tags/%s';
  64. const JSON_NETWORK = '/feeds/json/network/%s';
  65. const JSON_FANS = '/feeds/json/fans/%s';
  66. const JSON_URL = '/feeds/json/url/data';
  67. /**
  68. * Zend_Service_Rest instance
  69. *
  70. * @var Zend_Service_Rest
  71. */
  72. protected $_rest;
  73. /**
  74. * Username
  75. *
  76. * @var string
  77. */
  78. protected $_authUname;
  79. /**
  80. * Password
  81. *
  82. * @var string
  83. */
  84. protected $_authPass;
  85. /**
  86. * Microtime of last request
  87. *
  88. * @var float
  89. */
  90. protected static $_lastRequestTime = 0;
  91. /**
  92. * Constructs a new del.icio.us Web Services Client
  93. *
  94. * @param string $uname Client username
  95. * @param string $pass Client password
  96. * @return void
  97. */
  98. public function __construct($uname = null, $pass = null)
  99. {
  100. $this->_rest = new Zend_Rest_Client();
  101. $this->_rest->getHttpClient()->setConfig(array('ssltransport' => 'ssl'));
  102. $this->setAuth($uname, $pass);
  103. }
  104. /**
  105. * Set client username and password
  106. *
  107. * @param string $uname Client user name
  108. * @param string $pass Client password
  109. * @return Zend_Service_Delicious Provides a fluent interface
  110. */
  111. public function setAuth($uname, $pass)
  112. {
  113. $this->_authUname = $uname;
  114. $this->_authPass = $pass;
  115. return $this;
  116. }
  117. /**
  118. * Get time of the last update
  119. *
  120. * @throws Zend_Service_Delicious_Exception
  121. * @return Zend_Date
  122. */
  123. public function getLastUpdate()
  124. {
  125. $response = $this->makeRequest(self::PATH_UPDATE);
  126. $rootNode = $response->documentElement;
  127. if ($rootNode && $rootNode->nodeName == 'update') {
  128. /**
  129. * @todo replace strtotime() with Zend_Date equivalent
  130. */
  131. return new Zend_Date(strtotime($rootNode->getAttribute('time')));
  132. } else {
  133. /**
  134. * @see Zend_Service_Delicious_Exception
  135. */
  136. throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
  137. }
  138. }
  139. /**
  140. * Get all tags, returning an array with tags as keys and number of corresponding posts as values
  141. *
  142. * @return array list of tags
  143. */
  144. public function getTags()
  145. {
  146. $response = $this->makeRequest(self::PATH_TAGS);
  147. return self::_xmlResponseToArray($response, 'tags', 'tag', 'tag', 'count');
  148. }
  149. /**
  150. * Rename a tag
  151. *
  152. * @param string $old Old tag name
  153. * @param string $new New tag name
  154. * @return Zend_Service_Delicious Provides a fluent interface
  155. */
  156. public function renameTag($old, $new)
  157. {
  158. $response = $this->makeRequest(self::PATH_TAG_RENAME, array('old' => $old, 'new' => $new));
  159. self::_evalXmlResult($response);
  160. return $this;
  161. }
  162. /**
  163. * Get all bundles, returning an array with bundles as keys and array of tags as values
  164. *
  165. * @return array list of bundles
  166. */
  167. public function getBundles()
  168. {
  169. $response = $this->makeRequest(self::PATH_BUNDLES);
  170. $bundles = self::_xmlResponseToArray($response, 'bundles', 'bundle', 'name', 'tags');
  171. foreach ($bundles as &$tags) {
  172. $tags = explode(' ', $tags);
  173. }
  174. return $bundles;
  175. }
  176. /**
  177. * Adds a new bundle
  178. *
  179. * @param string $bundle Name of new bundle
  180. * @param array $tags Array of tags
  181. * @return Zend_Service_Delicious Provides a fluent interface
  182. */
  183. public function addBundle($bundle, array $tags)
  184. {
  185. $tags = implode(' ', (array) $tags);
  186. $response = $this->makeRequest(self::PATH_BUNDLE_ADD, array('bundle' => $bundle, 'tags' => $tags));
  187. self::_evalXmlResult($response);
  188. return $this;
  189. }
  190. /**
  191. * Delete a bundle
  192. *
  193. * @param string $bundle Name of bundle to be deleted
  194. * @return Zend_Service_Delicious Provides a fluent interface
  195. */
  196. public function deleteBundle($bundle)
  197. {
  198. $response = $this->makeRequest(self::PATH_BUNDLE_DELETE, array('bundle' => $bundle));
  199. self::_evalXmlResult($response);
  200. return $this;
  201. }
  202. /**
  203. * Delete a post
  204. *
  205. * @param string $url URL of post to be deleted
  206. * @return Zend_Service_Delicious Provides a fluent interface
  207. */
  208. public function deletePost($url)
  209. {
  210. $response = $this->makeRequest(self::PATH_POST_DELETE, array('url' => $url));
  211. self::_evalXmlResult($response);
  212. return $this;
  213. }
  214. /**
  215. * Get number of posts by date
  216. *
  217. * Returns array where keys are dates and values are numbers of posts
  218. *
  219. * @param string $tag Optional filtering by tag
  220. * @return array list of dates
  221. */
  222. public function getDates($tag = null)
  223. {
  224. $parms = array();
  225. if ($tag) {
  226. $parms['tag'] = $tag;
  227. }
  228. $response = $this->makeRequest(self::PATH_DATES, $parms);
  229. return self::_xmlResponseToArray($response, 'dates', 'date', 'date', 'count');
  230. }
  231. /**
  232. * Get posts matching the arguments
  233. *
  234. * If no date or url is given, most recent date will be used
  235. *
  236. * @param string $tag Optional filtering by tag
  237. * @param Zend_Date $dt Optional filtering by date
  238. * @param string $url Optional filtering by url
  239. * @throws Zend_Service_Delicious_Exception
  240. * @return Zend_Service_Delicious_PostList
  241. */
  242. public function getPosts($tag = null, Zend_Date $dt = null, $url = null)
  243. {
  244. $parms = array();
  245. if ($tag) {
  246. $parms['tag'] = $tag;
  247. }
  248. if ($url) {
  249. $parms['url'] = $url;
  250. }
  251. if ($dt) {
  252. $parms['dt'] = $dt->get('Y-m-d\TH:i:s\Z');
  253. }
  254. $response = $this->makeRequest(self::PATH_POSTS_GET, $parms);
  255. return $this->_parseXmlPostList($response);
  256. }
  257. /**
  258. * Get all posts
  259. *
  260. * @param string $tag Optional filtering by tag
  261. * @return Zend_Service_Delicious_PostList
  262. */
  263. public function getAllPosts($tag = null)
  264. {
  265. $parms = array();
  266. if ($tag) {
  267. $parms['tag'] = $tag;
  268. }
  269. $response = $this->makeRequest(self::PATH_POSTS_ALL, $parms);
  270. return $this->_parseXmlPostList($response);
  271. }
  272. /**
  273. * Get recent posts
  274. *
  275. * @param string $tag Optional filtering by tag
  276. * @param string $count Maximum number of posts to be returned (default 15)
  277. * @return Zend_Service_Delicious_PostList
  278. */
  279. public function getRecentPosts($tag = null, $count = 15)
  280. {
  281. $parms = array();
  282. if ($tag) {
  283. $parms['tag'] = $tag;
  284. }
  285. if ($count) {
  286. $parms['count'] = $count;
  287. }
  288. $response = $this->makeRequest(self::PATH_POSTS_RECENT, $parms);
  289. return $this->_parseXmlPostList($response);
  290. }
  291. /**
  292. * Create new post
  293. *
  294. * @return Zend_Service_Delicious_Post
  295. */
  296. public function createNewPost($title, $url)
  297. {
  298. return new Zend_Service_Delicious_Post($this, array('title' => $title, 'url' => $url));
  299. }
  300. /**
  301. * Get posts of a user
  302. *
  303. * @param string $user Owner of the posts
  304. * @param int $count Number of posts (default 15, max. 100)
  305. * @param string $tag Optional filtering by tag
  306. * @return Zend_Service_Delicious_PostList
  307. */
  308. public function getUserPosts($user, $count = null, $tag = null)
  309. {
  310. $parms = array();
  311. if ($count) {
  312. $parms['count'] = $count;
  313. }
  314. $path = sprintf(self::JSON_POSTS, $user, $tag);
  315. $res = $this->makeRequest($path, $parms, 'json');
  316. return new Zend_Service_Delicious_PostList($this, $res);
  317. }
  318. /**
  319. * Get tags of a user
  320. *
  321. * Returned array has tags as keys and number of posts as values
  322. *
  323. * @param string $user Owner of the posts
  324. * @param int $atleast Include only tags for which there are at least ### number of posts
  325. * @param int $count Number of tags to get (default all)
  326. * @param string $sort Order of returned tags ('alpha' || 'count')
  327. * @return array
  328. */
  329. public function getUserTags($user, $atleast = null, $count = null, $sort = 'alpha')
  330. {
  331. $parms = array();
  332. if ($atleast) {
  333. $parms['atleast'] = $atleast;
  334. }
  335. if ($count) {
  336. $parms['count'] = $count;
  337. }
  338. if ($sort) {
  339. $parms['sort'] = $sort;
  340. }
  341. $path = sprintf(self::JSON_TAGS, $user);
  342. return $this->makeRequest($path, $parms, 'json');
  343. }
  344. /**
  345. * Get network of a user
  346. *
  347. * @param string $user Owner of the network
  348. * @return array
  349. */
  350. public function getUserNetwork($user)
  351. {
  352. $path = sprintf(self::JSON_NETWORK, $user);
  353. return $this->makeRequest($path, array(), 'json');
  354. }
  355. /**
  356. * Get fans of a user
  357. *
  358. * @param string $user Owner of the fans
  359. * @return array
  360. */
  361. public function getUserFans($user)
  362. {
  363. $path = sprintf(self::JSON_FANS, $user);
  364. return $this->makeRequest($path, array(), 'json');
  365. }
  366. /**
  367. * Get details on a particular bookmarked URL
  368. *
  369. * Returned array contains four elements:
  370. * - hash - md5 hash of URL
  371. * - top_tags - array of tags and their respective usage counts
  372. * - url - URL for which details were returned
  373. * - total_posts - number of users that have bookmarked URL
  374. *
  375. * If URL hasen't been bookmarked null is returned.
  376. *
  377. * @param string $url URL for which to get details
  378. * @return array
  379. */
  380. public function getUrlDetails($url)
  381. {
  382. $parms = array('hash' => md5($url));
  383. $res = $this->makeRequest(self::JSON_URL, $parms, 'json');
  384. if(isset($res[0])) {
  385. return $res[0];
  386. } else {
  387. return null;
  388. }
  389. }
  390. /**
  391. * Handles all GET requests to a web service
  392. *
  393. * @param string $path Path
  394. * @param array $parms Array of GET parameters
  395. * @param string $type Type of a request ("xml"|"json")
  396. * @return mixed decoded response from web service
  397. * @throws Zend_Service_Delicious_Exception
  398. */
  399. public function makeRequest($path, array $parms = array(), $type = 'xml')
  400. {
  401. // if previous request was made less then 1 sec ago
  402. // wait until we can make a new request
  403. $timeDiff = microtime(true) - self::$_lastRequestTime;
  404. if ($timeDiff < 1) {
  405. usleep((1 - $timeDiff) * 1000000);
  406. }
  407. $this->_rest->getHttpClient()->setAuth($this->_authUname, $this->_authPass);
  408. switch ($type) {
  409. case 'xml':
  410. $this->_rest->setUri(self::API_URI);
  411. break;
  412. case 'json':
  413. $parms['raw'] = true;
  414. $this->_rest->setUri(self::JSON_URI);
  415. break;
  416. default:
  417. /**
  418. * @see Zend_Service_Delicious_Exception
  419. */
  420. throw new Zend_Service_Delicious_Exception('Unknown request type');
  421. }
  422. self::$_lastRequestTime = microtime(true);
  423. $response = $this->_rest->restGet($path, $parms);
  424. if (!$response->isSuccessful()) {
  425. /**
  426. * @see Zend_Service_Delicious_Exception
  427. */
  428. throw new Zend_Service_Delicious_Exception("Http client reported an error: '{$response->getMessage()}'");
  429. }
  430. $responseBody = $response->getBody();
  431. switch ($type) {
  432. case 'xml':
  433. $dom = new DOMDocument() ;
  434. if (!@$dom->loadXML($responseBody)) {
  435. /**
  436. * @see Zend_Service_Delicious_Exception
  437. */
  438. throw new Zend_Service_Delicious_Exception('XML Error');
  439. }
  440. return $dom;
  441. case 'json':
  442. return Zend_Json_Decoder::decode($responseBody);
  443. }
  444. }
  445. /**
  446. * Transform XML string to array
  447. *
  448. * @param DOMDocument $response
  449. * @param string $root Name of root tag
  450. * @param string $child Name of children tags
  451. * @param string $attKey Attribute of child tag to be used as a key
  452. * @param string $attValue Attribute of child tag to be used as a value
  453. * @return array
  454. * @throws Zend_Service_Delicious_Exception
  455. */
  456. private static function _xmlResponseToArray(DOMDocument $response, $root, $child, $attKey, $attValue)
  457. {
  458. $rootNode = $response->documentElement;
  459. $arrOut = array();
  460. if ($rootNode->nodeName == $root) {
  461. $childNodes = $rootNode->childNodes;
  462. for ($i = 0; $i < $childNodes->length; $i++) {
  463. $currentNode = $childNodes->item($i);
  464. if ($currentNode->nodeName == $child) {
  465. $arrOut[$currentNode->getAttribute($attKey)] = $currentNode->getAttribute($attValue);
  466. }
  467. }
  468. } else {
  469. /**
  470. * @see Zend_Service_Delicious_Exception
  471. */
  472. throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
  473. }
  474. return $arrOut;
  475. }
  476. /**
  477. * Constructs Zend_Service_Delicious_PostList from XML response
  478. *
  479. * @param DOMDocument $response
  480. * @return Zend_Service_Delicious_PostList
  481. * @throws Zend_Service_Delicious_Exception
  482. */
  483. private function _parseXmlPostList(DOMDocument $response)
  484. {
  485. $rootNode = $response->documentElement;
  486. if ($rootNode->nodeName == 'posts') {
  487. return new Zend_Service_Delicious_PostList($this, $rootNode->childNodes);
  488. } else {
  489. /**
  490. * @see Zend_Service_Delicious_Exception
  491. */
  492. throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
  493. }
  494. }
  495. /**
  496. * Evaluates XML response
  497. *
  498. * @param DOMDocument $response
  499. * @return void
  500. * @throws Zend_Service_Delicious_Exception
  501. */
  502. private static function _evalXmlResult(DOMDocument $response)
  503. {
  504. $rootNode = $response->documentElement;
  505. if ($rootNode && $rootNode->nodeName == 'result') {
  506. if ($rootNode->hasAttribute('code')) {
  507. $strResponse = $rootNode->getAttribute('code');
  508. } else {
  509. $strResponse = $rootNode->nodeValue;
  510. }
  511. if ($strResponse != 'done' && $strResponse != 'ok') {
  512. /**
  513. * @see Zend_Service_Delicious_Exception
  514. */
  515. throw new Zend_Service_Delicious_Exception("del.icio.us web service: '{$strResponse}'");
  516. }
  517. } else {
  518. /**
  519. * @see Zend_Service_Delicious_Exception
  520. */
  521. throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
  522. }
  523. }
  524. }