root / docs / www / colonyscout / twitter.class.php @ 781890a0
History | View | Annotate | Download (5.04 KB)
1 | f59acf11 | Dan Shope | <?php
|
---|---|---|---|
2 | |||
3 | /**
|
||
4 | * Twitter for PHP - library for sending messages to Twitter and receiving status updates.
|
||
5 | *
|
||
6 | * @author David Grudl
|
||
7 | * @copyright Copyright (c) 2008 David Grudl
|
||
8 | * @license New BSD License
|
||
9 | * @link http://phpfashion.com/
|
||
10 | * @see http://apiwiki.twitter.com/Twitter-API-Documentation
|
||
11 | * @version 1.2
|
||
12 | */
|
||
13 | class Twitter |
||
14 | { |
||
15 | /**#@+ Timeline {@link Twitter::load()} */
|
||
16 | const ME = 1; |
||
17 | const ME_AND_FRIENDS = 2; |
||
18 | const REPLIES = 3; |
||
19 | const ALL = 4; |
||
20 | /**#@-*/
|
||
21 | |||
22 | /**#@+ Output format {@link Twitter::load()} */
|
||
23 | const XML = 0; |
||
24 | const JSON = 16; |
||
25 | const RSS = 32; |
||
26 | const ATOM = 48; |
||
27 | /**#@-*/
|
||
28 | |||
29 | /** @var int */
|
||
30 | public static $cacheExpire = 1800; // 30 min |
||
31 | |||
32 | /** @var string */
|
||
33 | public static $cacheDir; |
||
34 | |||
35 | /** @var user name */
|
||
36 | private $user; |
||
37 | |||
38 | /** @var password */
|
||
39 | private $pass; |
||
40 | |||
41 | |||
42 | /**
|
||
43 | * Creates object using your credentials.
|
||
44 | * @param string user name
|
||
45 | * @param string password
|
||
46 | * @throws Exception
|
||
47 | */
|
||
48 | public function __construct($user, $pass) |
||
49 | { |
||
50 | if (!extension_loaded('curl')) { |
||
51 | throw new TwitterException('PHP extension CURL is not loaded.'); |
||
52 | } |
||
53 | |||
54 | $this->user = $user; |
||
55 | $this->pass = $pass; |
||
56 | } |
||
57 | |||
58 | |||
59 | |||
60 | /**
|
||
61 | * Tests if user credentials are valid.
|
||
62 | * @return boolean
|
||
63 | * @throws Exception
|
||
64 | */
|
||
65 | public function authenticate() |
||
66 | { |
||
67 | try {
|
||
68 | $xml = $this->httpRequest('http://twitter.com/account/verify_credentials.xml'); |
||
69 | return !empty($xml->id); |
||
70 | |||
71 | } catch (TwitterException $e) { |
||
72 | if ($e->getCode() === 401) { |
||
73 | return FALSE; |
||
74 | } |
||
75 | throw $e; |
||
76 | } |
||
77 | } |
||
78 | |||
79 | |||
80 | |||
81 | /**
|
||
82 | * Sends message to the Twitter.
|
||
83 | * @param string message encoded in UTF-8
|
||
84 | * @return mixed ID on success or FALSE on failure
|
||
85 | */
|
||
86 | public function send($message) |
||
87 | { |
||
88 | $xml = $this->httpRequest( |
||
89 | 'https://twitter.com/statuses/update.xml',
|
||
90 | array('status' => $message) |
||
91 | ); |
||
92 | return $xml->id ? (string) $xml->id : FALSE; |
||
93 | } |
||
94 | |||
95 | |||
96 | |||
97 | /**
|
||
98 | * Returns the most recent statuses.
|
||
99 | * @param int timeline (ME | ME_AND_FRIENDS | REPLIES | ALL) and optional format (XML | JSON | RSS | ATOM)
|
||
100 | * @param int number of statuses to retrieve
|
||
101 | * @param int page of results to retrieve
|
||
102 | * @return mixed
|
||
103 | * @throws TwitterException
|
||
104 | */
|
||
105 | public function load($flags = self::ME, $count = 20, $page = 1) |
||
106 | { |
||
107 | static $timelines = array(self::ME => 'user_timeline', self::ME_AND_FRIENDS => 'friends_timeline', self::REPLIES => 'mentions', self::ALL => 'public_timeline'); |
||
108 | static $formats = array(self::XML => 'xml', self::JSON => 'json', self::RSS => 'rss', self::ATOM => 'atom'); |
||
109 | |||
110 | if (!is_int($flags)) { // back compatibility |
||
111 | $flags = $flags ? self::ME_AND_FRIENDS : self::ME; |
||
112 | |||
113 | } elseif (!isset($timelines[$flags & 0x0F], $formats[$flags & 0x30])) { |
||
114 | throw new InvalidArgumentException; |
||
115 | } |
||
116 | |||
117 | return $this->cachedHttpRequest("http://twitter.com/statuses/" . $timelines[$flags & 0x0F] . '.' . $formats[$flags & 0x30] . "?count=$count&page=$page"); |
||
118 | } |
||
119 | |||
120 | |||
121 | |||
122 | /**
|
||
123 | * Process HTTP request.
|
||
124 | * @param string URL
|
||
125 | * @param array of post data
|
||
126 | * @return mixed
|
||
127 | */
|
||
128 | private function httpRequest($url, $postData = NULL) |
||
129 | { |
||
130 | $curl = curl_init();
|
||
131 | curl_setopt($curl, CURLOPT_URL, $url); |
||
132 | curl_setopt($curl, CURLOPT_USERPWD, "$this->user:$this->pass"); |
||
133 | curl_setopt($curl, CURLOPT_HEADER, FALSE); |
||
134 | curl_setopt($curl, CURLOPT_TIMEOUT, 20); |
||
135 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); |
||
136 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:')); |
||
137 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); // no echo, just return result |
||
138 | if ($postData) { |
||
139 | curl_setopt($curl, CURLOPT_POST, TRUE); |
||
140 | curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); |
||
141 | } |
||
142 | |||
143 | $result = curl_exec($curl); |
||
144 | if (curl_errno($curl)) { |
||
145 | throw new TwitterException('Server error: ' . curl_error($curl)); |
||
146 | } |
||
147 | |||
148 | $type = curl_getinfo($curl, CURLINFO_CONTENT_TYPE); |
||
149 | if (strpos($type, 'xml')) { |
||
150 | $payload = @simplexml_load_string($result); // intentionally @ |
||
151 | |||
152 | } elseif (strpos($type, 'json')) { |
||
153 | $payload = @json_decode($result); // intentionally @ |
||
154 | } |
||
155 | |||
156 | if (empty($payload)) { |
||
157 | throw new TwitterException('Invalid server response'); |
||
158 | } |
||
159 | |||
160 | $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); |
||
161 | if ($code >= 400) { |
||
162 | throw new TwitterException(isset($payload->error) ? $payload->error : "Server error #$code", $code); |
||
163 | } |
||
164 | |||
165 | return $payload; |
||
166 | } |
||
167 | |||
168 | |||
169 | |||
170 | /**
|
||
171 | * Cached HTTP request.
|
||
172 | * @param string URL
|
||
173 | * @return mixed
|
||
174 | */
|
||
175 | private function cachedHttpRequest($url) |
||
176 | { |
||
177 | if (!self::$cacheDir) { |
||
178 | return $this->httpRequest($url); |
||
179 | } |
||
180 | |||
181 | $cacheFile = self::$cacheDir . '/cache.' . md5($url); |
||
182 | $cache = @file_get_contents($cacheFile); // intentionally @ |
||
183 | $cache = strncmp($cache, '<', 1) ? @json_decode($cache) : @simplexml_load_string($cache); // intentionally @ |
||
184 | if ($cache && @filemtime($cacheFile) + self::$cacheExpire > time()) { // intentionally @ |
||
185 | return $cache; |
||
186 | } |
||
187 | |||
188 | try {
|
||
189 | $payload = $this->httpRequest($url); |
||
190 | file_put_contents($cacheFile, $payload instanceof SimpleXMLElement ? $payload->asXml() : json_encode($payload)); |
||
191 | return $payload; |
||
192 | |||
193 | } catch (TwitterException $e) { |
||
194 | if ($cache) { |
||
195 | return $cache; |
||
196 | } |
||
197 | throw $e; |
||
198 | } |
||
199 | } |
||
200 | |||
201 | } |
||
202 | |||
203 | |||
204 | |||
205 | /**
|
||
206 | * An exception generated by Twitter.
|
||
207 | */
|
||
208 | class TwitterException extends Exception |
||
209 | { |
||
210 | } |