Passed
Branch main (d68b9c)
by smiley
09:54
created

Deezer   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 8
eloc 54
c 2
b 0
f 0
dl 0
loc 97
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A parseTokenResponse() 0 27 5
A getAuthURL() 0 17 2
A getAccessToken() 0 21 1
1
<?php
2
/**
3
 * Class Deezer
4
 *
5
 * @link https://developers.deezer.com/api/oauth
6
 *
7
 * sure, you *can* use different parameter names than the standard ones... and what about JSON?
8
 * https://xkcd.com/927/
9
 *
10
 * @filesource   Deezer.php
11
 * @created      09.08.2018
12
 * @package      chillerlan\OAuth\Providers\Deezer
13
 * @author       Smiley <[email protected]>
14
 * @copyright    2018 Smiley
15
 * @license      MIT
16
 */
17
18
namespace chillerlan\OAuth\Providers\Deezer;
19
20
use chillerlan\OAuth\Core\{AccessToken, CSRFToken, OAuth2Provider, ProviderException};
21
use Psr\Http\Message\{ResponseInterface, UriInterface};
22
23
use function array_merge, http_build_query, implode, is_array, parse_str;
24
use function chillerlan\HTTP\Psr7\{decompress_content, merge_query};
0 ignored issues
show
Bug introduced by
The type chillerlan\HTTP\Psr7\decompress_content was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type chillerlan\HTTP\Psr7\merge_query was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
26
use const PHP_QUERY_RFC1738;
27
28
/**
29
 * @method \Psr\Http\Message\ResponseInterface me()
30
 */
31
class Deezer extends OAuth2Provider implements CSRFToken{
32
33
	public const SCOPE_BASIC             = 'basic_access';
34
	public const SCOPE_EMAIL             = 'email';
35
	public const SCOPE_OFFLINE_ACCESS    = 'offline_access';
36
	public const SCOPE_MANAGE_LIBRARY    = 'manage_library';
37
	public const SCOPE_MANAGE_COMMUNITY  = 'manage_community';
38
	public const SCOPE_DELETE_LIBRARY    = 'delete_library';
39
	public const SCOPE_LISTENING_HISTORY = 'listening_history';
40
41
	protected string $authURL         = 'https://connect.deezer.com/oauth/auth.php';
42
	protected string $accessTokenURL  = 'https://connect.deezer.com/oauth/access_token.php';
43
	protected ?string $apiURL         = 'https://api.deezer.com';
44
	protected ?string $userRevokeURL  = 'https://www.deezer.com/account/apps';
45
	protected ?string $endpointMap    = DeezerEndpoints::class;
46
	protected ?string $apiDocs        = 'https://developers.deezer.com/api';
47
	protected ?string $applicationURL = 'http://developers.deezer.com/myapps';
48
	protected int $authMethod         = self::AUTH_METHOD_QUERY;
49
50
	/**
51
	 * @inheritDoc
52
	 */
53
	public function getAuthURL(array $params = null, array $scopes = null):UriInterface{
54
		$params = $params ?? [];
55
56
		if(isset($params['client_secret'])){
57
			unset($params['client_secret']);
58
		}
59
60
		$params = array_merge($params, [
61
			'app_id'        => $this->options->key,
62
			'redirect_uri'  => $this->options->callbackURL,
63
			'perms'         => implode($this->scopesDelimiter, $scopes ?? []),
64
#			'response_type' => 'token', // -> token in hash fragment
65
		]);
66
67
		$params = $this->setState($params);
68
69
		return $this->uriFactory->createUri(merge_query($this->authURL, $params));
70
	}
71
72
	/**
73
	 * @inheritDoc
74
	 */
75
	public function getAccessToken(string $code, string $state = null):AccessToken{
76
		$this->checkState($state);
77
78
		$body = [
79
			'app_id' => $this->options->key,
80
			'secret' => $this->options->secret,
81
			'code'   => $code,
82
			'output' => 'json',
83
		];
84
85
		$request = $this->requestFactory
86
			->createRequest('POST', $this->accessTokenURL)
87
			->withHeader('Content-Type', 'application/x-www-form-urlencoded')
88
			->withHeader('Accept-Encoding', 'identity')
89
			->withBody($this->streamFactory->createStream(http_build_query($body, '', '&', PHP_QUERY_RFC1738)));
90
91
		$token = $this->parseTokenResponse($this->http->sendRequest($request));
92
93
		$this->storage->storeAccessToken($this->serviceName, $token);
94
95
		return $token;
96
	}
97
98
	/**
99
	 * @inheritDoc
100
	 */
101
	protected function parseTokenResponse(ResponseInterface $response):AccessToken{
102
		parse_str(decompress_content($response), $data);
103
104
		if(!is_array($data) || empty($data)){
105
			throw new ProviderException('unable to parse token response');
106
		}
107
108
		if(isset($data['error_reason'])){
109
			throw new ProviderException('error retrieving access token: "'.$data['error_reason'].'"');
110
		}
111
112
		if(!isset($data['access_token'])){
113
			throw new ProviderException('token missing');
114
		}
115
116
		$token = new AccessToken([
117
			'provider'     => $this->serviceName,
118
			'accessToken'  => $data['access_token'],
119
			'expires'      => $data['expires'] ?? $data['expires_in'] ?? AccessToken::EOL_NEVER_EXPIRES,
120
			'refreshToken' => $data['refresh_token'] ?? null,
121
		]);
122
123
		unset($data['expires'], $data['expires_in'], $data['refresh_token'], $data['access_token']);
124
125
		$token->extraParams = $data;
126
127
		return $token;
128
	}
129
130
}
131