2
0

Twitter.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  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-2008 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-2008 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. * Whether or not authorization has been initialized for the current user.
  41. * @var bool
  42. */
  43. protected $_authInitialized = false;
  44. /**
  45. * @var Zend_Http_CookieJar
  46. */
  47. protected $_cookieJar;
  48. /**
  49. * Date format for 'since' strings
  50. * @var string
  51. */
  52. protected $_dateFormat = 'D, d M Y H:i:s T';
  53. /**
  54. * Username
  55. * @var string
  56. */
  57. protected $_username;
  58. /**
  59. * Password
  60. * @var string
  61. */
  62. protected $_password;
  63. /**
  64. * Current method type (for method proxying)
  65. * @var string
  66. */
  67. protected $_methodType;
  68. /**
  69. * Types of API methods
  70. * @var array
  71. */
  72. protected $_methodTypes = array(
  73. 'status',
  74. 'user',
  75. 'directMessage',
  76. 'friendship',
  77. 'account',
  78. 'favorite'
  79. );
  80. /**
  81. * Constructor
  82. *
  83. * @param string $username
  84. * @param string $password
  85. * @return void
  86. */
  87. public function __construct($username, $password)
  88. {
  89. $this->setUsername($username);
  90. $this->setPassword($password);
  91. $this->setUri('http://twitter.com');
  92. $client = self::getHttpClient();
  93. $client->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
  94. }
  95. /**
  96. * Retrieve username
  97. *
  98. * @return string
  99. */
  100. public function getUsername()
  101. {
  102. return $this->_username;
  103. }
  104. /**
  105. * Set username
  106. *
  107. * @param string $value
  108. * @return Zend_Service_Twitter
  109. */
  110. public function setUsername($value)
  111. {
  112. $this->_username = $value;
  113. $this->_authInitialized = false;
  114. return $this;
  115. }
  116. /**
  117. * Retrieve password
  118. *
  119. * @return string
  120. */
  121. public function getPassword()
  122. {
  123. return $this->_password;
  124. }
  125. /**
  126. * Set password
  127. *
  128. * @param string $value
  129. * @return Zend_Service_Twitter
  130. */
  131. public function setPassword($value)
  132. {
  133. $this->_password = $value;
  134. $this->_authInitialized = false;
  135. return $this;
  136. }
  137. /**
  138. * Proxy service methods
  139. *
  140. * @param string $type
  141. * @return Zend_Service_Twitter
  142. * @throws Zend_Service_Twitter_Exception if method is not in method types list
  143. */
  144. public function __get($type)
  145. {
  146. if (!in_array($type, $this->_methodTypes)) {
  147. include_once 'Zend/Service/Twitter/Exception.php';
  148. throw new Zend_Service_Twitter_Exception('Invalid method type "' . $type . '"');
  149. }
  150. $this->_methodType = $type;
  151. return $this;
  152. }
  153. /**
  154. * Method overloading
  155. *
  156. * @param string $method
  157. * @param array $params
  158. * @return mixed
  159. * @throws Zend_Service_Twitter_Exception if unable to find method
  160. */
  161. public function __call($method, $params)
  162. {
  163. if (empty($this->_methodType)) {
  164. include_once 'Zend/Service/Twitter/Exception.php';
  165. throw new Zend_Service_Twitter_Exception('Invalid method "' . $method . '"');
  166. }
  167. $test = $this->_methodType . ucfirst($method);
  168. if (!method_exists($this, $test)) {
  169. include_once 'Zend/Service/Twitter/Exception.php';
  170. throw new Zend_Service_Twitter_Exception('Invalid method "' . $test . '"');
  171. }
  172. return call_user_func_array(array($this, $test), $params);
  173. }
  174. /**
  175. * Initialize HTTP authentication
  176. *
  177. * @return void
  178. */
  179. protected function _init()
  180. {
  181. $client = self::getHttpClient();
  182. $client->resetParameters();
  183. if (null == $this->_cookieJar) {
  184. $client->setCookieJar();
  185. $this->_cookieJar = $client->getCookieJar();
  186. } else {
  187. $client->setCookieJar($this->_cookieJar);
  188. }
  189. if (!$this->_authInitialized) {
  190. $client->setAuth($this->getUsername(), $this->getPassword());
  191. $this->_authInitialized = true;
  192. }
  193. }
  194. /**
  195. * Set date header
  196. *
  197. * @param int|string $value
  198. * @return void
  199. */
  200. protected function _setDate($value)
  201. {
  202. if (is_int($value)) {
  203. $date = date($this->_dateFormat, $value);
  204. } else {
  205. $date = date($this->_dateFormat, strtotime($value));
  206. }
  207. self::getHttpClient()->setHeaders('If-Modified-Since', $date);
  208. }
  209. /**
  210. * Public Timeline status
  211. *
  212. * @return Zend_Rest_Client_Result
  213. */
  214. public function statusPublicTimeline()
  215. {
  216. $this->_init();
  217. $path = '/statuses/public_timeline.xml';
  218. $response = $this->restGet($path);
  219. return new Zend_Rest_Client_Result($response->getBody());
  220. }
  221. /**
  222. * Friend Timeline Status
  223. *
  224. * $params may include one or more of the following keys
  225. * - id: ID of a friend whose timeline you wish to receive
  226. * - count: how many statuses to return
  227. * - since: return results only after the date specified
  228. * - since_id: return results only after the specific tweet
  229. * - page: return page X of results
  230. *
  231. * @param array $params
  232. * @return void
  233. */
  234. public function statusFriendsTimeline(array $params = array())
  235. {
  236. $this->_init();
  237. $path = '/statuses/friends_timeline';
  238. $_params = array();
  239. foreach ($params as $key => $value) {
  240. switch (strtolower($key)) {
  241. case 'count':
  242. $count = (int) $value;
  243. if (0 >= $count) {
  244. $count = 1;
  245. } elseif (200 < $count) {
  246. $count = 200;
  247. }
  248. $_params['count'] = (int) $count;
  249. break;
  250. case 'since_id':
  251. $_params['since_id'] = (int) $value;
  252. break;
  253. case 'since':
  254. $this->_setDate($value);
  255. break;
  256. case 'page':
  257. $_params['page'] = (int) $value;
  258. break;
  259. default:
  260. break;
  261. }
  262. }
  263. $path .= '.xml';
  264. $response = $this->restGet($path, $_params);
  265. return new Zend_Rest_Client_Result($response->getBody());
  266. }
  267. /**
  268. * User Timeline status
  269. *
  270. * $params may include one or more of the following keys
  271. * - id: ID of a friend whose timeline you wish to receive
  272. * - since: return results only after the date specified
  273. * - page: return page X of results
  274. * - count: how many statuses to return
  275. *
  276. * @return Zend_Rest_Client_Result
  277. */
  278. public function statusUserTimeline(array $params = array())
  279. {
  280. $this->_init();
  281. $path = '/statuses/user_timeline';
  282. $_params = array();
  283. foreach ($params as $key => $value) {
  284. switch (strtolower($key)) {
  285. case 'id':
  286. $path .= '/' . $value;
  287. break;
  288. case 'since':
  289. $this->_setDate($value);
  290. break;
  291. case 'page':
  292. $_params['page'] = (int) $value;
  293. break;
  294. case 'count':
  295. $count = (int) $value;
  296. if (0 >= $count) {
  297. $count = 1;
  298. } elseif (200 < $count) {
  299. $count = 200;
  300. }
  301. $_params['count'] = $count;
  302. break;
  303. default:
  304. break;
  305. }
  306. }
  307. $path .= '.xml';
  308. $response = $this->restGet($path, $_params);
  309. return new Zend_Rest_Client_Result($response->getBody());
  310. }
  311. /**
  312. * Show a single status
  313. *
  314. * @param int $id Id of status to show
  315. * @return Zend_Rest_Client_Result
  316. */
  317. public function statusShow($id)
  318. {
  319. $this->_init();
  320. $path = '/statuses/show/' . $id . '.xml';
  321. $response = $this->restGet($path);
  322. return new Zend_Rest_Client_Result($response->getBody());
  323. }
  324. /**
  325. * Update user's current status
  326. *
  327. * @param string $status
  328. * @param int $in_reply_to_status_id
  329. * @return Zend_Rest_Client_Result
  330. * @throws Zend_Service_Twitter_Exception if message is too short or too long
  331. */
  332. public function statusUpdate($status, $in_reply_to_status_id = null)
  333. {
  334. $this->_init();
  335. $path = '/statuses/update.xml';
  336. $len = iconv_strlen($status, 'UTF-8');
  337. if ($len > 140) {
  338. include_once 'Zend/Service/Twitter/Exception.php';
  339. throw new Zend_Service_Twitter_Exception('Status must be no more than 140 characters in length');
  340. } elseif (0 == $len) {
  341. include_once 'Zend/Service/Twitter/Exception.php';
  342. throw new Zend_Service_Twitter_Exception('Status must contain at least one character');
  343. }
  344. $data = array(
  345. 'status' => $status
  346. );
  347. if(is_numeric($in_reply_to_status_id) && !empty($in_reply_to_status_id)) {
  348. $data['in_reply_to_status_id'] = $in_reply_to_status_id;
  349. }
  350. //$this->status = $status;
  351. $response = $this->restPost($path, $data);
  352. return new Zend_Rest_Client_Result($response->getBody());
  353. }
  354. /**
  355. * Get status replies
  356. *
  357. * $params may include one or more of the following keys
  358. * - since: return results only after the date specified
  359. * - since_id: return results only after the specified tweet id
  360. * - page: return page X of results
  361. *
  362. * @return Zend_Rest_Client_Result
  363. */
  364. public function statusReplies(array $params = array())
  365. {
  366. $this->_init();
  367. $path = '/statuses/replies.xml';
  368. $_params = array();
  369. foreach ($params as $key => $value) {
  370. switch (strtolower($key)) {
  371. case 'since':
  372. $this->_setDate($value);
  373. break;
  374. case 'since_id':
  375. $_params['since_id'] = (int) $value;
  376. break;
  377. case 'page':
  378. $_params['page'] = (int) $value;
  379. break;
  380. default:
  381. break;
  382. }
  383. }
  384. $response = $this->restGet($path, $_params);
  385. return new Zend_Rest_Client_Result($response->getBody());
  386. }
  387. /**
  388. * Destroy a status message
  389. *
  390. * @param int $id ID of status to destroy
  391. * @return Zend_Rest_Client_Result
  392. */
  393. public function statusDestroy($id)
  394. {
  395. $this->_init();
  396. $path = '/statuses/destroy/' . (int) $id . '.xml';
  397. $response = $this->restPost($path);
  398. return new Zend_Rest_Client_Result($response->getBody());
  399. }
  400. /**
  401. * User friends
  402. *
  403. * @param int|string $id Id or username of user for whom to fetch friends
  404. * @return Zend_Rest_Client_Result
  405. */
  406. public function userFriends(array $params = array())
  407. {
  408. $this->_init();
  409. $path = '/statuses/friends';
  410. $_params = array();
  411. foreach ($params as $key => $value) {
  412. switch (strtolower($key)) {
  413. case 'id':
  414. $path .= '/' . $value;
  415. break;
  416. case 'since':
  417. $this->_setDate($value);
  418. break;
  419. case 'page':
  420. $_params['page'] = (int) $value;
  421. break;
  422. default:
  423. break;
  424. }
  425. }
  426. $path .= '.xml';
  427. $response = $this->restGet($path, $_params);
  428. return new Zend_Rest_Client_Result($response->getBody());
  429. }
  430. /**
  431. * User Followers
  432. *
  433. * @param bool $lite If true, prevents inline inclusion of current status for followers; defaults to false
  434. * @return Zend_Rest_Client_Result
  435. */
  436. public function userFollowers($lite = false)
  437. {
  438. $this->_init();
  439. $path = '/statuses/followers.xml';
  440. if ($lite) {
  441. $this->lite = 'true';
  442. }
  443. $response = $this->restGet($path);
  444. return new Zend_Rest_Client_Result($response->getBody());
  445. }
  446. /**
  447. * Get featured users
  448. *
  449. * @return Zend_Rest_Client_Result
  450. */
  451. public function userFeatured()
  452. {
  453. $this->_init();
  454. $path = '/statuses/featured.xml';
  455. $response = $this->restGet($path);
  456. return new Zend_Rest_Client_Result($response->getBody());
  457. }
  458. /**
  459. * Show extended information on a user
  460. *
  461. * @param int|string $id User ID or name
  462. * @return Zend_Rest_Client_Result
  463. */
  464. public function userShow($id)
  465. {
  466. $this->_init();
  467. $path = '/users/show/' . $id . '.xml';
  468. $response = $this->restGet($path);
  469. return new Zend_Rest_Client_Result($response->getBody());
  470. }
  471. /**
  472. * Retrieve direct messages for the current user
  473. *
  474. * $params may include one or more of the following keys
  475. * - since: return results only after the date specified
  476. * - since_id: return statuses only greater than the one specified
  477. * - page: return page X of results
  478. *
  479. * @param array $params
  480. * @return Zend_Rest_Client_Result
  481. */
  482. public function directMessageMessages(array $params = array())
  483. {
  484. $this->_init();
  485. $path = '/direct_messages.xml';
  486. $_params = array();
  487. foreach ($params as $key => $value) {
  488. switch (strtolower($key)) {
  489. case 'since':
  490. $this->_setDate($value);
  491. break;
  492. case 'since_id':
  493. $_params['since_id'] = (int) $value;
  494. break;
  495. case 'page':
  496. $_params['page'] = (int) $value;
  497. break;
  498. default:
  499. break;
  500. }
  501. }
  502. $response = $this->restGet($path, $_params);
  503. return new Zend_Rest_Client_Result($response->getBody());
  504. }
  505. /**
  506. * Retrieve list of direct messages sent by current user
  507. *
  508. * $params may include one or more of the following keys
  509. * - since: return results only after the date specified
  510. * - since_id: return statuses only greater than the one specified
  511. * - page: return page X of results
  512. *
  513. * @param array $params
  514. * @return Zend_Rest_Client_Result
  515. */
  516. public function directMessageSent(array $params = array())
  517. {
  518. $this->_init();
  519. $path = '/direct_messages/sent.xml';
  520. $_params = array();
  521. foreach ($params as $key => $value) {
  522. switch (strtolower($key)) {
  523. case 'since':
  524. $this->_setDate($value);
  525. break;
  526. case 'since_id':
  527. $_params['since_id'] = (int) $value;
  528. break;
  529. case 'page':
  530. $_params['page'] = (int) $value;
  531. break;
  532. default:
  533. break;
  534. }
  535. }
  536. $response = $this->restGet($path, $_params);
  537. return new Zend_Rest_Client_Result($response->getBody());
  538. }
  539. /**
  540. * Send a direct message to a user
  541. *
  542. * @param int|string $user User to whom to send message
  543. * @param string $text Message to send to user
  544. * @return Zend_Rest_Client_Result
  545. * @throws Zend_Service_Twitter_Exception if message is too short or too long
  546. */
  547. public function directMessageNew($user, $text)
  548. {
  549. $this->_init();
  550. $path = '/direct_messages/new.xml';
  551. $len = iconv_strlen($text, 'UTF-8');
  552. if (0 == $len) {
  553. throw new Zend_Service_Twitter_Exception('Direct message must contain at least one character');
  554. } elseif (140 < $len) {
  555. throw new Zend_Service_Twitter_Exception('Direct message must contain no more than 140 characters');
  556. }
  557. $data = array(
  558. 'user' => $user,
  559. 'text' => $text,
  560. );
  561. $response = $this->restPost($path, $data);
  562. return new Zend_Rest_Client_Result($response->getBody());
  563. }
  564. /**
  565. * Destroy a direct message
  566. *
  567. * @param int $id ID of message to destroy
  568. * @return Zend_Rest_Client_Result
  569. */
  570. public function directMessageDestroy($id)
  571. {
  572. $this->_init();
  573. $path = '/direct_messages/destroy/' . $id . '.xml';
  574. $response = $this->restPost($path);
  575. return new Zend_Rest_Client_Result($response->getBody());
  576. }
  577. /**
  578. * Create friendship
  579. *
  580. * @param int|string $id User ID or name of new friend
  581. * @return Zend_Rest_Client_Result
  582. */
  583. public function friendshipCreate($id)
  584. {
  585. $this->_init();
  586. $path = '/friendships/create/' . $id . '.xml';
  587. $response = $this->restPost($path);
  588. return new Zend_Rest_Client_Result($response->getBody());
  589. }
  590. /**
  591. * Destroy friendship
  592. *
  593. * @param int|string $id User ID or name of friend to remove
  594. * @return Zend_Rest_Client_Result
  595. */
  596. public function friendshipDestroy($id)
  597. {
  598. $this->_init();
  599. $path = '/friendships/destroy/' . $id . '.xml';
  600. $response = $this->restPost($path);
  601. return new Zend_Rest_Client_Result($response->getBody());
  602. }
  603. /**
  604. * Friendship exists
  605. *
  606. * @param int|string $id User ID or name of friend to see if they are your friend
  607. * @return Zend_Rest_Client_result
  608. */
  609. public function friendshipExists($id)
  610. {
  611. $this->_init();
  612. $path = '/friendships/exists.xml';
  613. $data = array(
  614. 'user_a' => $this->getUsername(),
  615. 'user_b' => $id
  616. );
  617. $response = $this->restGet($path, $data);
  618. return new Zend_Rest_Client_Result($response->getBody());
  619. }
  620. /**
  621. * Verify Account Credentials
  622. *
  623. * @return Zend_Rest_Client_Result
  624. */
  625. public function accountVerifyCredentials()
  626. {
  627. $this->_init();
  628. $response = $this->restGet('/account/verify_credentials.xml');
  629. return new Zend_Rest_Client_Result($response->getBody());
  630. }
  631. /**
  632. * End current session
  633. *
  634. * @return true
  635. */
  636. public function accountEndSession()
  637. {
  638. $this->_init();
  639. $this->restGet('/account/end_session');
  640. return true;
  641. }
  642. /**
  643. * Returns the number of api requests you have left per hour.
  644. *
  645. * @return Zend_Rest_Client_Result
  646. */
  647. public function accountRateLimitStatus()
  648. {
  649. $this->_init();
  650. $response = $this->restGet('/account/rate_limit_status.xml');
  651. return new Zend_Rest_Client_Result($response->getBody());
  652. }
  653. /**
  654. * Fetch favorites
  655. *
  656. * $params may contain one or more of the following:
  657. * - 'id': Id of a user for whom to fetch favorites
  658. * - 'page': Retrieve a different page of resuls
  659. *
  660. * @param array $params
  661. * @return Zend_Rest_Client_Result
  662. */
  663. public function favoriteFavorites(array $params = array())
  664. {
  665. $this->_init();
  666. $path = '/favorites';
  667. $_params = array();
  668. foreach ($params as $key => $value) {
  669. switch (strtolower($key)) {
  670. case 'id':
  671. $path .= '/' . $value;
  672. break;
  673. case 'page':
  674. $_params['page'] = (int) $value;
  675. break;
  676. default:
  677. break;
  678. }
  679. }
  680. $path .= '.xml';
  681. $response = $this->restGet($path, $_params);
  682. return new Zend_Rest_Client_Result($response->getBody());
  683. }
  684. /**
  685. * Mark a status as a favorite
  686. *
  687. * @param int $id Status ID you want to mark as a favorite
  688. * @return Zend_Rest_Client_Result
  689. */
  690. public function favoriteCreate($id)
  691. {
  692. $this->_init();
  693. $path = '/favorites/create/' . (int) $id . '.xml';
  694. $response = $this->restPost($path);
  695. return new Zend_Rest_Client_Result($response->getBody());
  696. }
  697. /**
  698. * Remove a favorite
  699. *
  700. * @param int $id Status ID you want to de-list as a favorite
  701. * @return Zend_Rest_Client_Result
  702. */
  703. public function favoriteDestroy($id)
  704. {
  705. $this->_init();
  706. $path = '/favorites/destroy/' . (int) $id . '.xml';
  707. $response = $this->restPost($path);
  708. return new Zend_Rest_Client_Result($response->getBody());
  709. }
  710. }