소스 검색

Added reasonably simple Zend_Service_Twitter integration with Zend_Oauth

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@22336 44c647ce-9c0f-0410-b52a-842ac1e357ba
padraic 15 년 전
부모
커밋
43ff5f3a99
2개의 변경된 파일128개의 추가작업 그리고 17개의 파일을 삭제
  1. 65 14
      library/Zend/Service/Twitter.php
  2. 63 3
      tests/Zend/Service/Twitter/TwitterTest.php

+ 65 - 14
library/Zend/Service/Twitter.php

@@ -29,6 +29,9 @@ require_once 'Zend/Rest/Client.php';
  * @see Zend_Rest_Client_Result
  */
 require_once 'Zend/Rest/Client/Result.php';
+
+require_once 'Zend/Oauth/Consumer.php';
+
 /**
  * @category   Zend
  * @package    Zend_Service
@@ -50,6 +53,11 @@ class Zend_Service_Twitter extends Zend_Rest_Client
     const STATUS_MAX_CHARACTERS = 246;
     
     /**
+     * OAuth Endpoint
+     */
+    const OAUTH_BASE_URI = 'http://twitter.com/oauth';
+    
+    /**
      * @var Zend_Http_CookieJar
      */
     protected $_cookieJar;
@@ -76,6 +84,13 @@ class Zend_Service_Twitter extends Zend_Rest_Client
     protected $_methodType;
     
     /**
+     * Zend_Oauth Consumer
+     *
+     * @var Zend_Oauth_Consumer
+     */
+    protected $_oauthConsumer = null;
+    
+    /**
      * Types of API methods
      *
      * @var array
@@ -89,6 +104,13 @@ class Zend_Service_Twitter extends Zend_Rest_Client
         'favorite',
         'block'
     );
+    
+    /**
+     * Options passed to constructor
+     *
+     * @var array
+     */
+    protected $_options = array();
 
     /**
      * Local HTTP Client cloned from statically set client
@@ -100,24 +122,32 @@ class Zend_Service_Twitter extends Zend_Rest_Client
     /**
      * Constructor
      *
-     * @param  string $username
-     * @param  string $password
+     * @param  array $options Optional options array
      * @return void
      */
