Skip to content

Commit

Permalink
Merge pull request #433 from PedroAmorim/deezer
Browse files Browse the repository at this point in the history
Add service Deezer
  • Loading branch information
elliotchance committed Oct 13, 2015
2 parents 92f3ee6 + 237ae54 commit cf3770e
Show file tree
Hide file tree
Showing 5 changed files with 353 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Included service implementations
- Buffer
- Dailymotion
- Delicious
- Deezer
- DeviantArt
- Dropbox
- Eve Online
Expand Down
52 changes: 52 additions & 0 deletions examples/deezer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/**
* Example of retrieving an authentication token of the Deezer service
*
* @author Pedro Amorim <contact@pamorim.fr>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://developers.deezer.com/api/
*/

use OAuth\OAuth2\Service\Deezer;
use OAuth\Common\Storage\Session;
use OAuth\Common\Consumer\Credentials;
use OAuth\Common\Http\Client\CurlClient;

/**
* Bootstrap the example
*/
require_once __DIR__ . '/bootstrap.php';

// Session storage
$storage = new Session();

// Setup the credentials for the requests
$credentials = new Credentials(
$servicesCredentials['deezer']['key'],
$servicesCredentials['deezer']['secret'],
$currentUri->getAbsoluteUri() // Deezer require Https callback's url
);
$serviceFactory->setHttpClient(new CurlClient);
// Instantiate the Deezer service using the credentials, http client and storage mechanism for the token
/** @var $deezerService Deezer */
$deezerService = $serviceFactory->createService('deezer', $credentials, $storage, [Deezer::SCOPE_BASIC_ACCESS, Deezer::SCOPE_OFFLINE_ACCESS, Deezer::SCOPE_EMAIL, Deezer::SCOPE_DELETE_LIBRARY]);

