Skip to content

Commit 791042e

Browse files
committed
Added DeviantArt support (#18) (thanks @cgenevier, daviddesberg/PHPoAuthLib#369)
1 parent c906369 commit 791042e

File tree

5 files changed

+301
-1
lines changed

5 files changed

+301
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Included service implementations
6464
- BitLy
6565
- Box
6666
- Dailymotion
67+
- DevianArt
6768
- Dropbox
6869
- Eve Online
6970
- Facebook

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "and/oauth",
33
"description": "Simple and amazing OAuth library with many providers. Just try it out!",
4-
"keywords": ["oauth", "oauth1", "oauth2", "authentication", "authorization", "security", "amazon", "bitbucket", "bitly", "box", "buffer", "dailymotion", "dropbox", "etsy", "eve", "eveonline", "facebook", "fitbit", "flickr", "foursquare", "github", "google", "harvest", "instagram", "jawbone", "linkedin", "mailchimp", "microsoft", "paypal", "pocket", "reddit", "runkeeper", "scoopit", "soundcloud", "spotify", "tumblr", "twitter", "ustream", "vkontakte", "yahoo"],
4+
"keywords": ["oauth", "oauth1", "oauth2", "authentication", "authorization", "security", "amazon", "bitbucket", "bitly", "box", "buffer", "dailymotion", "devianart", "dropbox", "etsy", "eve", "eveonline", "facebook", "fitbit", "flickr", "foursquare", "github", "google", "harvest", "instagram", "jawbone", "linkedin", "mailchimp", "microsoft", "paypal", "pocket", "reddit", "runkeeper", "scoopit", "soundcloud", "spotify", "tumblr", "twitter", "ustream", "vkontakte", "yahoo"],
55
"license": "MIT",
66
"authors": [
77
{

examples/devianart.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/**
4+
* Example of retrieving an authentication token of the DevianArt service
5+
*
6+
* PHP version 5.4
7+
*
8+
* @author @author Charlotte Genevier (https://github.com/cgenevier)
9+
* @author And <and.webdev@gmail.com>
10+
* @copyright Copyright (c) 2015 The authors
11+
* @license http://www.opensource.org/licenses/mit-license.html MIT License
12+
*/
13+
14+
use OAuth\OAuth2\Service\DeviantArt;
15+
use OAuth\Common\Storage\Session;
16+
use OAuth\Common\Consumer\Credentials;
17+
18+
/**
19+
* Bootstrap the example
20+
*/
21+
require_once __DIR__ . '/bootstrap.php';
22+
23+
// Session storage
24+
$storage = new Session();
25+
26+
// Setup the credentials for the requests
27+
$credentials = new Credentials(
28+
$servicesCredentials['devianart']['key'],
29+
$servicesCredentials['devianart']['secret'],
30+
$currentUri
31+
);
32+
33+
// Instantiate the DevianArt service using the credentials, http client and storage mechanism for the token
34+
/** @var $devianArtService DeviantArt */
35+
$devianArtService = $serviceFactory->createService('DevianArt', $credentials, $storage, []);
36+
37+
if ($devianArtService->isGlobalRequestArgumentsPassed()) {
38+
// Retrieve a token and send a request
39+
$result = $devianArtService->retrieveAccessTokenByGlobReqArgs()->requestJSON('/user/whoami');
40+
41+
// Show some of the resultant data
42+
echo 'Your DeviantArt username is: ' . $result['username'];
43+
44+
} elseif (!empty($_GET['go']) && $_GET['go'] === 'go') {
45+
$devianArtService->redirectToAuthorizationUri();
46+
} else {
47+
echo "<a href='$currentUri?go=go'>Login with DeviantArt!</a>";
48+
}

src/OAuth2/Service/DeviantArt.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace OAuth\OAuth2\Service;
4+
5+
use OAuth\OAuth2\Token\StdOAuth2Token;
6+
use OAuth\Common\Http\Exception\TokenResponseException;
7+
8+
/**
9+
* Class DeviantArt
10+
*
11+
* @package OAuth\OAuth2\Service
12+
* @author Charlotte Genevier (https://github.com/cgenevier)
13+
*/
14+
class DeviantArt extends AbstractService
15+
{
16+
/**
17+
* DeviantArt www url - used to build dialog urls
18+
*/
19+
const WWW_URL = 'https://www.deviantart.com/';
20+
21+
protected $baseApiUri = 'https://www.deviantart.com/api/{apiVersion}/oauth2/';
22+
protected $authorizationEndpoint = 'https://www.deviantart.com/oauth2/authorize';
23+
protected $accessTokenEndpoint = 'https://www.deviantart.com/oauth2/token';
24+
protected $apiVersion = 'v1';
25+
26+
/**
27+
* Defined scopes
28+
*
29+
* If you don't think this is scary you should not be allowed on the web at all
30+
*
31+
* @link https://www.deviantart.com/developers/authentication
32+
* @link https://www.deviantart.com/developers/http/v1/20150217
33+
*/
34+
const SCOPE_FEED = 'feed';
35+
const SCOPE_BROWSE = 'browse';
36+
const SCOPE_COMMENT = 'comment.post';
37+
const SCOPE_STASH = 'stash';
38+
const SCOPE_USER = 'user';
39+
const SCOPE_USERMANAGE = 'user.manage';
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
protected function parseAccessTokenResponse($responseBody)
45+
{
46+
$data = json_decode($responseBody, true);
47+
48+
if (null === $data || !is_array($data)) {
49+
throw new TokenResponseException('Unable to parse response.');
50+
} elseif (isset($data['error'])) {
51+
throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"');
52+
}
53+
54+
$token = new StdOAuth2Token();
55+
$token->setAccessToken($data['access_token']);
56+
57+
if (isset($data['expires_in'])) {
58+
$token->setLifeTime($data['expires_in']);
59+
}
60+
61+
if (isset($data['refresh_token'])) {
62+
$token->setRefreshToken($data['refresh_token']);
63+
unset($data['refresh_token']);
64+
}
65+
66+
unset($data['access_token']);
67+
unset($data['expires_in']);
68+
69+
$token->setExtraParams($data);
70+
71+
return $token;
72+
}
73+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<?php
2+
3+
namespace OAuthTest\Unit\OAuth2\Service;
4+
5+
use OAuth\Common\Token\TokenInterface;
6+
use OAuth\OAuth2\Service\DeviantArt;
7+
8+
class DeviantArtTest extends \PHPUnit_Framework_TestCase
9+
{
10+
/**
11+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
12+
*/
13+
public function testConstructCorrectInterfaceWithoutCustomUri()
14+
{
15+
$service = new DeviantArt(
16+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
17+
$this->getMock('\\Buzz\\Browser'),
18+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
19+
);
20+
21+
$this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\ServiceInterface', $service);
22+
}
23+
/**
24+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
25+
*/
26+
public function testConstructCorrectInstanceWithoutCustomUri()
27+
{
28+
$service = new DeviantArt(
29+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
30+
$this->getMock('\\Buzz\\Browser'),
31+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
32+
);
33+
34+
$this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\AbstractService', $service);
35+
}
36+
/**
37+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
38+
*/
39+
public function testConstructCorrectInstanceWithCustomUri()
40+
{
41+
$service = new DeviantArt(
42+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
43+
$this->getMock('\\Buzz\\Browser'),
44+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface'),
45+
[],
46+
''
47+
);
48+
49+
$this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\AbstractService', $service);
50+
}
51+
52+
public function testBaseApiUriIsCorrect()
53+
{
54+
$token = $this->getMock('\\OAuth\\OAuth2\\Token\\TokenInterface');
55+
$token->expects($this->once())->method('getEndOfLife')->will($this->returnValue(TokenInterface::EOL_NEVER_EXPIRES));
56+
$token->expects($this->once())->method('getAccessToken')->will($this->returnValue('foo'));
57+
58+
$storage = $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface');
59+
$storage->expects($this->once())->method('retrieveAccessToken')->will($this->returnValue($token));
60+
61+
/** @var DeviantArt|\PHPUnit_Framework_MockObject_MockObject $service */
62+
$service = $this->getMock('\\OAuth\\OAuth2\\Service\\DeviantArt', ['httpRequest'], [
63+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
64+
$this->getMock('\\Buzz\\Browser'),
65+
$storage
66+
]);
67+
68+
$service->expects($this->once())->method('httpRequest')->willReturnArgument(0);
69+
70+
$this->assertEquals('https://www.deviantart.com/api/v1/oauth2//api/method', (string) $service->request('/api/method'));
71+
}
72+
73+
/**
74+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
75+
* @covers OAuth\OAuth2\Service\DeviantArt::getAuthorizationEndpoint
76+
*/
77+
public function testGetAuthorizationEndpoint()
78+
{
79+
$service = new DeviantArt(
80+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
81+
$this->getMock('\\Buzz\\Browser'),
82+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
83+
);
84+
85+
$this->assertSame('https://www.deviantart.com/oauth2/authorize', (string) $service->getAuthorizationEndpoint());
86+
}
87+
/**
88+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
89+
* @covers OAuth\OAuth2\Service\DeviantArt::getAccessTokenEndpoint
90+
*/
91+
public function testGetAccessTokenEndpoint()
92+
{
93+
$service = new DeviantArt(
94+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
95+
$this->getMock('\\Buzz\\Browser'),
96+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
97+
);
98+
99+
$this->assertSame('https://www.deviantart.com/oauth2/token', (string) $service->getAccessTokenEndpoint());
100+
}
101+
/**
102+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
103+
*/
104+
public function testGetAuthorizationMethod()
105+
{
106+
$token = $this->getMock('\\OAuth\\OAuth2\\Token\\TokenInterface');
107+
$token->expects($this->once())->method('getEndOfLife')->will($this->returnValue(TokenInterface::EOL_NEVER_EXPIRES));
108+
$token->expects($this->once())->method('getAccessToken')->will($this->returnValue('foo'));
109+
110+
$storage = $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface');
111+
$storage->expects($this->once())->method('retrieveAccessToken')->will($this->returnValue($token));
112+
113+
/** @var DeviantArt|\PHPUnit_Framework_MockObject_MockObject $service */
114+
$service = $this->getMock('\\OAuth\\OAuth2\\Service\\DeviantArt', ['httpRequest'], [
115+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
116+
$this->getMock('\\Buzz\\Browser'),
117+
$storage
118+
]);
119+
120+
$service->expects($this->once())->method('httpRequest')->will($this->returnArgument(2));
121+
122+
$headers = $service->request('https://pieterhordijk.com/my/awesome/path');
123+
$this->assertTrue(array_key_exists('Authorization', $headers));
124+
$this->assertTrue(in_array('OAuth foo', $headers, true));
125+
}
126+
/**
127+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
128+
* @covers OAuth\OAuth2\Service\DeviantArt::parseAccessTokenResponse
129+
*/
130+
public function testParseAccessTokenResponseThrowsExceptionOnError()
131+
{
132+
/** @var DeviantArt|\PHPUnit_Framework_MockObject_MockObject $service */
133+
$service = $this->getMock('\\OAuth\\OAuth2\\Service\\DeviantArt', ['httpRequest'], [
134+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
135+
$this->getMock('\\Buzz\\Browser'),
136+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
137+
]);
138+
139+
$service->expects($this->once())->method('httpRequest')->will($this->returnValue('error=some_error'));
140+
141+
$this->setExpectedException('\\OAuth\\Common\\Http\\Exception\\TokenResponseException');
142+
$service->requestAccessToken('foo');
143+
}
144+
/**
145+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
146+
* @covers OAuth\OAuth2\Service\DeviantArt::parseAccessTokenResponse
147+
*/
148+
public function testParseAccessTokenResponseValidWithoutRefreshToken()
149+
{
150+
/** @var DeviantArt|\PHPUnit_Framework_MockObject_MockObject $service */
151+
$service = $this->getMock('\\OAuth\\OAuth2\\Service\\DeviantArt', ['httpRequest'], [
152+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
153+
$this->getMock('\\Buzz\\Browser'),
154+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
155+
]);
156+
157+
$service->expects($this->once())->method('httpRequest')->will($this->returnValue('{"access_token":"foo","expires_in":"bar"}'));
158+
159+
$this->assertInstanceOf('\\OAuth\\OAuth2\\Token\\StdOAuth2Token', $service->requestAccessToken('foo'));
160+
}
161+
/**
162+
* @covers OAuth\OAuth2\Service\DeviantArt::__construct
163+
* @covers OAuth\OAuth2\Service\DeviantArt::parseAccessTokenResponse
164+
*/
165+
public function testParseAccessTokenResponseValidWithRefreshToken()
166+
{
167+
/** @var DeviantArt|\PHPUnit_Framework_MockObject_MockObject $service */
168+
$service = $this->getMock('\\OAuth\\OAuth2\\Service\\DeviantArt', ['httpRequest'], [
169+
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
170+
$this->getMock('\\Buzz\\Browser'),
171+
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
172+
]);
173+
174+
$service->expects($this->once())->method('httpRequest')->will($this->returnValue('{"access_token":"foo","expires_in":"bar","refersh_token":"baz"}'));
175+
176+
$this->assertInstanceOf('\\OAuth\\OAuth2\\Token\\StdOAuth2Token', $service->requestAccessToken('foo'));
177+
}
178+
}

0 commit comments

Comments
 (0)