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}