if (!empty($_GET['code'])) {
// retrieve the CSRF state parameter
$state = isset($_GET['state']) ? $_GET['state'] : null;
// This was a callback request from deezer, get the token
$token = $deezerService->requestAccessToken($_GET['code'], $state);
// Show some of the resultant data
$result = json_decode($deezerService->request('user/me'), true);
echo 'Hello ' . ucfirst($result['name'])
. ' your Deezer Id is ' . $result['id'];
echo '<br><img src="'.$result['picture_medium'].'">';

} elseif (!empty($_GET['go']) && $_GET['go'] === 'go') {
$url = $deezerService->getAuthorizationUri();
header('Location: ' . $url);
} else {
$url = $currentUri->getRelativeUri() . '?go=go';
echo "<a href='$url'>Login with Deezer!</a>";
}
4 changes: 4 additions & 0 deletions examples/init.example.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
'key' => '',
'secret' => '',
),
'deezer' => array(
'key' => '',
'secret' => '',
),
'deviantart' => array(
'key' => '',
'secret' => '',
Expand Down
121 changes: 121 additions & 0 deletions src/OAuth/OAuth2/Service/Deezer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php
/**
* Deezer service.
*
* @author Pedro Amorim <contact@pamorim.fr>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://developers.deezer.com/api/
*/

namespace OAuth\OAuth2\Service;

use OAuth\OAuth2\Token\StdOAuth2Token;
use OAuth\Common\Http\Exception\TokenResponseException;
use OAuth\Common\Http\Uri\Uri;
use OAuth\Common\Consumer\CredentialsInterface;
use OAuth\Common\Http\Client\ClientInterface;
use OAuth\Common\Storage\TokenStorageInterface;
use OAuth\Common\Http\Uri\UriInterface;

/**
* Deezer service.
*
* @author Pedro Amorim <contact@pamorim.fr>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://developers.deezer.com/api/
*/
class Deezer extends AbstractService
{
/**
* Defined scopes
* http://developers.deezer.com/api/permissions
*/
const SCOPE_BASIC_ACCESS = 'basic_access'; // Access users basic information
const SCOPE_EMAIL = 'email'; // Get the user's email
const SCOPE_OFFLINE_ACCESS = 'offline_access'; // Access user data any time
const SCOPE_MANAGE_LIBRARY = 'manage_library'; // Manage users' library
const SCOPE_MANAGE_COMMUNITY = 'manage_community'; // Manage users' friends
const SCOPE_DELETE_LIBRARY = 'delete_library'; // Delete library items
const SCOPE_LISTENING_HISTORY = 'listening_history'; // Access the user's listening history

public function __construct(
CredentialsInterface $credentials,
ClientInterface $httpClient,
TokenStorageInterface $storage,
$scopes = array(),
UriInterface $baseApiUri = null
) {
parent::__construct(
$credentials,
$httpClient,
$storage,
$scopes,
$baseApiUri,
true
);

if (null === $baseApiUri) {
$this->baseApiUri = new Uri('https://api.deezer.com/');
}
}

/**
* {@inheritdoc}
*/
public function getAuthorizationEndpoint()
{
return new Uri('https://connect.deezer.com/oauth/auth.php');
}

/**
* {@inheritdoc}
*/
public function getAccessTokenEndpoint()
{
return new Uri('https://connect.deezer.com/oauth/access_token.php');
}

/**
* {@inheritdoc}
*/
protected function getAuthorizationMethod()
{
return static::AUTHORIZATION_METHOD_QUERY_STRING;
}

/**
* {@inheritdoc}
*/
protected function parseAccessTokenResponse($responseBody)
{
parse_str($responseBody, $data);
if (null === $data || !is_array($data) || empty($data)) {
throw new TokenResponseException('Unable to parse response.');
} elseif (isset($data['error'])) {
throw new TokenResponseException(
'Error in retrieving token: "' . $data['error'] . '"'
);
} elseif (isset($data['error_reason'])) {
throw new TokenResponseException(
'Error in retrieving token: "' . $data['error_reason'] . '"'
);
}

$token = new StdOAuth2Token();
$token->setAccessToken($data['access_token']);
$token->setLifeTime($data['expires']);

// I hope one day Deezer add a refresh token :)
if (isset($data['refresh_token'])) {
$token->setRefreshToken($data['refresh_token']);
unset($data['refresh_token']);
}

unset($data['access_token']);
unset($data['expires']);

$token->setExtraParams($data);

return $token;
}
}
175 changes: 175 additions & 0 deletions tests/Unit/OAuth2/Service/DeezerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php

namespace OAuthTest\Unit\OAuth2\Service;

use OAuth\OAuth2\Service\Deezer;
use OAuth\Common\Token\TokenInterface;

class DeezerTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
*/
public function testConstructCorrectInterfaceWithoutCustomUri()
{
$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'),
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\ServiceInterface', $service);
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
*/
public function testConstructCorrectInstanceWithoutCustomUri()
{
$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'),
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\AbstractService', $service);
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
*/
public function testConstructCorrectInstanceWithCustomUri()
{
$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'),
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface'),
array(),
$this->getMock('\\OAuth\\Common\\Http\\Uri\\UriInterface')
);

$this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\AbstractService', $service);
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
* @covers OAuth\OAuth2\Service\Deezer::getAuthorizationEndpoint
*/
public function testGetAuthorizationEndpoint()
{
$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'),
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->assertSame(
'https://connect.deezer.com/oauth/auth.php',
$service->getAuthorizationEndpoint()->getAbsoluteUri()
);
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
* @covers OAuth\OAuth2\Service\Deezer::getAccessTokenEndpoint
*/
public function testGetAccessTokenEndpoint()
{
$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'),
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->assertSame(
'https://connect.deezer.com/oauth/access_token.php',
$service->getAccessTokenEndpoint()->getAbsoluteUri()
);
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
* @covers OAuth\OAuth2\Service\Deezer::getAuthorizationMethod
*/
public function testGetAuthorizationMethod()
{
$client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface');
$client->expects($this->once())->method('retrieveResponse')->will($this->returnArgument(0));

$token = $this->getMock('\\OAuth\\OAuth2\\Token\\TokenInterface');
$token->expects($this->once())->method('getEndOfLife')->will($this->returnValue(TokenInterface::EOL_NEVER_EXPIRES));
$token->expects($this->once())->method('getAccessToken')->will($this->returnValue('foo'));

$storage = $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface');
$storage->expects($this->once())->method('retrieveAccessToken')->will($this->returnValue($token));

$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$client,
$storage
);

$uri = $service->request('https://pieterhordijk.com/my/awesome/path');
$absoluteUri = parse_url($uri->getAbsoluteUri());

$this->assertSame('access_token=foo', $absoluteUri['query']);
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
* @covers OAuth\OAuth2\Service\Deezer::parseAccessTokenResponse
*/
public function testParseAccessTokenResponseThrowsExceptionOnNulledResponse()
{
$client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface');
$client->expects($this->once())->method('retrieveResponse')->will($this->returnValue(null));

$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$client,
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->setExpectedException('\\OAuth\\Common\\Http\\Exception\\TokenResponseException');

$service->requestAccessToken('foo');
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
* @covers OAuth\OAuth2\Service\Deezer::parseAccessTokenResponse
*/
public function testParseAccessTokenResponseThrowsExceptionOnError()
{
$client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface');
$client->expects($this->once())->method('retrieveResponse')->will($this->returnValue('error_reason=user_denied'));

$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$client,
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->setExpectedException('\\OAuth\\Common\\Http\\Exception\\TokenResponseException');

$service->requestAccessToken('foo');
}

/**
* @covers OAuth\OAuth2\Service\Deezer::__construct
* @covers OAuth\OAuth2\Service\Deezer::parseAccessTokenResponse
*/
public function testParseAccessTokenResponseValid()
{
$client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface');
$client->expects($this->once())->method('retrieveResponse')->will($this->returnValue('access_token=foo&expires=bar'));

$service = new Deezer(
$this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'),
$client,
$this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface')
);

$this->assertInstanceOf('\\OAuth\\OAuth2\\Token\\StdOAuth2Token', $service->requestAccessToken('foo'));
}
}

0 comments on commit cf3770e

Please sign in to comment.