536 lines
14 KiB
PHP
536 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* @file
|
|
* Classes to implement the full Twitter API
|
|
*/
|
|
|
|
/**
|
|
* Class TwitterConfig
|
|
*
|
|
* Singleton which stores common configuration
|
|
* @see http://php.net/manual/en/language.oop5.patterns.php
|
|
*/
|
|
class TwitterConf {
|
|
private static $instance;
|
|
private $attributes = array(
|
|
'host' => 'twitter.com',
|
|
'api' => 'api.twitter.com',
|
|
'search' => 'search.twitter.com',
|
|
'tiny_url' => 'tinyurl.com',
|
|
);
|
|
|
|
private function __construct() {}
|
|
|
|
public static function instance() {
|
|
if (!isset(self::$instance)) {
|
|
$className = __CLASS__;
|
|
self::$instance = new $className;
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Generic getter
|
|
*
|
|
* @param $attribute
|
|
* string attribute name to return
|
|
* @return
|
|
* mixed value or NULL
|
|
*/
|
|
public function get($attribute) {
|
|
if (array_key_exists($attribute, $this->attributes)) {
|
|
return $this->attributes[$attribute];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generic setter
|
|
* @param $attribute
|
|
* string attribute name to be set
|
|
* @param $value
|
|
* mixed value
|
|
*/
|
|
public function set($attribute, $value) {
|
|
if (array_key_exists($attribute, $this->attributes)) {
|
|
$this->attributes[$attribute] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Exception handling class.
|
|
*/
|
|
class TwitterException extends Exception {}
|
|
|
|
/**
|
|
* Primary Twitter API implementation class
|
|
* Supports the full REST API for twitter.
|
|
*/
|
|
class Twitter {
|
|
|
|
/**
|
|
* @var $format API format to use: can be json or xml
|
|
*/
|
|
protected $format = 'json';
|
|
|
|
/**
|
|
* @var $source the twitter api 'source'
|
|
*/
|
|
protected $source = 'drupal';
|
|
|
|
/**
|
|
* @var $username Twitter username to use for authenticated requests
|
|
*/
|
|
protected $username;
|
|
|
|
/**
|
|
* @var $password Twitter password to use for authenticated requests
|
|
*/
|
|
protected $password;
|
|
|
|
/**
|
|
* Constructor for the Twitter class
|
|
*/
|
|
public function __construct($username = NULL, $password = NULL) {
|
|
if (!empty($username) && !empty($password)) {
|
|
$this->set_auth($username, $password);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the username and password
|
|
*/
|
|
public function set_auth($username, $password) {
|
|
$this->username = $username;
|
|
$this->password = $password;
|
|
}
|
|
|
|
/**
|
|
* Get an array of TwitterStatus objects from an API endpoint
|
|
*/
|
|
protected function get_statuses($path, $params = array(), $use_auth = FALSE) {
|
|
$values = $this->call($path, $params, 'GET', $use_auth);
|
|
// Check on successfull call
|
|
if ($values) {
|
|
$statuses = array();
|
|
foreach ($values as $status) {
|
|
$statuses[] = new TwitterStatus($status);
|
|
}
|
|
return $statuses;
|
|
}
|
|
// Call might return FALSE , e.g. on failed authentication
|
|
else {
|
|
// As call allready throws an exception, we can return an empty array to
|
|
// break no code.
|
|
return array();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch the public timeline
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-public_timeline
|
|
*/
|
|
public function public_timeline() {
|
|
return $this->get_statuses('statuses/public_timeline');
|
|
}
|
|
|
|
/**
|
|
* Fetch the authenticated user's friends timeline
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-friends_timeline
|
|
*/
|
|
public function friends_timeline($params = array()) {
|
|
return $this->get_statuses('statuses/friends_timeline', $params, TRUE);
|
|
}
|
|
|
|
/**
|
|
* Fetch a user's timeline
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-user_timeline
|
|
*/
|
|
public function user_timeline($id, $params = array(), $use_auth = FALSE) {
|
|
if (is_numeric($id)) {
|
|
$params['user_id'] = $id;
|
|
}
|
|
else {
|
|
$params['screen_name'] = $id;
|
|
}
|
|
|
|
return $this->get_statuses('statuses/user_timeline', $params, $use_auth);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-mentions
|
|
*/
|
|
public function mentions($params = array()) {
|
|
return $this->get_statuses('statuses/mentions', $params, TRUE);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses%C2%A0update
|
|
*/
|
|
public function status_update($status, $params = array()) {
|
|
$params['status'] = $status;
|
|
if ($this->source) {
|
|
$params['source'] = $this->source;
|
|
}
|
|
$values = $this->call('statuses/update', $params, 'POST', TRUE);
|
|
|
|
return new TwitterStatus($values);
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-users%C2%A0show
|
|
*/
|
|
public function users_show($id, $use_auth = TRUE) {
|
|
$params = array();
|
|
if (is_numeric($id)) {
|
|
$params['user_id'] = $id;
|
|
}
|
|
else {
|
|
$params['screen_name'] = $id;
|
|
}
|
|
|
|
$values = $this->call('users/show', $params, 'GET', $use_auth);
|
|
return new TwitterUser($values);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @see http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-account%C2%A0verify_credentials
|
|
*/
|
|
public function verify_credentials() {
|
|
$values = $this->call('account/verify_credentials', array(), 'GET', TRUE);
|
|
if (!$values) {
|
|
return FALSE;
|
|
}
|
|
return new TwitterUser($values);
|
|
}
|
|
|
|
|
|
/**
|
|
* Method for calling any twitter api resource
|
|
*/
|
|
public function call($path, $params = array(), $method = 'GET', $use_auth = FALSE) {
|
|
$url = $this->create_url($path);
|
|
|
|
try {
|
|
if ($use_auth) {
|
|
$response = $this->auth_request($url, $params, $method);
|
|
}
|
|
else {
|
|
$response = $this->request($url, $params, $method);
|
|
}
|
|
}
|
|
catch (TwitterException $e) {
|
|
watchdog('twitter', '!message', array('!message' => $e->__toString()), WATCHDOG_ERROR);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!$response) {
|
|
return FALSE;
|
|
}
|
|
|
|
return $this->parse_response($response);
|
|
}
|
|
|
|
/**
|
|
* Perform an authentication required request.
|
|
*/
|
|
protected function auth_request($path, $params = array(), $method = 'GET') {
|
|
if (empty($this->username) || empty($this->password)) {
|
|
return false;
|
|
}
|
|
|
|
return $this->request($path, $params, $method, TRUE);
|
|
}
|
|
|
|
/**
|
|
* Perform a request
|
|
*/
|
|
protected function request($url, $params = array(), $method = 'GET', $use_auth = FALSE) {
|
|
$data = '';
|
|
if (count($params) > 0) {
|
|
if ($method == 'GET') {
|
|
$url .= '?'. http_build_query($params, '', '&');
|
|
}
|
|
else {
|
|
$data = http_build_query($params, '', '&');
|
|
}
|
|
}
|
|
|
|
$headers = array();
|
|
|
|
if ($use_auth) {
|
|
$headers['Authorization'] = 'Basic '. base64_encode($this->username .':'. $this->password);
|
|
$headers['Content-type'] = 'application/x-www-form-urlencoded';
|
|
}
|
|
|
|
$response = drupal_http_request($url, array('headers' => $headers, 'method' => $method, 'data' => $data));
|
|
if (!isset($response->error)) {
|
|
return $response->data;
|
|
}
|
|
else {
|
|
$error = $response->error;
|
|
$data = $this->parse_response($response->data);
|
|
if (isset($data['error'])) {
|
|
$error = $data['error'];
|
|
}
|
|
throw new TwitterException($error);
|
|
}
|
|
}
|
|
|
|
protected function parse_response($response, $format = NULL) {
|
|
if (empty($format)) {
|
|
$format = $this->format;
|
|
}
|
|
|
|
switch ($format) {
|
|
case 'json':
|
|
// http://drupal.org/node/985544 - json_decode large integer issue
|
|
$length = strlen(PHP_INT_MAX);
|
|
$response = preg_replace('/"(id|in_reply_to_status_id)":(\d{' . $length . ',})/', '"\1":"\2"', $response);
|
|
return json_decode($response, TRUE);
|
|
}
|
|
}
|
|
|
|
protected function create_url($path, $format = NULL) {
|
|
if (is_null($format)) {
|
|
$format = $this->format;
|
|
}
|
|
$conf = TwitterConf::instance();
|
|
$url = 'http://'. $conf->get('api') .'/'. $path;
|
|
if (!empty($format)) {
|
|
$url .= '.'. $this->format;
|
|
}
|
|
return $url;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A class to provide OAuth enabled access to the twitter API
|
|
*/
|
|
class TwitterOAuth extends Twitter {
|
|
|
|
protected $signature_method;
|
|
|
|
protected $consumer;
|
|
|
|
protected $token;
|
|
|
|
public function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
|
|
$this->signature_method = new OAuthSignatureMethod_HMAC_SHA1();
|
|
$this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
|
|
if (!empty($oauth_token) && !empty($oauth_token_secret)) {
|
|
$this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
|
|
}
|
|
}
|
|
|
|
public function get_request_token() {
|
|
$url = $this->create_url('oauth/request_token', '');
|
|
try {
|
|
$response = $this->auth_request($url);
|
|
}
|
|
catch (TwitterException $e) {
|
|
}
|
|
parse_str($response, $token);
|
|
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
|
|
return $token;
|
|
}
|
|
|
|
public function get_authorize_url($token) {
|
|
$url = $this->create_url('oauth/authorize', '');
|
|
$url.= '?oauth_token=' . $token['oauth_token'];
|
|
|
|
return $url;
|
|
}
|
|
|
|
public function get_authenticate_url($token) {
|
|
$url = $this->create_url('oauth/authenticate', '');
|
|
$url.= '?oauth_token=' . $token['oauth_token'];
|
|
|
|
return $url;
|
|
}
|
|
|
|
public function get_access_token() {
|
|
$url = $this->create_url('oauth/access_token', '');
|
|
try {
|
|
$response = $this->auth_request($url);
|
|
}
|
|
catch (TwitterException $e) {
|
|
}
|
|
parse_str($response, $token);
|
|
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
|
|
return $token;
|
|
}
|
|
|
|
public function auth_request($url, $params = array(), $method = 'GET') {
|
|
$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $params);
|
|
$request->sign_request($this->signature_method, $this->consumer, $this->token);
|
|
switch ($method) {
|
|
case 'GET':
|
|
return $this->request($request->to_url());
|
|
case 'POST':
|
|
return $this->request($request->get_normalized_http_url(), $request->get_parameters(), 'POST');
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Twitter search is not used in this module yet
|
|
*/
|
|
class TwitterSearch extends Twitter {
|
|
public function search($params = array()) {}
|
|
}
|
|
|
|
/**
|
|
* Class for containing an individual twitter status.
|
|
*/
|
|
class TwitterStatus {
|
|
/**
|
|
* @var created_at
|
|
*/
|
|
public $created_at;
|
|
|
|
public $id;
|
|
|
|
public $text;
|
|
|
|
public $source;
|
|
|
|
public $truncated;
|
|
|
|
public $favorited;
|
|
|
|
public $in_reply_to_status_id;
|
|
|
|
public $in_reply_to_user_id;
|
|
|
|
public $in_reply_to_screen_name;
|
|
|
|
public $user;
|
|
|
|
/**
|
|
* Constructor for TwitterStatus
|
|
*/
|
|
public function __construct($values = array()) {
|
|
$this->created_at = $values['created_at'];
|
|
$this->id = $values['id'];
|
|
$this->text = $values['text'];
|
|
$this->source = $values['source'];
|
|
$this->truncated = $values['truncated'];
|
|
$this->favorited = $values['favorited'];
|
|
$this->in_reply_to_status_id = $values['in_reply_to_status_id'];
|
|
$this->in_reply_to_user_id = $values['in_reply_to_user_id'];
|
|
$this->in_reply_to_screen_name = $values['in_reply_to_screen_name'];
|
|
if (isset($values['user'])) {
|
|
$this->user = new TwitterUser($values['user']);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class TwitterUser {
|
|
|
|
public $id;
|
|
|
|
public $screen_name;
|
|
|
|
public $name;
|
|
|
|
public $location;
|
|
|
|
public $description;
|
|
|
|
public $followers_count;
|
|
|
|
public $friends_count;
|
|
|
|
public $statuses_count;
|
|
|
|
public $favourites_count;
|
|
|
|
public $url;
|
|
|
|
public $protected;
|
|
|
|
public $profile_image_url;
|
|
|
|
public $profile_background_color;
|
|
|
|
public $profile_text_color;
|
|
|
|
public $profile_link_color;
|
|
|
|
public $profile_sidebar_fill_color;
|
|
|
|
public $profile_sidebar_border_color;
|
|
|
|
public $profile_background_image_url;
|
|
|
|
public $profile_background_tile;
|
|
|
|
public $verified;
|
|
|
|
public $created_at;
|
|
|
|
public $created_time;
|
|
|
|
public $utc_offset;
|
|
|
|
public $status;
|
|
|
|
protected $password;
|
|
|
|
protected $oauth_token;
|
|
|
|
protected $oauth_token_secret;
|
|
|
|
public function __construct($values = array()) {
|
|
$this->id = $values['id'];
|
|
$this->screen_name = $values['screen_name'];
|
|
$this->name = $values['name'];
|
|
$this->location = $values['location'];
|
|
$this->description = $values['description'];
|
|
$this->url = $values['url'];
|
|
$this->followers_count = $values['followers_count'];
|
|
$this->friends_count = $values['friends_count'];
|
|
$this->statuses_count = $values['statuses_count'];
|
|
$this->favourites_count = $values['favourites_count'];
|
|
$this->protected = $values['protected'];
|
|
$this->profile_image_url = $values['profile_image_url'];
|
|
$this->profile_background_color = $values['profile_background_color'];
|
|
$this->profile_text_color = $values['profile_text_color'];
|
|
$this->profile_link_color = $values['profile_link_color'];
|
|
$this->profile_sidebar_fill_color = $values['profile_sidebar_fill_color'];
|
|
$this->profile_sidebar_border_color = $values['profile_sidebar_border_color'];
|
|
$this->profile_background_image_url = $values['profile_background_image_url'];
|
|
$this->profile_background_tile = $values['profile_background_tile'];
|
|
$this->verified = $values['verified'];
|
|
$this->created_at = $values['created_at'];
|
|
if ($values['created_at'] && $created_time = strtotime($values['created_at'])) {
|
|
$this->created_time = $created_time;
|
|
}
|
|
$this->utc_offset = $values['utc_offset']?$values['utc_offset']:0;
|
|
|
|
if (isset($values['status'])) {
|
|
$this->status = new TwitterStatus($values['status']);
|
|
}
|
|
}
|
|
|
|
public function get_auth() {
|
|
return array('password' => $this->password, 'oauth_token' => $this->oauth_token, 'oauth_token_secret' => $this->oauth_token_secret);
|
|
}
|
|
|
|
public function set_auth($values) {
|
|
$this->oauth_token = isset($values['oauth_token'])?$values['oauth_token']:NULL;
|
|
$this->oauth_token_secret = isset($values['oauth_token_secret'])?$values['oauth_token_secret']:NULL;
|
|
}
|
|
}
|