Guest User

Untitled

a guest
May 23rd, 2011
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 56.88 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Twitter class
  4.  *
  5.  * This source file can be used to communicate with Twitter (http://twitter.com)
  6.  *
  7.  * The class is documented in the file itself. If you find any bugs help me out and report them. Reporting can be done by sending an email to php-twitter-bugs[at]verkoyen[dot]eu.
  8.  * If you report a bug, make sure you give me enough information (include your code).
  9.  *
  10.  * Changelog since 1.0.0
  11.  * - dont send postfields as an array, pass them as an urldecoded string (otherwise @ won't work
  12.  *
  13.  * Changelog since 1.0.1
  14.  * - fixed a bug in verifyCredentials, it return a boolean instead of throwing an exception when the credentials are invalid (thx @Rahul)
  15.  *
  16.  * Changelog since 1.0.2
  17.  * - sinceId is from now on treated as a string instead of int. (thx @Paul Matthews)
  18.  *
  19.  * Changelog since 1.0.3
  20.  * - rewrote some comments
  21.  * - fixed some PHPDoc
  22.  * - it seems Twitter removed the $since-parameter, so I removed it from getFriendsTimeline, getUserTimeline, getDirectMessages, getSentDirectMessages, ...
  23.  * - implemented maxId into getFriendsTimeline
  24.  * - renamed getReplies to getMentions to reflect the Twitter API
  25.  * - added $count for getDirectMessages, getSentDirectMessages, ...
  26.  * - added getFriendship which shows more details about a friendship
  27.  * - added getFriendIds and getFollowerIds which return only the ids instead of a user-array
  28.  * - added existsBlock which test if a block exists
  29.  * - added getBlocked, which returns an array of blocked user-arrays
  30.  * - added getBlockedIds, which returns an array of blocked ids
  31.  *
  32.  * Changelog since 1.0.4
  33.  * - renamed verifyCrendentials to verifyCredentials (typo)
  34.  *
  35.  *
  36.  * License
  37.  * Copyright (c) 2008, Tijs Verkoyen. All rights reserved.
  38.  *
  39.  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  40.  *
  41.  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  42.  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  43.  * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
  44.  *
  45.  * This software is provided by the author "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
  46.  *
  47.  * @author      Tijs Verkoyen <[email protected]>
  48.  * @version     1.0.5
  49.  *
  50.  * @copyright   Copyright (c) 2008, Tijs Verkoyen. All rights reserved.
  51.  * @license     BSD License
  52.  */
  53. class Twitter
  54. {
  55.     // internal constant to enable/disable debugging
  56.     const DEBUG = false;
  57.  
  58.     // url for the twitter-api
  59.     const TWITTER_API_URL = 'http://twitter.com';
  60.  
  61.     // port for the twitter-api
  62.     const TWITTER_API_PORT = 80;
  63.  
  64.     // current version
  65.     const VERSION = '1.0.5';
  66.  
  67.  
  68.     /**
  69.      * The password for an authenticating user
  70.      *
  71.      * @var string
  72.      */
  73.     public $password;
  74.  
  75.  
  76.     /**
  77.      * The timeout
  78.      *
  79.      * @var int
  80.      */
  81.     private $timeOut = 60;
  82.  
  83.  
  84.     /**
  85.      * The user agent
  86.      *
  87.      * @var string
  88.      */
  89.     private $userAgent;
  90.  
  91.  
  92.     /**
  93.      * The username for an authenticating user
  94.      *
  95.      * @var string
  96.      */
  97.     public $username;
  98.  
  99.  
  100. // class methods
  101.     /**
  102.      * Default constructor
  103.      *
  104.      * @return  void
  105.      * @param   string[optional] $username  The username for an authenticating user
  106.      * @param   string[optional] $password  The password for an authenticating user
  107.      */
  108.      
  109.     //public function __construct($username = null, $password = null)
  110.     public function __construct($config= array())
  111.     {
  112.         //if($username !== null) $this->setUsername($username);
  113.         //if($password !== null) $this->setPassword($password);
  114.         $this->initialize($config);
  115.    
  116.         if($this->username !== null) $this->setUsername($this->username);
  117.         if($this->password !== null) $this->setPassword($this->password);
  118.     }
  119.  
  120.    
  121.     function initialize($config = array())
  122.     {
  123.        
  124.         foreach ($config as $key => $val)
  125.         {
  126.            
  127.            
  128.             $this->$key = $val;
  129.            
  130.            
  131.         }
  132.     }
  133.  
  134.     /**
  135.      * Make the call
  136.      *
  137.      * @return  string
  138.      * @param   string $url
  139.      * @param   array[optiona] $aParameters
  140.      * @param   bool[optional] $authenticate
  141.      * @param   bool[optional] $usePost
  142.      */
  143.     private function doCall($url, $aParameters = array(), $authenticate = false, $usePost = true)
  144.     {
  145.         // redefine
  146.         $url = (string) $url;
  147.         $aParameters = (array) $aParameters;
  148.         $authenticate = (bool) $authenticate;
  149.         $usePost = (bool) $usePost;
  150.  
  151.         // build url
  152.         $url = self::TWITTER_API_URL .'/'. $url;
  153.  
  154.         // validate needed authentication
  155.         if($authenticate && ($this->getUsername() == '' || $this->getPassword() == '')) throw new TwitterException('No username or password was set.');
  156.  
  157.         // rebuild url if we don't use post
  158.         if(!empty($aParameters) && !$usePost)
  159.         {
  160.             // init var
  161.             $queryString = '';
  162.  
  163.             // loop parameters and add them to the queryString
  164.             foreach($aParameters as $key => $value) $queryString .= '&'. $key .'='. urlencode(utf8_encode($value));
  165.  
  166.             // cleanup querystring
  167.             $queryString = trim($queryString, '&');
  168.  
  169.             // append to url
  170.             $url .= '?'. $queryString;
  171.         }
  172.  
  173.         // set options
  174.         $options[CURLOPT_URL] = $url;
  175.         $options[CURLOPT_PORT] = self::TWITTER_API_PORT;
  176.         $options[CURLOPT_USERAGENT] = $this->getUserAgent();
  177.         $options[CURLOPT_FOLLOWLOCATION] = true;
  178.         $options[CURLOPT_RETURNTRANSFER] = true;
  179.         $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
  180.  
  181.         // should we authenticate?
  182.         if($authenticate)
  183.         {
  184.             $options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC;
  185.             $options[CURLOPT_USERPWD] = $this->getUsername() .':'. $this->getPassword();
  186.         }
  187.  
  188.         // are there any parameters?
  189.         if(!empty($aParameters) && $usePost)
  190.         {
  191.             $var = '';
  192.  
  193.             // rebuild parameters
  194.             foreach($aParameters as $key => $value) $var .= '&'. $key .'='. urlencode($value);
  195.  
  196.             // set extra options
  197.             $options[CURLOPT_POST] = true;
  198.             $options[CURLOPT_POSTFIELDS] = trim($var, '&');
  199.  
  200.             // Probaly Twitter's webserver doesn't support the Expect: 100-continue header. So we reset it.
  201.             $options[CURLOPT_HTTPHEADER] = array('Expect:');
  202.         }
  203.  
  204.         // init
  205.         $curl = curl_init();
  206.  
  207.         // set options
  208.         curl_setopt_array($curl, $options);
  209.  
  210.         // execute
  211.         $response = curl_exec($curl);
  212.         $headers = curl_getinfo($curl);
  213.  
  214.         // fetch errors
  215.         $errorNumber = curl_errno($curl);
  216.         $errorMessage = curl_error($curl);
  217.  
  218.         // close
  219.         curl_close($curl);
  220.  
  221.         // validate body
  222.         $xml = @simplexml_load_string($response);
  223.         if($xml !== false && isset($xml->error)) throw new TwitterException((string) $xml->error);
  224.  
  225.         // invalid headers
  226.         if(!in_array($headers['http_code'], array(0, 200)))
  227.         {
  228.             // should we provide debug information
  229.             if(self::DEBUG)
  230.             {
  231.                 // make it output proper
  232.                 echo '<pre>';
  233.  
  234.                 // dump the header-information
  235.                 var_dump($headers);
  236.  
  237.                 // dump the raw response
  238.                 var_dump($response);
  239.  
  240.                 // end proper format
  241.                 echo '</pre>';
  242.  
  243.                 // stop the script
  244.                 exit;
  245.             }
  246.  
  247.             // throw error
  248.             throw new TwitterException(null, (int) $headers['http_code']);
  249.         }
  250.  
  251.         // error?
  252.         if($errorNumber != '') throw new TwitterException($errorMessage, $errorNumber);
  253.  
  254.         // return
  255.         return $response;
  256.     }
  257.  
  258.  
  259.     /**
  260.      * Get the password
  261.      *
  262.      * @return  string
  263.      */
  264.     private function getPassword()
  265.     {
  266.         return (string) $this->password;
  267.     }
  268.  
  269.  
  270.     /**
  271.      * Get the timeout
  272.      *
  273.      * @return  int
  274.      */
  275.     public function getTimeOut()
  276.     {
  277.         return (int) $this->timeOut;
  278.     }
  279.  
  280.  
  281.     /**
  282.      * Get the useragent that will be used. Our version will be prepended to yours.
  283.      * It will look like: "PHP Akismet/<version> <your-user-agent>"
  284.      *
  285.      * @return  string
  286.      */
  287.     public function getUserAgent()
  288.     {
  289.         return (string) 'PHP Twitter/'. self::VERSION .' '. $this->userAgent;
  290.     }
  291.  
  292.  
  293.     /**
  294.      * Get the username
  295.      *
  296.      * @return  string
  297.      */
  298.     private function getUsername()
  299.     {
  300.         return (string) $this->username;
  301.     }
  302.  
  303.  
  304.     /**
  305.      * Converts a piece of XML into a message-array
  306.      *
  307.      * @return  array
  308.      * @param   SimpleXMLElement $xml
  309.      */
  310.     private function messageXMLToArray($xml)
  311.     {
  312.         // validate xml
  313.         if(!isset($xml->id, $xml->text, $xml->created_at, $xml->sender, $xml->recipient)) throw new TwitterException('Invalid xml for message.');
  314.  
  315.         // convert into array
  316.         $aMessage['id'] = (string) $xml->id;
  317.         $aMessage['created_at'] = (int) strtotime($xml->created_at);
  318.         $aMessage['text'] = (string) utf8_decode($xml->text);
  319.         $aMessage['sender'] = $this->userXMLToArray($xml->sender);
  320.         $aMessage['recipient'] = $this->userXMLToArray($xml->recipient);
  321.  
  322.         // return
  323.         return $aMessage;
  324.     }
  325.  
  326.  
  327.     /**
  328.      * Set password
  329.      *
  330.      * @return  void
  331.      * @param   string $password
  332.      */
  333.     private function setPassword($password)
  334.     {
  335.         $this->password = (string) $password;
  336.     }
  337.  
  338.  
  339.     /**
  340.      * Set the timeout
  341.      *
  342.      * @return  void
  343.      * @param   int $seconds    The timeout in seconds
  344.      */
  345.     public function setTimeOut($seconds)
  346.     {
  347.         $this->timeOut = (int) $seconds;
  348.     }
  349.  
  350.  
  351.     /**
  352.      * Get the useragent that will be used. Our version will be prepended to yours.
  353.      * It will look like: "PHP Akismet/<version> <your-user-agent>"
  354.      *
  355.      * @return  void
  356.      * @param   string $userAgent   Your user-agent, it should look like <app-name>/<app-version>
  357.      */
  358.     public function setUserAgent($userAgent)
  359.     {
  360.         $this->userAgent = (string) $userAgent;
  361.     }
  362.  
  363.  
  364.     /**
  365.      * Set username
  366.      *
  367.      * @return  void
  368.      * @param   string $username
  369.      */
  370.     private function setUsername($username)
  371.     {
  372.         $this->username = (string) $username;
  373.     }
  374.  
  375.  
  376.     /**
  377.      * Converts a piece of XML into a status-array
  378.      *
  379.      * @return  array
  380.      * @param   SimpleXMLElement $xml
  381.      */
  382.     private function statusXMLToArray($xml)
  383.     {
  384.         // validate xml
  385.         if(!isset($xml->id, $xml->text, $xml->created_at, $xml->source, $xml->truncated, $xml->in_reply_to_status_id, $xml->in_reply_to_user_id, $xml->favorited, $xml->user)) throw new TwitterException('Invalid xml for message.');
  386.  
  387.         // convert into array
  388.         $aStatus['id'] = (string) $xml->id;
  389.         $aStatus['created_at'] = (int) strtotime($xml->created_at);
  390.         $aStatus['text'] = utf8_decode((string) $xml->text);
  391.         $aStatus['source'] = (isset($xml->source)) ? (string) $xml->source : '';
  392.         $aStatus['user'] = $this->userXMLToArray($xml->user);
  393.         $aStatus['truncated'] = (isset($xml->truncated) && $xml->truncated == 'true');
  394.         $aStatus['favorited'] = (isset($xml->favorited) && $xml->favorited == 'true');
  395.         $aStatus['in_reply_to_status_id'] = (string) $xml->in_reply_to_status_id;
  396.         $aStatus['in_reply_to_user_id'] = (string) $xml->in_reply_to_user_id;
  397.  
  398.         // return
  399.         return $aStatus;
  400.     }
  401.  
  402.  
  403.     /**
  404.      * Converts a piece of XML into an user-array
  405.      *
  406.      * @return  array
  407.      * @param   SimpleXMLElement $xml
  408.      */
  409.     private function userXMLToArray($xml, $extended = false)
  410.     {
  411.         // validate xml
  412.         if(!isset($xml->id, $xml->name, $xml->screen_name, $xml->description, $xml->location, $xml->profile_image_url, $xml->url, $xml->protected, $xml->followers_count)) throw new TwitterException('Invalid xml for message.');
  413.  
  414.  
  415.         // convert into array
  416.         $aUser['id'] = (string) $xml->id;
  417.         $aUser['name'] = utf8_decode((string) $xml->name);
  418.         $aUser['screen_name'] = utf8_decode((string) $xml->screen_name);
  419.         $aUser['description'] = utf8_decode((string) $xml->description);
  420.         $aUser['location'] = utf8_decode((string) $xml->location);
  421.         $aUser['url'] = (string) $xml->url;
  422.         $aUser['protected'] = (isset($xml->protected) && $xml->protected == 'true');
  423.         $aUser['followers_count'] = (int) $xml->followers_count;
  424.         $aUser['profile_image_url'] = (string) $xml->profile_image_url;
  425.  
  426.         // extended info?
  427.         if($extended)
  428.         {
  429.             if(isset($xml->profile_background_color)) $aUser['profile_background_color'] = utf8_decode((string) $xml->profile_background_color);
  430.             if(isset($xml->profile_text_color)) $aUser['profile_text_color'] = utf8_decode((string) $xml->profile_text_color);
  431.             if(isset($xml->profile_link_color)) $aUser['profile_link_color'] = utf8_decode((string) $xml->profile_link_color);
  432.             if(isset($xml->profile_sidebar_fill_color)) $aUser['profile_sidebar_fill_color'] = utf8_decode((string) $xml->profile_sidebar_fill_color);
  433.             if(isset($xml->profile_sidebar_border_color)) $aUser['profile_sidebar_border_color'] = utf8_decode((string) $xml->profile_sidebar_border_color);
  434.             if(isset($xml->profile_background_image_url)) $aUser['profile_background_image_url'] = utf8_decode((string) $xml->profile_background_image_url);
  435.             if(isset($xml->profile_background_tile)) $aUser['profile_background_tile'] = (isset($xml->profile_background_tile) && $xml->profile_background_tile == 'true');
  436.             if(isset($xml->created_at)) $aUser['created_at'] = (int) strtotime((string) $xml->created_at);
  437.             if(isset($xml->following)) $aUser['following'] = (isset($xml->following) && $xml->following == 'true');
  438.             if(isset($xml->notifications)) $aUser['notifications'] = (isset($xml->notifications) && $xml->notifications == 'true');
  439.             if(isset($xml->statuses_count)) $aUser['statuses_count'] = (int) $xml->statuses_count;
  440.             if(isset($xml->friends_count)) $aUser['friends_count'] =  (int) $xml->friends_count;
  441.             if(isset($xml->favourites_count)) $aUser['favourites_count'] = (int) $xml->favourites_count;
  442.             if(isset($xml->time_zone)) $aUser['time_zone'] = utf8_decode((string) $xml->time_zone);
  443.             if(isset($xml->utc_offset)) $aUser['utc_offset'] = (int) $xml->utc_offset;
  444.         }
  445.  
  446.         // return
  447.         return (array) $aUser;
  448.     }
  449.  
  450.  
  451. // timeline methods
  452.     /**
  453.      * Returns the 20 most recent statuses from non-protected users who have set a custom user icon.
  454.      * Note that the public timeline is cached for 60 seconds so requesting it more often than that is a waste of resources.
  455.      *
  456.      * @return  array
  457.      */
  458.     public function getPublicTimeline()
  459.     {
  460.         // do the call
  461.         $response = $this->doCall('statuses/public_timeline.xml');
  462.  
  463.         // convert into xml-object
  464.         $xml = @simplexml_load_string($response);
  465.  
  466.         // validate
  467.         if($xml == false) throw new TwitterException('invalid body');
  468.  
  469.         // init var
  470.         $aStatuses = array();
  471.  
  472.         // loop statuses
  473.         foreach ($xml->status as $status) $aStatuses[] = $this->statusXMLToArray($status);
  474.  
  475.         // return
  476.         return (array) $aStatuses;
  477.     }
  478.  
  479.  
  480.     /**
  481.      * Returns the 20 most recent statuses posted by the authenticating user and that user's friends.
  482.      * This is the equivalent of /home on the Web.
  483.      *
  484.      * @return  array
  485.      * @param   string[optional] $sinceId   Returns only statuses with an id greater than (that is, more recent than) the specified $sinceId.
  486.      * @param   string[optional] $maxId Returns only statuses with an ID less than (that is, older than) or equal to the specified $maxId.
  487.      * @param   int[optional] $count    Specifies the number of statuses to retrieve. May not be greater than 200.
  488.      * @param   int[optional] $page
  489.      */
  490.     public function getFriendsTimeline($sinceId = null, $maxId = null, $count = null, $page = null)
  491.     {
  492.         // validate parameters
  493.         if($sinceId !== null && (string) $sinceId == '') throw new TwitterException('Invalid value for sinceId.');
  494.         if($maxId !== null && (string) $maxId == '') throw new TwitterException('Invalid value for maxId.');
  495.         if($count !== null && (int) $count > 200) throw new TwitterException('Count can\'t be larger then 200.');
  496.  
  497.         // build url
  498.         $aParameters = array();
  499.         if($sinceId !== null) $aParameters['since_id'] = (string) $sinceId;
  500.         if($maxId !== null) $aParameters['max_id'] = (string) $maxId;
  501.         if($count !== null) $aParameters['count'] = (int) $count;
  502.         if($page !== null) $aParameters['page'] = (int) $page;
  503.  
  504.         // do the call
  505.         $response = $this->doCall('statuses/friends_timeline.xml', $aParameters, true, false);
  506.  
  507.         // convert into xml-object
  508.         $xml = @simplexml_load_string($response);
  509.  
  510.         // validate
  511.         if($xml == false) throw new TwitterException('invalid body');
  512.  
  513.         // init var
  514.         $aStatuses = array();
  515.  
  516.         // loop statuses
  517.         foreach ($xml->status as $status) $aStatuses[] = $this->statusXMLToArray($status);
  518.  
  519.         // return
  520.         return (array) $aStatuses;
  521.     }
  522.  
  523.  
  524.     /**
  525.      * Returns the 20 most recent statuses posted from the authenticating user. It's also possible to request another user's timeline via the id parameter below.
  526.      * This is the equivalent of the Web /archive page for your own user, or the profile page for a third party.
  527.      *
  528.      * @return  array
  529.      * @param   string[optional] $id    Specifies the id or screen name of the user for whom to return the friends_timeline.
  530.      * @param   string[optional] $sinceId   Returns only statuses with an id greater than (that is, more recent than) the specified $sinceId.
  531.      * @param   string[optional] $maxId Returns only statuses with an ID less than (that is, older than) or equal to the specified $maxId.
  532.      * @param   int[optional] $count    Specifies the number of statuses to retrieve. May not be greater than 200.
  533.      * @param   int[optional] $page Specifies the page or results to retrieve.
  534.      */
  535.     public function getUserTimeline($id = null, $sinceId = null, $maxId = null, $count = null, $page = null)
  536.     {
  537.         // validate parameters
  538.         if($sinceId !== null && (string) $sinceId == '') throw new TwitterException('Invalid value for sinceId.');
  539.         if($maxId !== null && (string) $maxId == '') throw new TwitterException('Invalid value for maxId.');
  540.         if($count !== null && (int) $count > 200) throw new TwitterException('Count can\'t be larger then 200.');
  541.  
  542.         // build parameters
  543.         $aParameters = array();
  544.         if($sinceId !== null) $aParameters['since_id'] = (string) $sinceId;
  545.         if($maxId !== null) $aParameters['max_id'] = (string) $maxId;
  546.         if($count !== null) $aParameters['count'] = (int) $count;
  547.         if($page !== null) $aParameters['page'] = (int) $page;
  548.  
  549.         // build url
  550.         $url = 'statuses/user_timeline.xml';
  551.         if($id !== null) $url = 'statuses/user_timeline/'. urlencode($id) .'.xml';
  552.  
  553.         // do the call
  554.         $response = $this->doCall($url, $aParameters, true, false);
  555.  
  556.         // convert into xml-object
  557.         $xml = @simplexml_load_string($response);
  558.  
  559.         // validate
  560.         if($xml == false) throw new TwitterException('invalid body');
  561.  
  562.         // init var
  563.         $aStatuses = array();
  564.  
  565.         // loop statuses
  566.         foreach ($xml->status as $status) $aStatuses[] = $this->statusXMLToArray($status);
  567.  
  568.         // return
  569.         return (array) $aStatuses;
  570.     }
  571.  
  572.  
  573.     /**
  574.      * Returns the 20 most recent mentions (status containing @username) for the authenticating user.
  575.      *
  576.      * @return  array
  577.      * @param   string[optional] $sinceId   Returns only statuses with an id greater than (that is, more recent than) the specified $sinceId.
  578.      * @param   string[optional] $maxId Returns only statuses with an ID less than (that is, older than) or equal to the specified $maxId.
  579.      * @param   int[optional] $count    Specifies the number of statuses to retrieve. May not be greater than 200.
  580.      * @param   int[optional] $page Specifies the page or results to retrieve.
  581.      */
  582.     public function getMentionsReplies($sinceId = null, $maxId = null, $count = null, $page = null)
  583.     {
  584.         // validate parameters
  585.         if($sinceId !== null && (string) $sinceId == '') throw new TwitterException('Invalid value for sinceId.');
  586.         if($maxId !== null && (string) $maxId == '') throw new TwitterException('Invalid value for maxId.');
  587.         if($count !== null && (int) $count > 200) throw new TwitterException('Count can\'t be larger then 200.');
  588.  
  589.         // build parameters
  590.         $aParameters = array();
  591.         if($sinceId !== null) $aParameters['since_id'] = (string) $sinceId;
  592.         if($maxId !== null) $aParameters['max_id'] = (string) $maxId;
  593.         if($count !== null) $aParameters['count'] = (int) $count;
  594.         if($page !== null) $aParameters['page'] = (int) $page;
  595.  
  596.         // do the call
  597.         $response = $this->doCall('statuses/mentions.xml', $aParameters, true, false);
  598.  
  599.         // convert into xml-object
  600.         $xml = @simplexml_load_string($response);
  601.  
  602.         // validate
  603.         if($xml == false) throw new TwitterException('invalid body');
  604.  
  605.         // init var
  606.         $aStatuses = array();
  607.  
  608.         // loop statuses
  609.         foreach ($xml->status as $status) $aStatuses[] = $this->statusXMLToArray($status);
  610.  
  611.         // return
  612.         return (array) $aStatuses;
  613.     }
  614.  
  615.  
  616. // status methods
  617.     /**
  618.      * Returns a single status, specified by the id parameter below.
  619.      *
  620.      * @return  array
  621.      * @param   int $id The numerical id of the status you're trying to retrieve.
  622.      */
  623.     public function getStatus($id)
  624.     {
  625.         // redefine
  626.         $id = (string) $id;
  627.  
  628.         // build url
  629.         $url = 'statuses/show/'. urlencode($id) .'.xml';
  630.  
  631.         // do the call
  632.         $response = $this->doCall($url);
  633.  
  634.         // convert into xml-object
  635.         $xml = @simplexml_load_string($response);
  636.  
  637.         // validate
  638.         if($xml == false) throw new TwitterException('invalid body');
  639.  
  640.         // return
  641.         return (array) $this->statusXMLToArray($xml);
  642.     }
  643.  
  644.  
  645.     /**
  646.      * Updates the authenticating user's status.
  647.      * A status update with text identical to the authenticating user's current status will be ignored.
  648.      *
  649.      * @return  array
  650.      * @param   string $status  The text of your status update. Should not be more than 140 characters.
  651.      * @param   int[optional] $inReplyToId  The id of an existing status that the status to be posted is in reply to.
  652.      */
  653.     public function updateStatus($status, $inReplyToId = null)
  654.     {
  655.         // redefine
  656.         $status = (string) $status;
  657.  
  658.         // validate parameters
  659.         if(strlen($status) > 140) throw new TwitterException('Maximum 140 characters allowed for status.');
  660.  
  661.         // build parameters
  662.         $aParameters = array();
  663.         $aParameters['status'] = $status;
  664.         if($inReplyToId !== null) $aParameters['in_reply_to_status_id'] = (int) $inReplyToId;
  665.  
  666.         // do the call
  667.         $response = $this->doCall('statuses/update.xml', $aParameters, true);
  668.  
  669.         // convert into xml-object
  670.         $xml = @simplexml_load_string($response);
  671.  
  672.         // validate
  673.         if($xml == false) throw new TwitterException('invalid body');
  674.  
  675.         // return
  676.         return (array) $this->statusXMLToArray($xml);
  677.     }
  678.  
  679.  
  680.     /**
  681.      * Destroys the status specified by the required $id parameter.
  682.      * The authenticating user must be the author of the specified status.
  683.      *
  684.      * @return  array
  685.      * @param   int[optional] $id
  686.      */
  687.     public function deleteStatus($id)
  688.     {
  689.         // redefine
  690.         $id = (string) $id;
  691.  
  692.         // build url
  693.         $url = 'statuses/destroy/'. urlencode($id) .'.xml';
  694.  
  695.         // build parameters
  696.         $aParameters = array();
  697.         $aParameters['id'] = $id;
  698.  
  699.         // do the call
  700.         $response = $this->doCall($url, $aParameters, true);
  701.  
  702.         // convert into xml-object
  703.         $xml = @simplexml_load_string($response);
  704.  
  705.         // validate
  706.         if($xml == false) throw new TwitterException('invalid body');
  707.  
  708.         // return
  709.         return (array) $this->statusXMLToArray($xml);
  710.     }
  711.  
  712.  
  713. // user methods
  714.     /**
  715.      * Returns extended information of a given user, specified by id or screen name.
  716.      * This information includes design settings, so third party developers can theme their widgets according to a given user's preferences.
  717.      * You must be properly authenticated to request the page of a protected user.
  718.      *
  719.      * @return  array
  720.      * @param   string $id  The id or screen name of a user.
  721.      */
  722.     public function getUser($id)
  723.     {
  724.         // build parameters
  725.         $aParameters = array();
  726.  
  727.         // build url
  728.         $url = 'users/show/'. urlencode($id) .'.xml';
  729.  
  730.         // do the call
  731.         $response = $this->doCall($url, $aParameters, true, false);
  732.  
  733.         // convert into xml-object
  734.         $xml = @simplexml_load_string($response);
  735.  
  736.         // validate
  737.         if($xml == false) throw new TwitterException('invalid body');
  738.  
  739.         // return
  740.         return (array) $this->userXMLToArray($xml, true);
  741.     }
  742.  
  743.  
  744.     /**
  745.      * Returns up to 100 of the authenticating user's friends who have most recently updated.
  746.      * It's also possible to request another user's recent friends list via the $id parameter.
  747.      *
  748.      * @return  array
  749.      * @param   string[optional] $id    The id or screen name of the user for whom to request a list of friends.
  750.      * @param   int[optional] $page Specifies the page of friends to receive.
  751.      */
  752.     public function getFriends($id = null, $cursor = null)
  753.     {
  754.         // build parameters
  755.         $aParameters = array();
  756.         if($page !== null) $aParameters['page'] = (int) $page;
  757.  
  758.         // build url
  759.         $url = 'statuses/friends.xml';
  760.         if($id !== null) $url = 'statuses/friends/'. urlencode($id) .'.xml';
  761.  
  762.         // do the call
  763.         $response = $this->doCall($url, $aParameters, true, false);
  764.  
  765.         // convert into xml-object
  766.         $xml = @simplexml_load_string($response);
  767.  
  768.         // validate
  769.         if($xml == false) throw new TwitterException('invalid body');
  770.  
  771.         // init var
  772.         $aUsers = array();
  773.  
  774.         // loop statuses
  775.         foreach ($xml->user as $user) $aUsers[] = $this->userXMLToArray($user);
  776.  
  777.         // return
  778.         return (array) $aUsers;
  779.     }
  780.  
  781.  
  782.     /**
  783.      * Returns the authenticating user's followers.
  784.      *
  785.      * @return  array
  786.      * @param   string[optional] $id     The id or screen name of the user for whom to request a list of followers.
  787.      * @param   int[optional] $page
  788.      */
  789.     public function getFollowers($id = null, $page = null)
  790.     {
  791.         // build parameters
  792.         $aParameters = array();
  793.         if($page !== null) $aParameters['page'] = (int) $page;
  794.  
  795.         // build url
  796.         $url = 'statuses/followers.xml';
  797.         if($id !== null) $url = 'statuses/followers/'. urlencode($id) .'.xml';
  798.  
  799.         // do the call
  800.         $response = $this->doCall($url, $aParameters, true, false);
  801.  
  802.         // convert into xml-object
  803.         $xml = @simplexml_load_string($response);
  804.  
  805.         // validate
  806.         if($xml == false) throw new TwitterException('invalid body');
  807.  
  808.         // init var
  809.         $aUsers = array();
  810.  
  811.         // loop statuses
  812.         foreach ($xml->user as $user) $aUsers[] = $this->userXMLToArray($user);
  813.  
  814.         // return
  815.         return (array) $aUsers;
  816.     }
  817.  
  818.  
  819.  
  820. // direct message methods
  821.     /**
  822.      * Returns a list of the 20 most recent direct messages sent to the authenticating user.
  823.      *
  824.      * @return  array
  825.      * @param   string[optional] $sinceId   Returns only direct messages with an id greater than (that is, more recent than) the specified $sinceId.
  826.      * @param   string[optional] $maxId Returns only statuses with an ID less than (that is, older than) or equal to the specified $maxId.
  827.      * @param   int[optional] $count    Specifies the number of statuses to retrieve. May not be greater than 200.
  828.      * @param   int[optional] $page
  829.      */
  830.     public function getDirectMessages($sinceId = null, $maxId = null, $count = null, $page = null)
  831.     {
  832.         // validate parameters
  833.         if($sinceId !== null && (string) $sinceId == '') throw new TwitterException('Invalid value for sinceId.');
  834.         if($maxId !== null && (string) $maxId == '') throw new TwitterException('Invalid value for maxId.');
  835.         if($count !== null && (int) $count > 200) throw new TwitterException('Count can\'t be larger then 200.');
  836.  
  837.         // build url
  838.         $aParameters = array();
  839.         if($sinceId !== null) $aParameters['since_id'] = (string) $sinceId;
  840.         if($maxId !== null) $aParameters['max_id'] = (string) $maxId;
  841.         if($count !== null) $aParameters['count'] = (int) $count;
  842.         if($page !== null) $aParameters['page'] = (int) $page;
  843.  
  844.         // do the call
  845.         $response = $this->doCall('direct_messages.xml', $aParameters, true, false);
  846.  
  847.         // convert into xml-object
  848.         $xml = @simplexml_load_string($response);
  849.  
  850.         // validate
  851.         if($xml == false) throw new TwitterException('invalid body');
  852.  
  853.         // init var
  854.         $aDirectMessages = array();
  855.  
  856.         // loop statuses
  857.         foreach ($xml->direct_message as $message) $aDirectMessages[] = $this->messageXMLToArray($message);
  858.  
  859.         // return
  860.         return (array) $aDirectMessages;
  861.     }
  862.  
  863.  
  864.     /**
  865.      * Returns a list of the 20 most recent direct messages sent by the authenticating user.
  866.      *
  867.      * @return  array
  868.      * @param   string[optional] $sinceId   Returns only sent direct messages with an id greater than (that is, more recent than) the specified $sinceId.
  869.      * @param   string[optional] $maxId Returns only statuses with an ID less than (that is, older than) or equal to the specified $maxId.
  870.      * @param   int[optiona] $count Specifies the number of direct messages to retrieve. May not be greater than 200.
  871.      * @param   int[optional] $page
  872.      */
  873.     public function getSentDirectMessages($sinceId = null, $maxId = null, $count = null, $page = null)
  874.     {
  875.         // validate parameters
  876.         if($sinceId !== null && (string) $sinceId == '') throw new TwitterException('Invalid value for sinceId.');
  877.         if($maxId !== null && (string) $maxId == '') throw new TwitterException('Invalid value for maxId.');
  878.         if($count !== null && (int) $count > 200) throw new TwitterException('Count can\'t be larger then 200.');
  879.  
  880.         // build url
  881.         $aParameters = array();
  882.         if($sinceId !== null) $aParameters['since_id'] = (string) $sinceId;
  883.         if($maxId !== null) $aParameters['max_id'] = (string) $maxId;
  884.         if($count !== null) $aParameters['count'] = (int) $count;
  885.         if($page !== null) $aParameters['page'] = (int) $page;
  886.  
  887.         // do the call
  888.         $response = $this->doCall('direct_messages/sent.xml', $aParameters, true, false);
  889.  
  890.         // convert into xml-object
  891.         $xml = @simplexml_load_string($response);
  892.  
  893.         // validate
  894.         if($xml == false) throw new TwitterException('invalid body');
  895.  
  896.         // init var
  897.         $aDirectMessages = array();
  898.  
  899.         // loop statuses
  900.         foreach ($xml->direct_message as $message) $aDirectMessages[] = $this->messageXMLToArray($message);
  901.  
  902.         // return
  903.         return (array) $aDirectMessages;
  904.     }
  905.  
  906.  
  907.     /**
  908.      * Sends a new direct message to the specified user from the authenticating user.
  909.      *
  910.      * @return  array
  911.      * @param   string $id  The id or screen name of the recipient user.
  912.      * @param   string $text    The text of your direct message. Keep it under 140 characters.
  913.      */
  914.     public function sendDirectMessage($id, $text)
  915.     {
  916.         // redefine
  917.         $id = (string) $id;
  918.         $text = (string) $text;
  919.  
  920.         // validate parameters
  921.         if(strlen($text) > 140) throw new TwitterException('Maximum 140 characters allowed for status.');
  922.  
  923.         // build parameters
  924.         $aParameters = array();
  925.         $aParameters['user'] = $id;
  926.         $aParameters['text'] = $text;
  927.  
  928.         // do the call
  929.         $response = $this->doCall('direct_messages/new.xml', $aParameters, true);
  930.  
  931.         // convert into xml-object
  932.         $xml = @simplexml_load_string($response);
  933.  
  934.         // validate
  935.         if($xml == false) throw new TwitterException('invalid body');
  936.  
  937.         // return
  938.         return (array) $this->messageXMLToArray($xml);
  939.     }
  940.  
  941.  
  942.     /**
  943.      * Destroys the direct message.
  944.      * The authenticating user must be the recipient of the specified direct message.
  945.      *
  946.      * @return  array
  947.      * @param   string $id
  948.      */
  949.     public function deleteDirectMessage($id)
  950.     {
  951.         // redefine
  952.         $id = (string) $id;
  953.  
  954.         // build url
  955.         $url = 'direct_messages/destroy/'. urlencode($id) .'.xml';
  956.  
  957.         // build parameters
  958.         $aParameters = array();
  959.         $aParameters['id'] = $id;
  960.  
  961.         // do the call
  962.         $response = $this->doCall($url, $aParameters, true);
  963.  
  964.         // convert into xml-object
  965.         $xml = @simplexml_load_string($response);
  966.  
  967.         // validate
  968.         if($xml == false) throw new TwitterException('invalid body');
  969.  
  970.         // return
  971.         return (array) $this->messageXMLToArray($xml);
  972.     }
  973.  
  974.  
  975. // friendship methods
  976.     /**
  977.      * Befriends the user specified in the id parameter as the authenticating user.
  978.      *
  979.      * @return  array
  980.      * @param   string $id  The id or screen name of the user to befriend.
  981.      * @param   bool[optional] $follow  Enable notifications for the target user in addition to becoming friends.
  982.      */
  983.     public function createFriendship($id, $follow = true)
  984.     {
  985.         // redefine
  986.         $id = (string) $id;
  987.         $follow = (bool) $follow;
  988.  
  989.         // build url
  990.         $url = 'friendships/create/'. urlencode($id) .'.xml';
  991.  
  992.         // build parameters
  993.         $aParameters = array();
  994.         $aParameters['id'] = $id;
  995.         if($follow) $aParameters['follow'] = $follow;
  996.  
  997.         // do the call
  998.         $response = $this->doCall($url, $aParameters, true);
  999.  
  1000.         // convert into xml-object
  1001.         $xml = @simplexml_load_string($response);
  1002.  
  1003.         // validate
  1004.         if($xml == false) throw new TwitterException('invalid body');
  1005.  
  1006.         // return
  1007.         return (array) $this->userXMLToArray($xml);
  1008.     }
  1009.  
  1010.  
  1011.     /**
  1012.      * Discontinues friendship with the user.
  1013.      *
  1014.      * @return  array
  1015.      * @param   string $id
  1016.      */
  1017.     public function deleteFriendship($id)
  1018.     {
  1019.         // redefine
  1020.         $id = (string) $id;
  1021.  
  1022.         // build url
  1023.         $url = 'friendships/destroy/'. urlencode($id) .'.xml';
  1024.  
  1025.         // build parameters
  1026.         $aParameters = array();
  1027.         $aParameters['id'] = $id;
  1028.  
  1029.         // do the call
  1030.         $response = $this->doCall($url, $aParameters, true);
  1031.  
  1032.         // convert into xml-object
  1033.         $xml = @simplexml_load_string($response);
  1034.  
  1035.         // validate
  1036.         if($xml == false) throw new TwitterException('invalid body');
  1037.  
  1038.         // return
  1039.         return (array) $this->userXMLToArray($xml);
  1040.     }
  1041.  
  1042.  
  1043.     /**
  1044.      * Tests if a friendship exists between two users.
  1045.      *
  1046.      * @return  bool
  1047.      * @param   string $id  The id or screen_name of the first user to test friendship for.
  1048.      * @param   string $friendId    The id or screen_name of the second user to test friendship for.
  1049.      */
  1050.     public function existsFriendship($id, $friendId)
  1051.     {
  1052.         // redefine
  1053.         $id = (string) $id;
  1054.         $friendId = (string) $friendId;
  1055.  
  1056.         // build parameters
  1057.         $aParameters = array();
  1058.         $aParameters['user_a'] = (string) $id;
  1059.         $aParameters['user_b'] = (string) $friendId;
  1060.  
  1061.         // do the call
  1062.         $response = $this->doCall('friendships/exists.xml', $aParameters, true, false);
  1063.  
  1064.         // convert into xml-object
  1065.         $xml = @simplexml_load_string($response);
  1066.  
  1067.         // validate
  1068.         if($xml == false) throw new TwitterException('invalid body');
  1069.  
  1070.         // return
  1071.         return (bool) ($xml == 'true');
  1072.     }
  1073.  
  1074.  
  1075.     /**
  1076.      * Returns detailed information about the relationship between two users.
  1077.      *
  1078.      * @return  array
  1079.      * @param   string $id  The id or screen name of the subject user.
  1080.      * @param   string $friendId    The id or screen name of the target user.
  1081.      */
  1082.     public function getFriendship($id, $friendId)
  1083.     {
  1084.         // redefine
  1085.         $id = (string) $id;
  1086.         $friendId = (string) $friendId;
  1087.  
  1088.         // build parameters
  1089.         $aParameters = array();
  1090.         if((bool) preg_match("/^[0-9]+$/", $id)) $aParameters['source_id'] = $id;
  1091.         else $aParameters['source_screen_name'] = (string) $id;
  1092.         if((bool) preg_match("/^[0-9]+$/", $friendId)) $aParameters['target_id'] = $friendId;
  1093.         else $aParameters['target_screen_name'] = $friendId;
  1094.  
  1095.         // do the call
  1096.         $response = $this->doCall('friendships/show.xml', $aParameters, true, false);
  1097.  
  1098.         // convert into xml-object
  1099.         $xml = @simplexml_load_string($response);
  1100.  
  1101.         // validate
  1102.         if($xml == false) throw new TwitterException('invalid body');
  1103.  
  1104.         $aReturn = array();
  1105.         $aReturn['target']['id'] = (string) $xml->target->id;
  1106.         $aReturn['target']['screen_name'] = (string) utf8_decode($xml->target->screen_name);
  1107.         $aReturn['target']['following'] = (bool) ((string) $xml->target->following == 'true');
  1108.         $aReturn['target']['followed_by'] = (bool) ((string) $xml->target->followed_by == 'true');
  1109.  
  1110.         $aReturn['source']['id'] = (string) $xml->source->id;
  1111.         $aReturn['source']['screen_name'] = (string) utf8_decode($xml->source->screen_name);
  1112.         $aReturn['source']['following'] = (bool) ((string) $xml->source->following == 'true');
  1113.         $aReturn['source']['followed_by'] = (bool) ((string) $xml->source->followed_by == 'true');
  1114.         $aReturn['source']['notifications_enabled'] = (bool) ((string) $xml->source->notifications_enabled == 'true');
  1115.         $aReturn['source']['blocking'] = (bool) ((string) $xml->source->blocking == 'true');
  1116.  
  1117.         // return
  1118.         return (array) $aReturn;
  1119.     }
  1120.  
  1121.  
  1122. // social grap methods
  1123.     /**
  1124.      * Returns an array of numeric IDs for every user the specified user is following.
  1125.      *
  1126.      * @return  array
  1127.      * @param   string[optional] $id    The id or screen name of the user for whom to request a list of friends.
  1128.      * @param   int[optional] $page Specifies the page number of the results beginning at 1. A single page contains 5000 ids. This is recommended for users with large ID lists. If not provided all ids are returned. (Please note that the result set isn't guaranteed to be 5000 every time as suspended users will be filtered out.)
  1129.      */
  1130.     public function getFriendIds($id = null, $page = null)
  1131.     {
  1132.         // build parameters
  1133.         $aParameters = array();
  1134.         if($page !== null) $aParameters['page'] = (int) $page;
  1135.  
  1136.         // build url
  1137.         $url = 'friends/ids.xml';
  1138.         if($id !== null) $url = 'friends/ids/'. urlencode($id) .'.xml';
  1139.  
  1140.         // do the call
  1141.         $response = $this->doCall($url, $aParameters, true, false);
  1142.  
  1143.         // convert into xml-object
  1144.         $xml = @simplexml_load_string($response);
  1145.  
  1146.         // validate
  1147.         if($xml == false) throw new TwitterException('invalid body');
  1148.  
  1149.         // init var
  1150.         $aReturn = array();
  1151.  
  1152.         if(isset($xml->id))
  1153.         {
  1154.             // loop ids
  1155.             foreach($xml->id as $id) $aReturn[] = (string) $id;
  1156.         }
  1157.  
  1158.         // return
  1159.         return (array) $aReturn;
  1160.     }
  1161.  
  1162.  
  1163.     /**
  1164.      * Returns an array of numeric IDs for every user following the specified user.
  1165.      *
  1166.      * @return  array
  1167.      * @param   string[optional] $id    The id or screen name  of the user to retrieve the friends ID list for.
  1168.      * @param   int[optional] $page Specifies the page number of the results beginning at 1. A single page contains 5000 ids. This is recommended for users with large ID lists. If not provided all ids are returned. (Please note that the result set isn't guaranteed to be 5000 every time as suspended users will be filtered out.)
  1169.      */
  1170.     public function getFollowerIds($id = null, $page = null)
  1171.     {
  1172.         // build parameters
  1173.         $aParameters = array();
  1174.         if($page !== null) $aParameters['page'] = (int) $page;
  1175.  
  1176.         // build url
  1177.         $url = 'followers/ids.xml';
  1178.         if($id !== null) $url = 'followers/ids/'. urlencode($id) .'.xml';
  1179.  
  1180.         // do the call
  1181.         $response = $this->doCall($url, $aParameters, true, false);
  1182.  
  1183.         // convert into xml-object
  1184.         $xml = @simplexml_load_string($response);
  1185.  
  1186.         // validate
  1187.         if($xml == false) throw new TwitterException('invalid body');
  1188.  
  1189.         // init var
  1190.         $aReturn = array();
  1191.  
  1192.         if(isset($xml->id))
  1193.         {
  1194.             // loop ids
  1195.             foreach($xml->id as $id) $aReturn[] = (string) $id;
  1196.         }
  1197.  
  1198.         // return
  1199.         return (array) $aReturn;
  1200.     }
  1201.  
  1202.  
  1203. // account methods
  1204.     /**
  1205.      * Verifies your credentials
  1206.      * Use this method to test if supplied user credentials are valid.
  1207.      *
  1208.      * @return  bool
  1209.      */
  1210.     public function verifyCredentials()
  1211.     {
  1212.         try
  1213.         {
  1214.             // do the call
  1215.             $response = $this->doCall('account/verify_credentials.xml', array(), true);
  1216.  
  1217.             // content was found
  1218.             if($response != '') return true;
  1219.  
  1220.             // no content
  1221.             else return false;
  1222.         }
  1223.         catch (Exception $e)
  1224.         {
  1225.             if($e->getCode() == 401 || $e->getMessage() == 'Could not authenticate you.') return false;
  1226.             else throw $e;
  1227.         }
  1228.     }
  1229.  
  1230.  
  1231.     /**
  1232.      * Returns the remaining number of API requests available to the requesting user before the API limit is reached for the current hour.
  1233.      *
  1234.      * @return  array
  1235.      */
  1236.     public function getRateLimitStatus()
  1237.     {
  1238.         // do the call
  1239.         $response = $this->doCall('account/rate_limit_status.xml', array(), true);
  1240.  
  1241.         // convert into xml-object
  1242.         $xml = @simplexml_load_string($response);
  1243.  
  1244.         // validate
  1245.         if($xml == false) throw new TwitterException('invalid body');
  1246.  
  1247.         // create response
  1248.         if(isset($xml->{'remaining-hits'})) $aResponse['remaining_hits'] = (int) $xml->{'remaining-hits'};
  1249.         if(isset($xml->{'reset-time-in-seconds'})) $aResponse['reset_time'] = (int) $xml->{'reset-time-in-seconds'};
  1250.         if(isset($xml->{'hourly-limit'})) $aResponse['hourly_limit'] = (int) $xml->{'hourly-limit'};
  1251.  
  1252.         // return
  1253.         return $aResponse;
  1254.     }
  1255.  
  1256.  
  1257.     /**
  1258.      * Ends the session of the authenticating user, returning a null cookie.
  1259.      * Use this method to sign users out of client-facing applications like widgets.
  1260.      *
  1261.      * @return  void
  1262.      */
  1263.     public function endSession()
  1264.     {
  1265.         $this->doCall('account/end_session');
  1266.     }
  1267.  
  1268.  
  1269.     /**
  1270.      * Sets which device Twitter delivers updates to for the authenticating user.
  1271.      * Sending none as the device parameter will disable IM or SMS updates.
  1272.      *
  1273.      * @return  array
  1274.      * @param   string $device  Must be one of: sms, im, none.
  1275.      */
  1276.     public function updateDeliveryDevice($device)
  1277.     {
  1278.         // redefine
  1279.         $device = (string) $device;
  1280.  
  1281.         // init vars
  1282.         $aPossibleDevices = array('sms', 'im', 'none');
  1283.  
  1284.         // validate parameters
  1285.         if(!in_array($device, $aPossibleDevices)) throw new TwitterException('Invalid value for device. Possible values are: '. implode(', ', $aPossibleDevices) .'.');
  1286.  
  1287.         // build url
  1288.         $url = 'account/update_delivery_device.xml';
  1289.  
  1290.         // build parameters
  1291.         $aParameters = array();
  1292.         $aParameters['device'] = $device;
  1293.  
  1294.         // do the call
  1295.         $response = $this->doCall($url, $aParameters, true);
  1296.  
  1297.         // convert into xml-object
  1298.         $xml = @simplexml_load_string($response);
  1299.  
  1300.         // validate
  1301.         if($xml == false) throw new TwitterException('invalid body');
  1302.  
  1303.         // return
  1304.         return (array) $this->userXMLToArray($xml);
  1305.     }
  1306.  
  1307.  
  1308.     /**
  1309.      * Sets one or more hex values that control the color scheme of the authenticating user's profile page on twitter.com.
  1310.      * Only the parameters specified will be updated.
  1311.      *
  1312.      * @return  array
  1313.      * @param   string[optiona] $backgroundColor
  1314.      * @param   string[optiona] $textColor
  1315.      * @param   string[optiona] $linkColor
  1316.      * @param   string[optiona] $sidebarBackgroundColor
  1317.      * @param   string[optiona] $sidebarBorderColor
  1318.      */
  1319.     public function updateProfileColors($backgroundColor = null, $textColor = null, $linkColor = null, $sidebarBackgroundColor = null, $sidebarBorderColor = null)
  1320.     {
  1321.         // validate parameters
  1322.         if($backgroundColor === null && $textColor === null && $linkColor === null && $sidebarBackgroundColor === null && $sidebarBorderColor === null) throw new TwitterException('Specify at least one parameter.');
  1323.         if($backgroundColor !== null && (strlen($backgroundColor) < 3 || strlen($backgroundColor) > 6)) throw new TwitterException('Invalid color for background color.');
  1324.         if($textColor !== null && (strlen($textColor) < 3 || strlen($textColor) > 6)) throw new TwitterException('Invalid color for text color.');
  1325.         if($linkColor !== null && (strlen($linkColor) < 3 || strlen($linkColor) > 6)) throw new TwitterException('Invalid color for link color.');
  1326.         if($sidebarBackgroundColor !== null && (strlen($sidebarBackgroundColor) < 3 || strlen($sidebarBackgroundColor) > 6)) throw new TwitterException('Invalid color for sidebar background color.');
  1327.         if($sidebarBorderColor !== null && (strlen($sidebarBorderColor) < 3 || strlen($sidebarBorderColor) > 6)) throw new TwitterException('Invalid color for sidebar border color.');
  1328.  
  1329.         // build parameters
  1330.         if($backgroundColor !== null) $aParameters['profile_background_color'] = (string) $backgroundColor;
  1331.         if($textColor !== null) $aParameters['profile_text_color'] = (string) $textColor;
  1332.         if($linkColor !== null) $aParameters['profile_link_color'] = (string) $linkColor;
  1333.         if($sidebarBackgroundColor !== null) $aParameters['profile_sidebar_fill_color'] = (string) $sidebarBackgroundColor;
  1334.         if($sidebarBorderColor !== null) $aParameters['profile_sidebar_border_color'] = (string) $sidebarBorderColor;
  1335.  
  1336.         // make the call
  1337.         $response = $this->doCall('account/update_profile_colors.xml', $aParameters, true);
  1338.  
  1339.         // convert into xml-object
  1340.         $xml = @simplexml_load_string($response);
  1341.  
  1342.         // validate
  1343.         if($xml == false) throw new TwitterException('invalid body');
  1344.  
  1345.         // return
  1346.         return (array) $this->userXMLToArray($xml, true);
  1347.     }
  1348.  
  1349.  
  1350.     /**
  1351.      * Updates the authenticating user's profile image.
  1352.      * Expects raw multipart data, not a URL to an image.
  1353.      *
  1354.      * @remark  not implemented yet, feel free to code
  1355.      * @return  void
  1356.      * @param   string $image
  1357.      */
  1358.     public function updateProfileImage($image)
  1359.     {
  1360.         throw new TwitterException(null, 501);
  1361.  
  1362.         // build parameters
  1363.         $aParameters = array();
  1364.         $aParameters['image'] = (string) $image;
  1365.  
  1366.         // make the call
  1367.         $response = $this->doCall('account/update_profile_image.xml', $aParameters, true);
  1368.  
  1369.         // convert into xml-object
  1370.         $xml = @simplexml_load_string($response);
  1371.  
  1372.         // validate
  1373.         if($xml == false) throw new TwitterException('invalid body');
  1374.  
  1375.         // return
  1376.         return (array) $this->userXMLToArray($xml, true);
  1377.     }
  1378.  
  1379.  
  1380.     /**
  1381.      * Updates the authenticating user's profile background image.
  1382.      * Expects raw multipart data, not a URL to an image.
  1383.      *
  1384.      * @remark  not implemented yet, feel free to code
  1385.      * @return  void
  1386.      * @param   string $image
  1387.      */
  1388.     public function updateProfileBackgroundImage($image)
  1389.     {
  1390.         throw new TwitterException(null, 501);
  1391.  
  1392.         // build parameters
  1393.         $aParameters = array();
  1394.         $aParameters['image'] = (string) $image;
  1395.  
  1396.         // make the call
  1397.         $response = $this->doCall('account/update_profile_background_image.xml', $aParameters, true);
  1398.  
  1399.         // convert into xml-object
  1400.         $xml = @simplexml_load_string($response);
  1401.  
  1402.         // validate
  1403.         if($xml == false) throw new TwitterException('invalid body');
  1404.  
  1405.         // return
  1406.         return (array) $this->userXMLToArray($xml, true);
  1407.     }
  1408.  
  1409.  
  1410.     /**
  1411.      * Sets values that users are able to set under the "Account" tab of their settings page.
  1412.      * Only the parameters specified will be updated.
  1413.      *
  1414.      * @return  array
  1415.      * @param   string[optional] $name
  1416.      * @param   string[optional] $email
  1417.      * @param   string[optional] $url
  1418.      * @param   string[optional] $location
  1419.      * @param   string[optional] $description
  1420.      */
  1421.     public function updateProfile($name = null, $email = null, $url = null, $location = null, $description = null)
  1422.     {
  1423.         // validate parameters
  1424.         if($name === null && $email === null && $url === null && $location === null && $description === null) throw new TwitterException('Specify at least one parameter.');
  1425.         if($name !== null && strlen($name) > 40) throw new TwitterException('Maximum 40 characters allowed for name.');
  1426.         if($email !== null && strlen($email) > 40) throw new TwitterException('Maximum 40 characters allowed for email.');
  1427.         if($url !== null && strlen($url) > 100) throw new TwitterException('Maximum 100 characters allowed for url.');
  1428.         if($location !== null && strlen($location) > 30) throw new TwitterException('Maximum 30 characters allowed for location.');
  1429.         if($description !== null && strlen($description) > 160) throw new TwitterException('Maximum 160 characters allowed for description.');
  1430.  
  1431.         // build parameters
  1432.         if($name !== null) $aParameters['name'] = (string) $name;
  1433.         if($email !== null) $aParameters['email'] = (string) $email;
  1434.         if($url !== null) $aParameters['url'] = (string) $url;
  1435.         if($location !== null) $aParameters['location'] = (string) $location;
  1436.         if($description !== null) $aParameters['description'] = (string) $description;
  1437.  
  1438.         // make the call
  1439.         $response = $this->doCall('account/update_profile.xml', $aParameters, true);
  1440.  
  1441.         // convert into xml-object
  1442.         $xml = @simplexml_load_string($response);
  1443.  
  1444.         // validate
  1445.         if($xml == false) throw new TwitterException('invalid body');
  1446.  
  1447.         // return
  1448.         return (array) $this->userXMLToArray($xml, true);
  1449.     }
  1450.  
  1451.  
  1452. // favorite methods
  1453.     /**
  1454.      * Returns the 20 most recent favorite statuses for the authenticating user or user specified by the $id parameter
  1455.      *
  1456.      * @return  array
  1457.      * @param   string[optional] $id    The id or screen name of the user for whom to request a list of favorite statuses.
  1458.      * @param   int[optional] $page
  1459.      */
  1460.     public function getFavorites($id = null, $page = null)
  1461.     {
  1462.         // build parameters
  1463.         $aParameters = array();
  1464.         if($page !== null) $aParameters['page'] = (int) $page;
  1465.  
  1466.         $url = 'favorites.xml';
  1467.         if($id !== null) $url = 'favorites/'. urlencode($id) .'.xml';
  1468.  
  1469.         // do the call
  1470.         $response = $this->doCall($url, $aParameters, true, false);
  1471.  
  1472.         // convert into xml-object
  1473.         $xml = @simplexml_load_string($response);
  1474.  
  1475.         // validate
  1476.         if($xml == false) throw new TwitterException('invalid body');
  1477.  
  1478.         // init var
  1479.         $aStatuses = array();
  1480.  
  1481.         // loop statuses
  1482.         foreach ($xml->status as $status) $aStatuses[] = $this->statusXMLToArray($status);
  1483.  
  1484.         // return
  1485.         return (array) $aStatuses;
  1486.     }
  1487.  
  1488.  
  1489.     /**
  1490.      * Favorites the status specified in the id parameter as the authenticating user.
  1491.      *
  1492.      * @return  array
  1493.      * @param   string $id
  1494.      */
  1495.     public function createFavorite($id)
  1496.     {
  1497.         // redefine
  1498.         $id = (string) $id;
  1499.  
  1500.         // build url
  1501.         $url = 'favorites/create/'. urlencode($id) .'.xml';
  1502.  
  1503.         // build parameters
  1504.         $aParameters = array();
  1505.         $aParameters['id'] = $id;
  1506.  
  1507.         // do the call
  1508.         $response = $this->doCall($url, $aParameters, true);
  1509.  
  1510.         // convert into xml-object
  1511.         $xml = @simplexml_load_string($response);
  1512.  
  1513.         // validate
  1514.         if($xml == false) throw new TwitterException('invalid body');
  1515.  
  1516.         // return
  1517.         return (array) $this->statusXMLToArray($xml);
  1518.     }
  1519.  
  1520.  
  1521.     /**
  1522.      * Un-favorites the status specified in the id parameter as the authenticating user.
  1523.      *
  1524.      * @return  array
  1525.      * @param   string $id
  1526.      */
  1527.     public function deleteFavorite($id)
  1528.     {
  1529.         // redefine
  1530.         $id = (string) $id;
  1531.  
  1532.         // build url
  1533.         $url = 'favorites/destroy/'. urlencode($id) .'.xml';
  1534.  
  1535.         // build parameters
  1536.         $aParameters = array();
  1537.         $aParameters['id'] = $id;
  1538.  
  1539.         // do the call
  1540.         $response = $this->doCall($url, $aParameters, true);
  1541.  
  1542.         // convert into xml-object
  1543.         $xml = @simplexml_load_string($response);
  1544.  
  1545.         // validate
  1546.         if($xml == false) throw new TwitterException('invalid body');
  1547.  
  1548.         // return
  1549.         return (array) $this->statusXMLToArray($xml);
  1550.     }
  1551.  
  1552.  
  1553. // notification methods
  1554.     /**
  1555.      * Enables notifications for updates from the specified user to the authenticating user.
  1556.      * This method requires the authenticated user to already be friends with the specified user otherwise the error "there was a problem following the specified user" will be returned.
  1557.      *
  1558.      * @return  void
  1559.      * @param   string $id
  1560.      */
  1561.     public function follow($id)
  1562.     {
  1563.         // redefine
  1564.         $id = (string) $id;
  1565.  
  1566.         // build url
  1567.         $url = 'notifications/follow/'. urlencode($id) .'.xml';
  1568.  
  1569.         // build parameters
  1570.         $aParameters = array();
  1571.         $aParameters['id'] = $id;
  1572.  
  1573.         // do the call
  1574.         $response = $this->doCall($url, $aParameters, true);
  1575.  
  1576.         // convert into xml-object
  1577.         $xml = @simplexml_load_string($response);
  1578.  
  1579.         // validate
  1580.         if($xml == false) throw new TwitterException('invalid body');
  1581.  
  1582.         // return
  1583.         return (array) $this->userXMLToArray($xml);
  1584.     }
  1585.  
  1586.  
  1587.     /**
  1588.      * Disables notifications for updates from the specified user to the authenticating user.
  1589.      * This method requires the authenticated user to already be friends with the specified user otherwise the error "there was a problem following the specified user" will be returned.
  1590.      *
  1591.      * @return  void
  1592.      * @param   string $id
  1593.      */
  1594.     public function unfollow($id)
  1595.     {
  1596.         // redefine
  1597.         $id = (string) $id;
  1598.  
  1599.         // build url
  1600.         $url = 'notifications/leave/'. urlencode($id) .'.xml';
  1601.  
  1602.         // build parameters
  1603.         $aParameters = array();
  1604.         $aParameters['id'] = $id;
  1605.  
  1606.         // do the call
  1607.         $response = $this->doCall($url, $aParameters, true);
  1608.  
  1609.         // convert into xml-object
  1610.         $xml = @simplexml_load_string($response);
  1611.  
  1612.         // validate
  1613.         if($xml == false) throw new TwitterException('invalid body');
  1614.  
  1615.         // return
  1616.         return (array) $this->userXMLToArray($xml);
  1617.     }
  1618.  
  1619.  
  1620. // block methods
  1621.     /**
  1622.      * Blocks the user specified in the id parameter as the authenticating user.
  1623.      *
  1624.      * @return  void
  1625.      * @param   string $id
  1626.      */
  1627.     public function createBlock($id)
  1628.     {
  1629.         // redefine
  1630.         $id = (string) $id;
  1631.  
  1632.         // build url
  1633.         $url = 'blocks/create/'. urlencode($id) .'.xml';
  1634.  
  1635.         // build parameters
  1636.         $aParameters = array();
  1637.         $aParameters['id'] = $id;
  1638.  
  1639.         // do the call
  1640.         $response = $this->doCall($url, $aParameters, true);
  1641.  
  1642.         // convert into xml-object
  1643.         $xml = @simplexml_load_string($response);
  1644.  
  1645.         // validate
  1646.         if($xml == false) throw new TwitterException('invalid body');
  1647.  
  1648.         // return
  1649.         return (array) $this->userXMLToArray($xml);
  1650.     }
  1651.  
  1652.  
  1653.     /**
  1654.      * Un-blocks the user specified in the id parameter as the authenticating user.
  1655.      *
  1656.      * @return  void
  1657.      * @param   string $id
  1658.      */
  1659.     public function deleteBlock($id)
  1660.     {
  1661.         // redefine
  1662.         $id = (string) $id;
  1663.  
  1664.         // build url
  1665.         $url = 'blocks/destroy/'. urlencode($id) .'.xml';
  1666.  
  1667.         // build parameters
  1668.         $aParameters = array();
  1669.         $aParameters['id'] = $id;
  1670.  
  1671.         // do the call
  1672.         $response = $this->doCall($url, $aParameters, true);
  1673.  
  1674.         // convert into xml-object
  1675.         $xml = @simplexml_load_string($response);
  1676.  
  1677.         // validate
  1678.         if($xml == false) throw new TwitterException('invalid body');
  1679.  
  1680.         // return
  1681.         return (array) $this->userXMLToArray($xml);
  1682.     }
  1683.  
  1684.  
  1685.     /**
  1686.      * Returns if the authenticating user is blocking a target user.
  1687.      *
  1688.      * @return  bool
  1689.      * @param   string $id  The id or screen_name of the potentially blocked user.
  1690.      */
  1691.     public function existsBlock($id)
  1692.     {
  1693.         // redefine
  1694.         $id = (string) $id;
  1695.  
  1696.         // build url
  1697.         $url = 'blocks/exists/'. urlencode($id) .'.xml';
  1698.  
  1699.         // build parameters
  1700.         $aParameters = array();
  1701.         $aParameters['id'] = $id;
  1702.  
  1703.         // do the call
  1704.         try
  1705.         {
  1706.             $response = $this->doCall($url, $aParameters, true, false);
  1707.         }
  1708.  
  1709.         // catch exceptions
  1710.         catch(Exception $e)
  1711.         {
  1712.             // not blocking
  1713.             if($e->getMessage() == 'You are not blocking this user.') return false;
  1714.  
  1715.             // other exceptions
  1716.             else throw $e;
  1717.         }
  1718.  
  1719.         // convert into xml-object
  1720.         $xml = @simplexml_load_string($response);
  1721.  
  1722.         // validate
  1723.         if($xml == false) throw new TwitterException('invalid body');
  1724.  
  1725.         // return
  1726.         return true;
  1727.     }
  1728.  
  1729.  
  1730.     /**
  1731.      * Returns an array of user that the authenticating user is blocking.
  1732.      *
  1733.      * @return  array
  1734.      * @param   int[optional] $page Specifies the page number of the results beginning at 1. A single page contains 20 ids.
  1735.      */
  1736.     public function getBlocked($page = null)
  1737.     {
  1738.         // build parameters
  1739.         $aParameters = array();
  1740.         if($page !== null) $aParameters['page'] = (int) $page;
  1741.  
  1742.         // build url
  1743.         $url = 'blocks/blocking.xml';
  1744.  
  1745.         // do the call
  1746.         $response = $this->doCall($url, $aParameters, true, false);
  1747.  
  1748.         // convert into xml-object
  1749.         $xml = @simplexml_load_string($response);
  1750.  
  1751.         // validate
  1752.         if($xml == false) throw new TwitterException('invalid body');
  1753.  
  1754.         // init var
  1755.         $aUsers = array();
  1756.  
  1757.         // loop statuses
  1758.         foreach ($xml->user as $user) $aUsers[] = $this->userXMLToArray($user);
  1759.  
  1760.         // return
  1761.         return (array) $aUsers;
  1762.     }
  1763.  
  1764.  
  1765.     /**
  1766.      * Returns an array of numeric user ids the authenticating user is blocking.
  1767.      *
  1768.      * @return  array
  1769.      */
  1770.     public function getBlockedIds()
  1771.     {
  1772.         // build parameters
  1773.         $aParameters = array();
  1774.  
  1775.         // build url
  1776.         $url = 'blocks/blocking/ids.xml';
  1777.  
  1778.         // do the call
  1779.         $response = $this->doCall($url, $aParameters, true, false);
  1780.  
  1781.         // convert into xml-object
  1782.         $xml = @simplexml_load_string($response);
  1783.  
  1784.         // validate
  1785.         if($xml == false) throw new TwitterException('invalid body');
  1786.  
  1787.         // init var
  1788.         $aUsers = array();
  1789.  
  1790.         // loop statuses
  1791.         foreach ($xml->id as $id) $aUsers[] = (string) $id;
  1792.  
  1793.         // return
  1794.         return (array) $aUsers;
  1795.     }
  1796.  
  1797.  
  1798. // help methods
  1799.     /**
  1800.      * Test the connection to Twitter
  1801.      *
  1802.      * @return  bool
  1803.      */
  1804.     public function test()
  1805.     {
  1806.         // make the call
  1807.         $response = $this->doCall('help/test.xml');
  1808.  
  1809.         // validate response & return
  1810.         return (bool) ($response == '<ok>true</ok>');
  1811.     }
  1812. }
  1813.  
  1814.  
  1815. /**
  1816.  * Twitter Exception class
  1817.  *
  1818.  * @author  Tijs Verkoyen <[email protected]>
  1819.  */
  1820. class TwitterException extends Exception
  1821. {
  1822.     /**
  1823.      * Http header-codes
  1824.      *
  1825.      * @var array
  1826.      */
  1827.     private $aStatusCodes = array(100 => 'Continue',
  1828.                                     101 => 'Switching Protocols',
  1829.                                     200 => 'OK',
  1830.                                     201 => 'Created',
  1831.                                     202 => 'Accepted',
  1832.                                     203 => 'Non-Authoritative Information',
  1833.                                     204 => 'No Content',
  1834.                                     205 => 'Reset Content',
  1835.                                     206 => 'Partial Content',
  1836.                                     300 => 'Multiple Choices',
  1837.                                     301 => 'Moved Permanently',
  1838.                                     301 => 'Status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.',
  1839.                                     302 => 'Found',
  1840.                                     302 => 'Status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.',
  1841.                                     303 => 'See Other',
  1842.                                     304 => 'Not Modified',
  1843.                                     305 => 'Use Proxy',
  1844.                                     306 => '(Unused)',
  1845.                                     307 => 'Temporary Redirect',
  1846.                                     400 => 'Bad Request',
  1847.                                     401 => 'Unauthorized',
  1848.                                     402 => 'Payment Required',
  1849.                                     403 => 'Forbidden',
  1850.                                     404 => 'Not Found',
  1851.                                     405 => 'Method Not Allowed',
  1852.                                     406 => 'Not Acceptable',
  1853.                                     407 => 'Proxy Authentication Required',
  1854.                                     408 => 'Request Timeout',
  1855.                                     409 => 'Conflict',
  1856.                                     411 => 'Length Required',
  1857.                                     412 => 'Precondition Failed',
  1858.                                     413 => 'Request Entity Too Large',
  1859.                                     414 => 'Request-URI Too Long',
  1860.                                     415 => 'Unsupported Media Type',
  1861.                                     416 => 'Requested Range Not Satisfiable',
  1862.                                     417 => 'Expectation Failed',
  1863.                                     500 => 'Internal Server Error',
  1864.                                     501 => 'Not Implemented',
  1865.                                     502 => 'Bad Gateway',
  1866.                                     503 => 'Service Unavailable',
  1867.                                     504 => 'Gateway Timeout',
  1868.                                     505 => 'HTTP Version Not Supported');
  1869.  
  1870.  
  1871.     /**
  1872.      * Default constructor
  1873.      *
  1874.      * @return  void
  1875.      * @param   string[optional] $message
  1876.      * @param   int[optional] $code
  1877.      */
  1878.     public function __construct($message = null, $code = null)
  1879.     {
  1880.         // set message
  1881.         if($message === null && isset($this->aStatusCodes[(int) $code])) $message = $this->aStatusCodes[(int) $code];
  1882.  
  1883.         // call parent
  1884.         parent::__construct((string) $message, $code);
  1885.     }
  1886. }
  1887.  
  1888. ?>
Advertisement
Add Comment
Please, Sign In to add comment