Twitter.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  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 Twitter
  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$
  21. */
  22. /**
  23. * @see Zend_Rest_Client
  24. */
  25. require_once 'Zend/Rest/Client.php';
  26. /**
  27. * @see Zend_Rest_Client_Result
  28. */
  29. require_once 'Zend/Rest/Client/Result.php';
  30. /**
  31. * @category Zend
  32. * @package Zend_Service
  33. * @subpackage Twitter
  34. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. class Zend_Service_Twitter extends Zend_Rest_Client
  38. {
  39. /**
  40. * 246 is the current limit for a status message, 140 characters are displayed
  41. * initially, with the remainder linked from the web UI or client. The limit is
  42. * applied to a html encoded UTF-8 string (i.e. entities are counted in the limit
  43. * which may appear unusual but is a security measure).
  44. *
  45. * This should be reviewed in the future...
  46. */
  47. const STATUS_MAX_CHARACTERS = 246;
  48. /**
  49. * Whether or not authorization has been initialized for the current user.
  50. * @var bool
  51. */
  52. protected $_authInitialized = false;
  53. /**
  54. * @var Zend_Http_CookieJar
  55. */
  56. protected $_cookieJar;
  57. /**
  58. * Date format for 'since' strings
  59. * @var string
  60. */
  61. protected $_dateFormat = 'D, d M Y H:i:s T';
  62. /**
  63. * Username
  64. * @var string
  65. */
  66. protected $_username;
  67. /**
  68. * Password
  69. * @var string
  70. */
  71. protected $_password;
  72. /**
  73. * Current method type (for method proxying)
  74. * @var string
  75. */
  76. protected $_methodType;
  77. /**
  78. * Types of API methods
  79. * @var array
  80. */
  81. protected $_methodTypes = array('status', 'user', 'directMessage', 'friendship', 'account', 'favorite', 'block');
  82. /**
  83. * Local HTTP Client cloned from statically set client
  84. * @var Zend_Http_Client
  85. */
  86. protected $_localHttpClient = null;
  87. /**
  88. * Constructor
  89. *
  90. * @param string $username
  91. * @param string $password
  92. * @return void
  93. */
  94. public function __construct($username = null, $password = null)
  95. {
  96. $this->setLocalHttpClient(clone self::getHttpClient());
  97. if (is_array($username) && is_null($password)) {
  98. if (isset($username['username']) && isset($username['password'])) {
  99. $this->setUsername($username['username']);
  100. $this->setPassword($username['password']);
  101. } elseif (isset($username[0]) && isset($username[1])) {
  102. $this->setUsername($username[0]);
  103. $this->setPassword($username[1]);
  104. }
  105. } else if (!is_null($username)) {
  106. $this->setUsername($username);
  107. $this->setPassword($password);
  108. }
  109. $this->setUri('http://twitter.com');
  110. $this->_localHttpClient->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
  111. }
  112. /**
  113. * Set local HTTP client as distinct from the static HTTP client
  114. * as inherited from Zend_Rest_Client.
  115. *
  116. * @param Zend_Http_Client $client
  117. * @return self
  118. */
  119. public function setLocalHttpClient(Zend_Http_Client $client)
  120. {
  121. $this->_localHttpClient = $client;
  122. return $this;
  123. }
  124. public function getLocalHttpClient()
  125. {
  126. return $this->_localHttpClient;
  127. }
  128. /**
  129. * Retrieve username
  130. *
  131. * @return string
  132. */
  133. public function getUsername()
  134. {
  135. return $this->_username;
  136. }
  137. /**
  138. * Set username
  139. *
  140. * @param string $value
  141. * @return Zend_Service_Twitter
  142. */
  143. public function setUsername($value)
  144. {
  145. $this->_username = $value;
  146. $this->_authInitialized = false;
  147. return $this;
  148. }
  149. /**
  150. * Retrieve password
  151. *
  152. * @return string
  153. */
  154. public function getPassword()
  155. {
  156. return $this->_password;
  157. }
  158. /**
  159. * Set password
  160. *
  161. * @param string $value
  162. * @return Zend_Service_Twitter
  163. */
  164. public function setPassword($value)
  165. {
  166. $this->_password = $value;
  167. $this->_authInitialized = false;
  168. return $this;
  169. }
  170. /**
  171. * Proxy service methods
  172. *
  173. * @param string $type
  174. * @return Zend_Service_Twitter
  175. * @throws Zend_Service_Twitter_Exception if method is not in method types list
  176. */
  177. public function __get($type)
  178. {
  179. if (!in_array($type, $this->_methodTypes)) {
  180. include_once 'Zend/Service/Twitter/Exception.php';
  181. throw new Zend_Service_Twitter_Exception('Invalid method type "' . $type . '"');
  182. }
  183. $this->_methodType = $type;
  184. return $this;
  185. }
  186. /**
  187. * Method overloading
  188. *
  189. * @param string $method
  190. * @param array $params
  191. * @return mixed
  192. * @throws Zend_Service_Twitter_Exception if unable to find method
  193. */
  194. public function __call($method, $params)
  195. {
  196. if (empty($this->_methodType)) {
  197. include_once 'Zend/Service/Twitter/Exception.php';
  198. throw new Zend_Service_Twitter_Exception('Invalid method "' . $method . '"');
  199. }
  200. $test = $this->_methodType . ucfirst($method);
  201. if (!method_exists($this, $test)) {
  202. include_once 'Zend/Service/Twitter/Exception.php';
  203. throw new Zend_Service_Twitter_Exception('Invalid method "' . $test . '"');
  204. }
  205. return call_user_func_array(array($this, $test), $params);
  206. }
  207. /**
  208. * Initialize HTTP authentication
  209. *
  210. * @return void
  211. */
  212. protected function _init()
  213. {
  214. $client = $this->_localHttpClient;
  215. $client->resetParameters();
  216. if (null == $this->_cookieJar) {
  217. $client->setCookieJar();
  218. $this->_cookieJar = $client->getCookieJar();
  219. } else {
  220. $client->setCookieJar($this->_cookieJar);
  221. }
  222. if (!$this->_authInitialized && $this->getUsername() !== null) {
  223. $client->setAuth($this->getUsername(), $this->getPassword());
  224. $this->_authInitialized = true;
  225. }
  226. }
  227. /**
  228. * Set date header
  229. *
  230. * @param int|string $value
  231. * @deprecated Not supported by Twitter since April 08, 2009
  232. * @return void
  233. */
  234. protected function _setDate($value)
  235. {
  236. if (is_int($value)) {
  237. $date = date($this->_dateFormat, $value);
  238. } else {
  239. $date = date($this->_dateFormat, strtotime($value));
  240. }
  241. $this->_localHttpClient->setHeaders('If-Modified-Since', $date);
  242. }
  243. /**
  244. * Public Timeline status
  245. *
  246. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  247. * @return Zend_Rest_Client_Result
  248. */
  249. public function statusPublicTimeline()
  250. {
  251. $this->_init();
  252. $path = '/statuses/public_timeline.xml';
  253. $response = $this->_get($path);
  254. return new Zend_Rest_Client_Result($response->getBody());
  255. }
  256. /**
  257. * Friend Timeline Status
  258. *
  259. * $params may include one or more of the following keys
  260. * - id: ID of a friend whose timeline you wish to receive
  261. * - count: how many statuses to return
  262. * - since_id: return results only after the specific tweet
  263. * - page: return page X of results
  264. *
  265. * @param array $params
  266. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  267. * @return void
  268. */
  269. public function statusFriendsTimeline(array $params = array())
  270. {
  271. $this->_init();
  272. $path = '/statuses/friends_timeline';
  273. $_params = array();
  274. foreach ($params as $key => $value) {
  275. switch (strtolower($key)) {
  276. case 'count':
  277. $count = (int) $value;
  278. if (0 >= $count) {
  279. $count = 1;
  280. } elseif (200 < $count) {
  281. $count = 200;
  282. }
  283. $_params['count'] = (int) $count;
  284. break;
  285. case 'since_id':
  286. $_params['since_id'] = $this->_validInteger($value);
  287. break;
  288. case 'page':
  289. $_params['page'] = (int) $value;
  290. break;
  291. default:
  292. break;
  293. }
  294. }
  295. $path .= '.xml';
  296. $response = $this->_get($path, $_params);
  297. return new Zend_Rest_Client_Result($response->getBody());
  298. }
  299. /**
  300. * User Timeline status
  301. *
  302. * $params may include one or more of the following keys
  303. * - id: ID of a friend whose timeline you wish to receive
  304. * - since_id: return results only after the tweet id specified
  305. * - page: return page X of results
  306. * - count: how many statuses to return
  307. * - max_id: returns only statuses with an ID less than or equal to the specified ID
  308. * - user_id: specfies the ID of the user for whom to return the user_timeline
  309. * - screen_name: specfies the screen name of the user for whom to return the user_timeline
  310. *
  311. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  312. * @return Zend_Rest_Client_Result
  313. */
  314. public function statusUserTimeline(array $params = array())
  315. {
  316. $this->_init();
  317. $path = '/statuses/user_timeline';
  318. $_params = array();
  319. foreach ($params as $key => $value) {
  320. switch (strtolower($key)) {
  321. case 'id':
  322. $path .= '/' . $value;
  323. break;
  324. case 'page':
  325. $_params['page'] = (int) $value;
  326. break;
  327. case 'count':
  328. $count = (int) $value;
  329. if (0 >= $count) {
  330. $count = 1;
  331. } elseif (200 < $count) {
  332. $count = 200;
  333. }
  334. $_params['count'] = $count;
  335. break;
  336. case 'user_id':
  337. $_params['user_id'] = $this->_validInteger($value);
  338. break;
  339. case 'screen_name':
  340. $_params['screen_name'] = $this->_validateScreenName($value);
  341. break;
  342. case 'since_id':
  343. $_params['since_id'] = $this->_validInteger($value);
  344. break;
  345. case 'max_id':
  346. $_params['max_id'] = $this->_validInteger($value);
  347. break;
  348. default:
  349. break;
  350. }
  351. }
  352. $path .= '.xml';
  353. $response = $this->_get($path, $_params);
  354. return new Zend_Rest_Client_Result($response->getBody());
  355. }
  356. /**
  357. * Show a single status
  358. *
  359. * @param int $id Id of status to show
  360. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  361. * @return Zend_Rest_Client_Result
  362. */
  363. public function statusShow($id)
  364. {
  365. $this->_init();
  366. $path = '/statuses/show/' . $this->_validInteger($id) . '.xml';
  367. $response = $this->_get($path);
  368. return new Zend_Rest_Client_Result($response->getBody());
  369. }
  370. /**
  371. * Update user's current status
  372. *
  373. * @param string $status
  374. * @param int $in_reply_to_status_id
  375. * @return Zend_Rest_Client_Result
  376. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  377. * @throws Zend_Service_Twitter_Exception if message is too short or too long
  378. */
  379. public function statusUpdate($status, $inReplyToStatusId = null)
  380. {
  381. $this->_init();
  382. $path = '/statuses/update.xml';
  383. $len = iconv_strlen(htmlspecialchars($status, ENT_QUOTES, 'UTF-8'), 'UTF-8');
  384. if ($len > self::STATUS_MAX_CHARACTERS) {
  385. include_once 'Zend/Service/Twitter/Exception.php';
  386. throw new Zend_Service_Twitter_Exception('Status must be no more than ' . self::STATUS_MAX_CHARACTERS . ' characters in length');
  387. } elseif (0 == $len) {
  388. include_once 'Zend/Service/Twitter/Exception.php';
  389. throw new Zend_Service_Twitter_Exception('Status must contain at least one character');
  390. }
  391. $data = array('status' => $status);
  392. if (is_numeric($inReplyToStatusId) && !empty($inReplyToStatusId)) {
  393. $data['in_reply_to_status_id'] = $inReplyToStatusId;
  394. }
  395. //$this->status = $status;
  396. $response = $this->_post($path, $data);
  397. return new Zend_Rest_Client_Result($response->getBody());
  398. }
  399. /**
  400. * Get status replies
  401. *
  402. * $params may include one or more of the following keys
  403. * - since_id: return results only after the specified tweet id
  404. * - page: return page X of results
  405. *
  406. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  407. * @return Zend_Rest_Client_Result
  408. */
  409. public function statusReplies(array $params = array())
  410. {
  411. $this->_init();
  412. $path = '/statuses/replies.xml';
  413. $_params = array();
  414. foreach ($params as $key => $value) {
  415. switch (strtolower($key)) {
  416. case 'since_id':
  417. $_params['since_id'] = $this->_validInteger($value);
  418. break;
  419. case 'page':
  420. $_params['page'] = (int) $value;
  421. break;
  422. default:
  423. break;
  424. }
  425. }
  426. $response = $this->_get($path, $_params);
  427. return new Zend_Rest_Client_Result($response->getBody());
  428. }
  429. /**
  430. * Destroy a status message
  431. *
  432. * @param int $id ID of status to destroy
  433. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  434. * @return Zend_Rest_Client_Result
  435. */
  436. public function statusDestroy($id)
  437. {
  438. $this->_init();
  439. $path = '/statuses/destroy/' . $this->_validInteger($id) . '.xml';
  440. $response = $this->_post($path);
  441. return new Zend_Rest_Client_Result($response->getBody());
  442. }
  443. /**
  444. * User friends
  445. *
  446. * @param int|string $id Id or username of user for whom to fetch friends
  447. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  448. * @return Zend_Rest_Client_Result
  449. */
  450. public function userFriends(array $params = array())
  451. {
  452. $this->_init();
  453. $path = '/statuses/friends';
  454. $_params = array();
  455. foreach ($params as $key => $value) {
  456. switch (strtolower($key)) {
  457. case 'id':
  458. $path .= '/' . $value;
  459. break;
  460. case 'page':
  461. $_params['page'] = (int) $value;
  462. break;
  463. default:
  464. break;
  465. }
  466. }
  467. $path .= '.xml';
  468. $response = $this->_get($path, $_params);
  469. return new Zend_Rest_Client_Result($response->getBody());
  470. }
  471. /**
  472. * User Followers
  473. *
  474. * @param bool $lite If true, prevents inline inclusion of current status for followers; defaults to false
  475. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  476. * @return Zend_Rest_Client_Result
  477. */
  478. public function userFollowers($lite = false)
  479. {
  480. $this->_init();
  481. $path = '/statuses/followers.xml';
  482. if ($lite) {
  483. $this->lite = 'true';
  484. }
  485. $response = $this->_get($path);
  486. return new Zend_Rest_Client_Result($response->getBody());
  487. }
  488. /**
  489. * Get featured users
  490. *
  491. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  492. * @return Zend_Rest_Client_Result
  493. */
  494. public function userFeatured()
  495. {
  496. $this->_init();
  497. $path = '/statuses/featured.xml';
  498. $response = $this->_get($path);
  499. return new Zend_Rest_Client_Result($response->getBody());
  500. }
  501. /**
  502. * Show extended information on a user
  503. *
  504. * @param int|string $id User ID or name
  505. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  506. * @return Zend_Rest_Client_Result
  507. */
  508. public function userShow($id)
  509. {
  510. $this->_init();
  511. $path = '/users/show/' . $id . '.xml';
  512. $response = $this->_get($path);
  513. return new Zend_Rest_Client_Result($response->getBody());
  514. }
  515. /**
  516. * Retrieve direct messages for the current user
  517. *
  518. * $params may include one or more of the following keys
  519. * - since_id: return statuses only greater than the one specified
  520. * - page: return page X of results
  521. *
  522. * @param array $params
  523. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  524. * @return Zend_Rest_Client_Result
  525. */
  526. public function directMessageMessages(array $params = array())
  527. {
  528. $this->_init();
  529. $path = '/direct_messages.xml';
  530. $_params = array();
  531. foreach ($params as $key => $value) {
  532. switch (strtolower($key)) {
  533. case 'since_id':
  534. $_params['since_id'] = $this->_validInteger($value);
  535. break;
  536. case 'page':
  537. $_params['page'] = (int) $value;
  538. break;
  539. default:
  540. break;
  541. }
  542. }
  543. $response = $this->_get($path, $_params);
  544. return new Zend_Rest_Client_Result($response->getBody());
  545. }
  546. /**
  547. * Retrieve list of direct messages sent by current user
  548. *
  549. * $params may include one or more of the following keys
  550. * - since_id: return statuses only greater than the one specified
  551. * - page: return page X of results
  552. *
  553. * @param array $params
  554. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  555. * @return Zend_Rest_Client_Result
  556. */
  557. public function directMessageSent(array $params = array())
  558. {
  559. $this->_init();
  560. $path = '/direct_messages/sent.xml';
  561. $_params = array();
  562. foreach ($params as $key => $value) {
  563. switch (strtolower($key)) {
  564. case 'since_id':
  565. $_params['since_id'] = $this->_validInteger($value);
  566. break;
  567. case 'page':
  568. $_params['page'] = (int) $value;
  569. break;
  570. default:
  571. break;
  572. }
  573. }
  574. $response = $this->_get($path, $_params);
  575. return new Zend_Rest_Client_Result($response->getBody());
  576. }
  577. /**
  578. * Send a direct message to a user
  579. *
  580. * @param int|string $user User to whom to send message
  581. * @param string $text Message to send to user
  582. * @return Zend_Rest_Client_Result
  583. * @throws Zend_Service_Twitter_Exception if message is too short or too long
  584. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  585. */
  586. public function directMessageNew($user, $text)
  587. {
  588. $this->_init();
  589. $path = '/direct_messages/new.xml';
  590. $len = iconv_strlen($text, 'UTF-8');
  591. if (0 == $len) {
  592. throw new Zend_Service_Twitter_Exception('Direct message must contain at least one character');
  593. } elseif (140 < $len) {
  594. throw new Zend_Service_Twitter_Exception('Direct message must contain no more than 140 characters');
  595. }
  596. $data = array('user' => $user, 'text' => $text);
  597. $response = $this->_post($path, $data);
  598. return new Zend_Rest_Client_Result($response->getBody());
  599. }
  600. /**
  601. * Destroy a direct message
  602. *
  603. * @param int $id ID of message to destroy
  604. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  605. * @return Zend_Rest_Client_Result
  606. */
  607. public function directMessageDestroy($id)
  608. {
  609. $this->_init();
  610. $path = '/direct_messages/destroy/' . $this->_validInteger($id) . '.xml';
  611. $response = $this->_post($path);
  612. return new Zend_Rest_Client_Result($response->getBody());
  613. }
  614. /**
  615. * Create friendship
  616. *
  617. * @param int|string $id User ID or name of new friend
  618. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  619. * @return Zend_Rest_Client_Result
  620. */
  621. public function friendshipCreate($id)
  622. {
  623. $this->_init();
  624. $path = '/friendships/create/' . $id . '.xml';
  625. $response = $this->_post($path);
  626. return new Zend_Rest_Client_Result($response->getBody());
  627. }
  628. /**
  629. * Destroy friendship
  630. *
  631. * @param int|string $id User ID or name of friend to remove
  632. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  633. * @return Zend_Rest_Client_Result
  634. */
  635. public function friendshipDestroy($id)
  636. {
  637. $this->_init();
  638. $path = '/friendships/destroy/' . $id . '.xml';
  639. $response = $this->_post($path);
  640. return new Zend_Rest_Client_Result($response->getBody());
  641. }
  642. /**
  643. * Friendship exists
  644. *
  645. * @param int|string $id User ID or name of friend to see if they are your friend
  646. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  647. * @return Zend_Rest_Client_result
  648. */
  649. public function friendshipExists($id)
  650. {
  651. $this->_init();
  652. $path = '/friendships/exists.xml';
  653. $data = array('user_a' => $this->getUsername(), 'user_b' => $id);
  654. $response = $this->_get($path, $data);
  655. return new Zend_Rest_Client_Result($response->getBody());
  656. }
  657. /**
  658. * Verify Account Credentials
  659. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  660. *
  661. * @return Zend_Rest_Client_Result
  662. */
  663. public function accountVerifyCredentials()
  664. {
  665. $this->_init();
  666. $response = $this->_get('/account/verify_credentials.xml');
  667. return new Zend_Rest_Client_Result($response->getBody());
  668. }
  669. /**
  670. * End current session
  671. *
  672. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  673. * @return true
  674. */
  675. public function accountEndSession()
  676. {
  677. $this->_init();
  678. $this->_get('/account/end_session');
  679. return true;
  680. }
  681. /**
  682. * Returns the number of api requests you have left per hour.
  683. *
  684. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  685. * @return Zend_Rest_Client_Result
  686. */
  687. public function accountRateLimitStatus()
  688. {
  689. $this->_init();
  690. $response = $this->_get('/account/rate_limit_status.xml');
  691. return new Zend_Rest_Client_Result($response->getBody());
  692. }
  693. /**
  694. * Fetch favorites
  695. *
  696. * $params may contain one or more of the following:
  697. * - 'id': Id of a user for whom to fetch favorites
  698. * - 'page': Retrieve a different page of resuls
  699. *
  700. * @param array $params
  701. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  702. * @return Zend_Rest_Client_Result
  703. */
  704. public function favoriteFavorites(array $params = array())
  705. {
  706. $this->_init();
  707. $path = '/favorites';
  708. $_params = array();
  709. foreach ($params as $key => $value) {
  710. switch (strtolower($key)) {
  711. case 'id':
  712. $path .= '/' . $this->_validInteger($value);
  713. break;
  714. case 'page':
  715. $_params['page'] = (int) $value;
  716. break;
  717. default:
  718. break;
  719. }
  720. }
  721. $path .= '.xml';
  722. $response = $this->_get($path, $_params);
  723. return new Zend_Rest_Client_Result($response->getBody());
  724. }
  725. /**
  726. * Mark a status as a favorite
  727. *
  728. * @param int $id Status ID you want to mark as a favorite
  729. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  730. * @return Zend_Rest_Client_Result
  731. */
  732. public function favoriteCreate($id)
  733. {
  734. $this->_init();
  735. $path = '/favorites/create/' . $this->_validInteger($id) . '.xml';
  736. $response = $this->_post($path);
  737. return new Zend_Rest_Client_Result($response->getBody());
  738. }
  739. /**
  740. * Remove a favorite
  741. *
  742. * @param int $id Status ID you want to de-list as a favorite
  743. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  744. * @return Zend_Rest_Client_Result
  745. */
  746. public function favoriteDestroy($id)
  747. {
  748. $this->_init();
  749. $path = '/favorites/destroy/' . $this->_validInteger($id) . '.xml';
  750. $response = $this->_post($path);
  751. return new Zend_Rest_Client_Result($response->getBody());
  752. }
  753. /**
  754. * Blocks the user specified in the ID parameter as the authenticating user.
  755. * Destroys a friendship to the blocked user if it exists.
  756. *
  757. * @param integer|string $id The ID or screen name of a user to block.
  758. * @return Zend_Rest_Client_Result
  759. */
  760. public function blockCreate($id)
  761. {
  762. $this->_init();
  763. $path = '/blocks/create/' . $id . '.xml';
  764. $response = $this->_post($path);
  765. return new Zend_Rest_Client_Result($response->getBody());
  766. }
  767. /**
  768. * Un-blocks the user specified in the ID parameter for the authenticating user
  769. *
  770. * @param integer|string $id The ID or screen_name of the user to un-block.
  771. * @return Zend_Rest_Client_Result
  772. */
  773. public function blockDestroy($id)
  774. {
  775. $this->_init();
  776. $path = '/blocks/destroy/' . $id . '.xml';
  777. $response = $this->_post($path);
  778. return new Zend_Rest_Client_Result($response->getBody());
  779. }
  780. /**
  781. * Returns if the authenticating user is blocking a target user.
  782. *
  783. * @param string|integer $id The ID or screen_name of the potentially blocked user.
  784. * @param boolean $returnResult Instead of returning a boolean return the rest response from twitter
  785. * @return Boolean|Zend_Rest_Client_Result
  786. */
  787. public function blockExists($id, $returnResult = false)
  788. {
  789. $this->_init();
  790. $path = '/blocks/exists/' . $id . '.xml';
  791. $response = $this->_get($path);
  792. $cr = new Zend_Rest_Client_Result($response->getBody());
  793. if ($returnResult === true)
  794. return $cr;
  795. if (!empty($cr->request)) {
  796. return false;
  797. }
  798. return true;
  799. }
  800. /**
  801. * Returns an array of user objects that the authenticating user is blocking
  802. *
  803. * @param integer $page Optional. Specifies the page number of the results beginning at 1. A single page contains 20 ids.
  804. * @param boolean $returnUserIds Optional. Returns only the userid's instead of the whole user object
  805. * @return Zend_Rest_Client_Result
  806. */
  807. public function blockBlocking($page = 1, $returnUserIds = false)
  808. {
  809. $this->_init();
  810. $path = '/blocks/blocking';
  811. if ($returnUserIds === true) {
  812. $path .= '/ids';
  813. }
  814. $path .= '.xml';
  815. $response = $this->_get($path, array('page' => $page));
  816. return new Zend_Rest_Client_Result($response->getBody());
  817. }
  818. /**
  819. * Protected function to validate that the integer is valid or return a 0
  820. * @param $int
  821. * @throws Zend_Http_Client_Exception if HTTP request fails or times out
  822. * @return integer
  823. */
  824. protected function _validInteger($int)
  825. {
  826. if (preg_match("/(\d+)/", $int)) {
  827. return $int;
  828. }
  829. return 0;
  830. }
  831. /**
  832. * Validate a screen name using Twitter rules
  833. *
  834. * @param string $name
  835. * @throws Zend_Service_Twitter_Exception
  836. * @return string
  837. */
  838. protected function _validateScreenName($name)
  839. {
  840. if (!preg_match('/^[a-zA-Z0-9_]{0,20}$/', $name)) {
  841. require_once 'Zend/Service/Twitter/Exception.php';
  842. throw new Zend_Service_Twitter_Exception('Screen name, "' . $name . '" should only contain alphanumeric characters and' . ' underscores, and not exceed 15 characters.');
  843. }
  844. return $name;
  845. }
  846. /**
  847. * Call a remote REST web service URI and return the Zend_Http_Response object
  848. *
  849. * @param string $path The path to append to the URI
  850. * @throws Zend_Rest_Client_Exception
  851. * @return void
  852. */
  853. protected function _prepare($path)
  854. {
  855. // Get the URI object and configure it
  856. if (!$this->_uri instanceof Zend_Uri_Http) {
  857. require_once 'Zend/Rest/Client/Exception.php';
  858. throw new Zend_Rest_Client_Exception('URI object must be set before performing call');
  859. }
  860. $uri = $this->_uri->getUri();
  861. if ($path[0] != '/' && $uri[strlen($uri) - 1] != '/') {
  862. $path = '/' . $path;
  863. }
  864. $this->_uri->setPath($path);
  865. /**
  866. * Get the HTTP client and configure it for the endpoint URI. Do this each time
  867. * because the Zend_Http_Client instance is shared among all Zend_Service_Abstract subclasses.
  868. */
  869. $this->_localHttpClient->resetParameters()->setUri($this->_uri);
  870. }
  871. /**
  872. * Performs an HTTP GET request to the $path.
  873. *
  874. * @param string $path
  875. * @param array $query Array of GET parameters
  876. * @throws Zend_Http_Client_Exception
  877. * @return Zend_Http_Response
  878. */
  879. protected function _get($path, array $query = null)
  880. {
  881. $this->_prepare($path);
  882. $this->_localHttpClient->setParameterGet($query);
  883. return $this->_localHttpClient->request('GET');
  884. }
  885. /**
  886. * Performs an HTTP POST request to $path.
  887. *
  888. * @param string $path
  889. * @param mixed $data Raw data to send
  890. * @throws Zend_Http_Client_Exception
  891. * @return Zend_Http_Response
  892. */
  893. protected function _post($path, $data = null)
  894. {
  895. $this->_prepare($path);
  896. return $this->_performPost('POST', $data);
  897. }
  898. /**
  899. * Perform a POST or PUT
  900. *
  901. * Performs a POST or PUT request. Any data provided is set in the HTTP
  902. * client. String data is pushed in as raw POST data; array or object data
  903. * is pushed in as POST parameters.
  904. *
  905. * @param mixed $method
  906. * @param mixed $data
  907. * @return Zend_Http_Response
  908. */
  909. protected function _performPost($method, $data = null)
  910. {
  911. $client = $this->_localHttpClient;
  912. if (is_string($data)) {
  913. $client->setRawData($data);
  914. } elseif (is_array($data) || is_object($data)) {
  915. $client->setParameterPost((array) $data);
  916. }
  917. return $client->request($method);
  918. }
  919. }