123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <?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;
- }
- }
|