Project

General

Profile

Statistics
| Branch: | Revision:

colonymech / docs / www / colonyscout / twitter.class.php @ f59acf11

History | View | Annotate | Download (5.04 KB)

1
<?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
}