friendship ended with social-app. php is my new best friend
1<?php
2/**
3 * Class DeviantArt
4 *
5 * @created 26.10.2017
6 * @author Smiley <smiley@chillerlan.net>
7 * @copyright 2017 Smiley
8 * @license MIT
9 *
10 * @noinspection PhpUnused
11 */
12declare(strict_types=1);
13
14namespace chillerlan\OAuth\Providers;
15
16use chillerlan\HTTP\Utils\MessageUtil;
17use chillerlan\OAuth\Core\{
18 AccessToken, AuthenticatedUser, ClientCredentials, ClientCredentialsTrait,
19 CSRFToken, OAuth2Provider, TokenInvalidate, TokenRefresh, UserInfo,
20};
21use chillerlan\OAuth\Storage\MemoryStorage;
22use Throwable;
23use function sprintf;
24
25/**
26 * DeviantArt OAuth2
27 *
28 * @link https://www.deviantart.com/developers/
29 */
30class DeviantArt extends OAuth2Provider implements ClientCredentials, CSRFToken, TokenInvalidate, TokenRefresh, UserInfo{
31 use ClientCredentialsTrait;
32
33 public const IDENTIFIER = 'DEVIANTART';
34
35 public const SCOPE_BASIC = 'basic';
36 public const SCOPE_BROWSE = 'browse';
37 public const SCOPE_COLLECTION = 'collection';
38 public const SCOPE_COMMENT_POST = 'comment.post';
39 public const SCOPE_FEED = 'feed';
40 public const SCOPE_GALLERY = 'gallery';
41 public const SCOPE_MESSAGE = 'message';
42 public const SCOPE_NOTE = 'note';
43 public const SCOPE_STASH = 'stash';
44 public const SCOPE_USER = 'user';
45 public const SCOPE_USER_MANAGE = 'user.manage';
46
47 public const DEFAULT_SCOPES = [
48 self::SCOPE_BASIC,
49 self::SCOPE_BROWSE,
50 ];
51
52 public const HEADERS_API = [
53 'dA-minor-version' => '20210526',
54 ];
55
56 protected string $authorizationURL = 'https://www.deviantart.com/oauth2/authorize';
57 protected string $accessTokenURL = 'https://www.deviantart.com/oauth2/token';
58 protected string $revokeURL = 'https://www.deviantart.com/oauth2/revoke';
59 protected string $apiURL = 'https://www.deviantart.com/api/v1/oauth2';
60 protected string|null $userRevokeURL = 'https://www.deviantart.com/settings/applications';
61 protected string|null $apiDocs = 'https://www.deviantart.com/developers/';
62 protected string|null $applicationURL = 'https://www.deviantart.com/developers/apps';
63
64 /** @codeCoverageIgnore */
65 public function me():AuthenticatedUser{
66 $json = $this->getMeResponseData('/user/whoami');
67
68 $userdata = [
69 'data' => $json,
70 'avatar' => $json['usericon'],
71 'handle' => $json['username'],
72 'id' => $json['userid'],
73 'url' => sprintf('https://www.deviantart.com/%s', $json['username']),
74 ];
75
76 return new AuthenticatedUser($userdata);
77 }
78
79 public function invalidateAccessToken(AccessToken|null $token = null, string|null $type = null):bool{
80
81 if($token !== null){
82 // to revoke a token different from the one of the currently authenticated user,
83 // we're going to clone the provider and feed the other token for the invalidate request
84 return (clone $this)
85 ->setStorage(new MemoryStorage)
86 ->storeAccessToken($token)
87 ->invalidateAccessToken()
88 ;
89 }
90
91 $request = $this->requestFactory->createRequest('POST', $this->revokeURL);
92 $response = $this->http->sendRequest($this->getRequestAuthorization($request));
93
94 try{
95 $json = MessageUtil::decodeJSON($response);
96 }
97 catch(Throwable){
98 return false;
99 }
100
101 if($response->getStatusCode() === 200 && !empty($json->success)){
102 // delete the token from storage
103 $this->storage->clearAccessToken($this->name);
104
105 return true;
106 }
107
108 return false; // @codeCoverageIgnore
109 }
110
111}