-    public function __construct($username = null)
+    public function __construct(array $options = null, Zend_Oauth_Consumer $consumer = null)
     {
-        $this->setLocalHttpClient(clone self::getHttpClient());
-        if (is_array($username)) {
-            if (isset($username['username'])) {
-                $this->setUsername($username['username']);
-            } elseif (isset($username[0])) {
-                $this->setUsername($username[0]);
+        $this->setUri('http://api.twitter.com');
+        if (!is_array($options)) $options = array();
+        $options['siteUrl'] = self::OAUTH_BASE_URI;
+        if ($options instanceof Zend_Config) {
+            $options = $options->toArray();
+        }
+        $this->_options = $options;
+        if (isset($options['username'])) {
+            $this->setUsername($options['username']);
+        }
+        if (isset($options['accessToken'])
+        && $options['accessToken'] instanceof Zend_Oauth_Token_Access) {
+            $this->setLocalHttpClient($options['accessToken']->getHttpClient($options));
+        } else {
+            $this->setLocalHttpClient(clone self::getHttpClient());
+            if (is_null($consumer)) {
+                $this->_oauthConsumer = new Zend_Oauth_Consumer($options);
+            } else {
+                $this->_oauthConsumer = $consumer;
             }
-        } elseif (!is_null($username)) {
-            $this->setUsername($username);
         }
-        $this->setUri('http://api.twitter.com');
-        $this->_localHttpClient->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
     }
 
     /**
@@ -130,11 +160,12 @@ class Zend_Service_Twitter extends Zend_Rest_Client
     public function setLocalHttpClient(Zend_Http_Client $client)
     {
         $this->_localHttpClient = $client;
+        $this->_localHttpClient->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
         return $this;
     }
     
     /**
-     * Get the local HTTP client as distinct from the static HTPP client
+     * Get the local HTTP client as distinct from the static HTTP client
      * inherited from Zend_Rest_Client
      *
      * @return Zend_Http_Client
@@ -143,6 +174,19 @@ class Zend_Service_Twitter extends Zend_Rest_Client
     {
         return $this->_localHttpClient;
     }
+    
+    /**
+     * Checks for an authorised state
+     *
+     * @return bool
+     */
+    public function isAuthorised()
+    {
+        if ($this->getLocalHttpClient() instanceof Zend_Oauth_Client) {
+            return true;
+        }
+        return false;
+    }
 
     /**
      * Retrieve username
@@ -196,6 +240,13 @@ class Zend_Service_Twitter extends Zend_Rest_Client
      */
     public function __call($method, $params)
     {
+        if (method_exists($this->_oauthConsumer, $method)) {
+            $return = call_user_func_array(array($this->_oauthConsumer, $method), $params);
+            if ($return instanceof Zend_Oauth_Token_Access) {
+                $this->setLocalHttpClient($return->getHttpClient($this->_options));
+            }
+            return $return;
+        }
         if (empty($this->_methodType)) {
             include_once 'Zend/Service/Twitter/Exception.php';
             throw new Zend_Service_Twitter_Exception(

+ 63 - 3
tests/Zend/Service/Twitter/TwitterTest.php

@@ -106,6 +106,66 @@ class Zend_Service_Twitter_TwitterTest extends PHPUnit_Framework_TestCase
     }
     
     /**
+     * OAuth tests
+     */
+    
+    public function testProvidingAccessTokenInOptionsSetsHttpClientFromAccessToken()
+    {
+        $token = $this->getMock('Zend_Oauth_Token_Access', array(), array(), '', false);
+        $client = $this->getMock('Zend_Oauth_Client', array(), array(), '', false);
+        $token->expects($this->once())->method('getHttpClient')
+            ->with(array('accessToken'=>$token, 'opt1'=>'val1', 'siteUrl'=>'http://twitter.com/oauth'))
+            ->will($this->returnValue($client));
+        $twitter = new Zend_Service_Twitter(array('accessToken'=>$token, 'opt1'=>'val1'));
+        $this->assertTrue($client === $twitter->getLocalHttpClient());
+    }
+    
+    public function testNotAuthorisedWithoutToken()
+    {
+        $twitter = new Zend_Service_Twitter;
+        $this->assertFalse($twitter->isAuthorised());
+    }
+    
+    public function testChecksAuthenticatedStateBasedOnAvailabilityOfAccessTokenBasedClient()
+    {
+        $token = $this->getMock('Zend_Oauth_Token_Access', array(), array(), '', false);
+        $client = $this->getMock('Zend_Oauth_Client', array(), array(), '', false);
+        $token->expects($this->once())->method('getHttpClient')
+            ->with(array('accessToken'=>$token, 'siteUrl'=>'http://twitter.com/oauth'))
+            ->will($this->returnValue($client));
+        $twitter = new Zend_Service_Twitter(array('accessToken'=>$token));
+        $this->assertTrue($twitter->isAuthorised());
+    }
+    
+    public function testRelaysMethodsToInternalOAuthInstance()
+    {
+        $oauth = $this->getMock('Zend_Oauth_Consumer', array(), array(), '', false);
+        $oauth->expects($this->once())->method('getRequestToken')->will($this->returnValue('foo'));
+        $oauth->expects($this->once())->method('getRedirectUrl')->will($this->returnValue('foo'));
+        $oauth->expects($this->once())->method('redirect')->will($this->returnValue('foo'));
+        $oauth->expects($this->once())->method('getAccessToken')->will($this->returnValue('foo'));
+        $oauth->expects($this->once())->method('getToken')->will($this->returnValue('foo'));
+        $twitter = new Zend_Service_Twitter(array('opt1'=>'val1'), $oauth);
+        $this->assertEquals('foo', $twitter->getRequestToken());
+        $this->assertEquals('foo', $twitter->getRedirectUrl());
+        $this->assertEquals('foo', $twitter->redirect());
+        $this->assertEquals('foo', $twitter->getAccessToken(array(), $this->getMock('Zend_Oauth_Token_Request')));
+        $this->assertEquals('foo', $twitter->getToken());
+    }
+    
+    public function testResetsHttpClientOnReceiptOfAccessTokenToOauthClient()
+    {
+        $oauth = $this->getMock('Zend_Oauth_Consumer', array(), array(), '', false);
+        $client = $this->getMock('Zend_Oauth_Client', array(), array(), '', false);
+        $token = $this->getMock('Zend_Oauth_Token_Access', array(), array(), '', false);
+        $token->expects($this->once())->method('getHttpClient')->will($this->returnValue($client));
+        $oauth->expects($this->once())->method('getAccessToken')->will($this->returnValue($token));
+        $twitter = new Zend_Service_Twitter(array(), $oauth);
+        $twitter->getAccessToken(array(), $this->getMock('Zend_Oauth_Token_Request'));
+        $this->assertTrue($client === $twitter->getLocalHttpClient());
+    }
+    
+    /**
      * @group ZF-8218
      */
     public function testUserNameNotRequired()
@@ -295,7 +355,7 @@ class Zend_Service_Twitter_TwitterTest extends PHPUnit_Framework_TestCase
      */
     public function testFriendshipExists()
     {
-        $twitter = new Zend_Service_Twitter('padraicb');
+        $twitter = new Zend_Service_Twitter(array('username'=>'padraicb'));
         $twitter->setLocalHttpClient($this->_stubTwitter(
             'friendships/exists.xml', Zend_Http_Client::GET, 'friendships.exists.twitter.xml',
             array('user_a'=>'padraicb', 'user_b'=>'twitter')
@@ -555,8 +615,8 @@ class Zend_Service_Twitter_TwitterTest extends PHPUnit_Framework_TestCase
      */
     public function testTwitterObjectsSoNotShareSameHttpClientToPreventConflictingAuthentication()
     {
-        $twitter1 = new Zend_Service_Twitter('zftestuser1');
-        $twitter2 = new Zend_Service_Twitter('zftestuser2');
+        $twitter1 = new Zend_Service_Twitter(array('username'=>'zftestuser1'));
+        $twitter2 = new Zend_Service_Twitter(array('username'=>'zftestuser2'));
         $this->assertFalse($twitter1->getLocalHttpClient() === $twitter2->getLocalHttpClient());
     }