Passed
Push — main ( e868ec...9f95cc )
by smiley
12:00
created

GuildWars2   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 9
eloc 45
c 1
b 0
f 0
dl 0
loc 95
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A storeGW2Token() 0 32 4
A getAccessToken() 0 2 1
A me() 0 15 3
A getAuthURL() 0 2 1
1
<?php
2
/**
3
 * Class GuildWars2
4
 *
5
 * @created      22.10.2017
6
 * @author       Smiley <[email protected]>
7
 * @copyright    2017 Smiley
8
 * @license      MIT
9
 */
10
11
namespace chillerlan\OAuth\Providers;
12
13
use chillerlan\HTTP\Utils\MessageUtil;
14
use chillerlan\OAuth\Core\{AccessToken, OAuth2Provider, ProviderException};
15
use chillerlan\HTTP\Utils\QueryUtil;
16
use Psr\Http\Message\ResponseInterface;
17
use Psr\Http\Message\UriInterface;
18
use function implode;
19
use function preg_match;
20
use function sprintf;
21
use function str_starts_with;
22
use function substr;
23
24
/**
25
 * GW2 does not support authentication (anymore) but the API still works like a regular OAUth API, so...
26
 *
27
 * @see https://api.guildwars2.com/v2
28
 * @see https://wiki.guildwars2.com/wiki/API:Main
29
 */
30
class GuildWars2 extends OAuth2Provider{
31
32
	public const SCOPE_ACCOUNT        = 'account';
33
	public const SCOPE_INVENTORIES    = 'inventories';
34
	public const SCOPE_CHARACTERS     = 'characters';
35
	public const SCOPE_TRADINGPOST    = 'tradingpost';
36
	public const SCOPE_WALLET         = 'wallet';
37
	public const SCOPE_UNLOCKS        = 'unlocks';
38
	public const SCOPE_PVP            = 'pvp';
39
	public const SCOPE_BUILDS         = 'builds';
40
	public const SCOPE_PROGRESSION    = 'progression';
41
	public const SCOPE_GUILDS         = 'guilds';
42
43
	protected const AUTH_ERRMSG       = 'GuildWars2 does not support authentication anymore.';
44
45
	protected string  $authURL        = 'https://account.arena.net/applications/create';
46
	protected string  $apiURL         = 'https://api.guildwars2.com';
47
	protected ?string $userRevokeURL  = 'https://account.arena.net/applications';
48
	protected ?string $apiDocs        = 'https://wiki.guildwars2.com/wiki/API:Main';
49
	protected ?string $applicationURL = 'https://account.arena.net/applications';
50
51
	/**
52
	 * @param string $access_token
53
	 *
54
	 * @return \chillerlan\OAuth\Core\AccessToken
55
	 * @throws \chillerlan\OAuth\Core\ProviderException
56
	 */
57
	public function storeGW2Token(string $access_token):AccessToken{
58
59
		if(!preg_match('/^[a-f\d\-]{72}$/i', $access_token)){
60
			throw new ProviderException('invalid token');
61
		}
62
63
		// to verify the token we need to send a request without authentication
64
		$request = $this->requestFactory
65
			->createRequest('GET', QueryUtil::merge($this->apiURL.'/v2/tokeninfo', ['access_token' => $access_token]))
66
		;
67
68
		$tokeninfo = MessageUtil::decodeJSON($this->http->sendRequest($request));
69
70
		if(isset($tokeninfo->id) && str_starts_with($access_token, $tokeninfo->id)){
71
			$token                    = new AccessToken;
72
			$token->provider          = $this->serviceName;
73
			$token->accessToken       = $access_token;
74
			$token->accessTokenSecret = substr($access_token, 36, 36); // the actual token
75
			$token->expires           = AccessToken::EOL_NEVER_EXPIRES;
76
			$token->extraParams       = [
77
				'token_type' => 'Bearer',
78
				'id'         => $tokeninfo->id,
79
				'name'       => $tokeninfo->name,
80
				'scope'      => implode($this->scopesDelimiter, $tokeninfo->permissions),
81
			];
82
83
			$this->storage->storeAccessToken($token, $this->serviceName);
84
85
			return $token;
86
		}
87
88
		throw new ProviderException('unverified token'); // @codeCoverageIgnore
89
	}
90
91
	/**
92
	 * @inheritdoc
93
	 * @throws \chillerlan\OAuth\Core\ProviderException
94
	 */
95
	public function getAuthURL(array $params = null, array $scopes = null):UriInterface{
96
		throw new ProviderException($this::AUTH_ERRMSG);
97
	}
98
99
	/**
100
	 * @inheritdoc
101
	 * @throws \chillerlan\OAuth\Core\ProviderException
102
	 */
103
	public function getAccessToken(string $code, string $state = null):AccessToken{
104
		throw new ProviderException($this::AUTH_ERRMSG);
105
	}
106
107
	/**
108
	 * @inheritDoc
109
	 */
110
	public function me():ResponseInterface{
111
		$response = $this->request('/v2/tokeninfo');
112
		$status   = $response->getStatusCode();
113
114
		if($status === 200){
115
			return $response;
116
		}
117
118
		$json = MessageUtil::decodeJSON($response);
119
120
		if(isset($json->text)){
121
			throw new ProviderException($json->text);
122
		}
123
124
		throw new ProviderException(sprintf('user info error error HTTP/%s', $status));
125
	}
126
127
}
128