-
Notifications
You must be signed in to change notification settings - Fork 454
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #433 from PedroAmorim/deezer
Add service Deezer
- Loading branch information
Showing
5 changed files
with
353 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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')); | ||
} | ||
} |