Permalink
Browse files

Adding support for multipart image uploads. It's 1/2 working.

  • Loading branch information...
1 parent ea28b21 commit 5fc33a53feaac0f533be2e7b0a02374540a04344 @jmathai committed Jun 9, 2009
Showing with 87 additions and 22 deletions.
  1. +37 −13 EpiOAuth.php
  2. +39 −6 EpiTwitter.php
  3. +11 −3 tests/EpiTwitterTest.php
  4. BIN tests/avatar_test_image.jpg
View
@@ -46,7 +46,7 @@ public function getUrl($url)
return $url;
}
- public function httpRequest($method = null, $url = null, $params = null)
+ public function httpRequest($method = null, $url = null, $params = null, $isMultipart = false)
{
if(empty($method) || empty($url))
return false;
@@ -60,7 +60,7 @@ public function httpRequest($method = null, $url = null, $params = null)
return $this->httpGet($url, $params);
break;
case 'POST':
- return $this->httpPost($url, $params);
+ return $this->httpPost($url, $params, $isMultipart);
break;
}
}
@@ -86,7 +86,6 @@ protected function addOAuthHeaders(&$ch, $url, $oauthHeaders)
$oauth .= "{$name}=\"{$value}\",";
}
$_h[] = substr($oauth, 0, -1);
-
curl_setopt($ch, CURLOPT_HTTPHEADER, $_h);
}
@@ -120,7 +119,6 @@ protected function generateSignature($method = null, $url = null, $params = null
if(empty($method) || empty($url))
return false;
-
// concatenating
$concatenatedParams = '';
foreach($params as $k => $v)
@@ -156,12 +154,17 @@ protected function httpGet($url, $params = null)
return $resp;
}
- protected function httpPost($url, $params = null)
+ protected function httpPost($url, $params = null, $isMultipart)
{
$ch = $this->curlInit($url);
$this->addOAuthHeaders($ch, $url, $params['oauth']);
curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params['request']));
+ // php's curl extension automatically sets the content type
+ // based on whether the params are in string or array form
+ if($isMultipart)
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $params['request']);
+ else
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params['request']));
$resp = $this->curl->addCurl($ch);
return $resp;
}
@@ -198,18 +201,39 @@ protected function prepareParameters($method = null, $url = null, $params = null
$oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test
$oauth['oauth_signature_method'] = $this->signatureMethod;
$oauth['oauth_version'] = $this->version;
-
- // encoding
- array_walk($oauth, array($this, 'encode_rfc3986'));
+ // encode all oauth values
+// foreach($oauth as $k => $v)
+// $oauth[$k] = $this->encode_rfc3986($v);
+// // encode all non '@' params
+// // keep sigParams for signature generation (exclude '@' params)
+// // rename '@key' to 'key'
+// $sigParams = array();
if(is_array($params))
- array_walk($params, array($this, 'encode_rfc3986'));
- $encodedParams = array_merge($oauth, (array)$params);
+ {
+ foreach($params as $k => $v)
+ {
+ if(strncmp('@',$k,1) !== 0)
+ {
+// $sigParams[$k] = $this->encode_rfc3986($v);
+// $params[$k] = $this->encode_rfc3986($v);
+ $sigParams[$k] = ($v);
+ $params[$k] = ($v);
+ }
+ else
+ {
+ $params[substr($k, 1)] = $v;
+ unset($params[$k]);
+ }
+ }
+ }
+
+ $sigParams = array_merge($oauth, (array)$sigParams);
// sorting
- ksort($encodedParams);
+ ksort($sigParams);
// signing
- $oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $encodedParams));
+ $oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $sigParams));
return array('request' => $params, 'oauth' => $oauth);
}
View
@@ -12,6 +12,8 @@
class EpiTwitter extends EpiOAuth
{
const EPITWITTER_SIGNATURE_METHOD = 'HMAC-SHA1';
+ const EPITWITTER_AUTH_OAUTH = 'oauth';
+ const EPITWITTER_AUTH_BASIC = 'basic';
protected $requestTokenUrl= 'http://twitter.com/oauth/request_token';
protected $accessTokenUrl = 'http://twitter.com/oauth/access_token';
protected $authorizeUrl = 'http://twitter.com/oauth/authorize';
@@ -27,19 +29,34 @@ public function __call($name, $params = null)
$path = '/' . preg_replace('/[A-Z]|[0-9]+/e', "'/'.strtolower('\\0')", $parts) . '.json';
$args = !empty($params) ? array_shift($params) : null;
- // intercept calls to the search api
- if(preg_match('/^(search|trends)/', $parts))
+ // calls which do not have a consumerKey are assumed to not require authentication
+ if(empty($this->consumerKey))
{
+ echo 'do basic';
$query = isset($args) ? http_build_query($args) : '';
$url = "{$this->searchUrl}{$path}?{$query}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- return new EpiTwitterJson(EpiCurl::getInstance()->addCurl($ch));
+ return new EpiTwitterJson(EpiCurl::getInstance()->addCurl($ch), self::EPITWITTER_AUTH_BASIC);
+ }
+
+ // parse the keys to determine if this should be multipart
+ $isMultipart = false;
+ if($args)
+ {
+ foreach($args as $k => $v)
+ {
+ if(strncmp('@',$k,1) === 0)
+ {
+ $isMultipart = true;
+ break;
+ }
+ }
}
$url = $this->getUrl("{$this->apiUrl}{$path}");
- return new EpiTwitterJson(call_user_func(array($this, 'httpRequest'), $method, $url, $args));
+ return new EpiTwitterJson(call_user_func(array($this, 'httpRequest'), $method, $url, $args, $isMultipart));
}
public function __construct($consumerKey = null, $consumerSecret = null, $oauthToken = null, $oauthTokenSecret = null)
@@ -52,9 +69,12 @@ public function __construct($consumerKey = null, $consumerSecret = null, $oauthT
class EpiTwitterJson implements ArrayAccess, Countable, IteratorAggregate
{
private $__resp;
- public function __construct($response)
+ private $__auth = EpiTwitter::EPITWITTER_AUTH_OAUTH;
+ public function __construct($response, $auth = null)
{
$this->__resp = $response;
+ if($auth !== null)
+ $this->__auth = $auth;
}
// Implementation of the IteratorAggregate::getIterator() to support foreach ($this as $...)
@@ -97,9 +117,20 @@ public function offsetGet($offset)
public function __get($name)
{
if($this->__resp->code != 200 && $name !== 'responseText')
- EpiOAuthException::raise($this->__resp->data, $this->__resp->code);
+ {
+ switch($this->__auth)
+ {
+ case EpiTwitter::EPITWITTER_AUTH_OAUTH:
+ EpiOAuthException::raise($this->__resp->data, $this->__resp->code);
+ case EpiTwitter::EPITWITTER_AUTH_BASIC:
+ throw new EpiTwitterException($this->__resp->data, $this->__resp->code);
+ default:
+ throw new Exception("Unknown EpiTwitter Exception. Response: {$this->__resp->data}", $this->__resp->code);
+ }
+ }
$this->responseText = $this->__resp->data;
+ $this->code = $this->__resp->code;
$this->response = json_decode($this->responseText, 1);
$this->__obj = json_decode($this->responseText);
@@ -120,3 +151,5 @@ public function __isset($name)
return empty($name);
}
}
+
+class EpiTwitterException extends Exception {}
@@ -14,6 +14,7 @@ function setUp()
$token = '25451974-uakRmTZxrSFQbkDjZnTAsxDO5o9kacz2LT6kqEHA';
$secret= 'CuQPQ1WqIdSJDTIkDUlXjHpbcRao9lcKhQHflqGE8';
$this->twitterObj = new EpiTwitter($consumer_key, $consumer_secret, $token, $secret);
+ $this->twitterObjBasic = new EpiTwitter();
$this->screenName = 'jmathai_test';
}
@@ -57,7 +58,7 @@ function testPostStatus()
$this->assertEquals($resp->text, $statusText, 'The status was not updated correctly');
// reply to it
$statusText = 'Testing a random status with reply to id (reply to: ' . $resp->id . ')';
- $resp = $this->twitterObj->post_statusesUpdate(array('status' => $statusText, 'in_reply_to_status_id' => $resp->id));
+ $resp = $this->twitterObj->post_statusesUpdate(array('status' => $statusText, 'in_reply_to_status_id' => "{$resp->id}"));
$this->assertEquals($resp->text, $statusText, 'The status with reply to id was not updated correctly');
}
@@ -106,14 +107,14 @@ function testResponseAccess()
function testSearch()
{
- $resp = $this->twitterObj->get_search(array('q' => 'hello'));
+ $resp = $this->twitterObjBasic->get_search(array('q' => 'hello'));
$this->assertTrue(is_array($resp->response['results']));
$this->assertTrue(!empty($resp->results[0]->text), "search response is not an array {$resp->results[0]->text}");
}
function testTrends()
{
- $resp = $this->twitterObj->get_trends();
+ $resp = $this->twitterObjBasic->get_trends();
$this->assertTrue(is_array($resp->response['trends']), "trends is empty");
$this->assertTrue(!empty($resp->trends[0]->name), "current trends is not an array " . $resp->trends[0]->name);
@@ -140,4 +141,11 @@ function testCount()
$resp = $this->twitterObj->$method(array('page' => 100));
$this->assertTrue(count($resp) == 0, "Page 100 should return a count of 0");
}
+ function testUpdateAvatar()
+ {
+ $file = dirname(__FILE__) . '/avatar_test_image.jpg';
+ $resp = $this->twitterObj->post_accountUpdate_profile_image(array('@image' => "@{$file}"));
+ // api seems to be a bit behind and doesn't respond with the new image url - use code instead for now
+ $this->assertEquals($resp->code, 200, 'Response code was not 200');
+ }
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5fc33a5

Please sign in to comment.