Completed
Push — master ( b0169f...379291 )
by Tharanga
05:57
created

SpotifyConnection::getSelf()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 1
dl 0
loc 18
rs 9.9
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 25-02-2019
5
 */
6
7
namespace TSK\SSO\ThirdParty\Spotify;
8
9
use TSK\SSO\Http\CurlRequest;
10
use TSK\SSO\ThirdParty;
11
use TSK\SSO\ThirdParty\CommonAccessToken;
12
use TSK\SSO\ThirdParty\Exception\NoThirdPartyEmailFoundException;
13
use TSK\SSO\ThirdParty\Exception\ThirdPartyConnectionFailedException;
14
use TSK\SSO\ThirdParty\ThirdPartyUser;
15
use TSK\SSO\ThirdParty\VendorConnection;
16
17
/**
18
 * @codeCoverageIgnore
19
 * @package TSK\SSO\ThirdParty\Spotify
20
 * @see https://developer.spotify.com/documentation/general/guides/authorization-guide/
21
 */
22
class SpotifyConnection implements VendorConnection
23
{
24
    const API_BASE = 'https://accounts.spotify.com';
25
26
    /**
27
     * @var SpotifyApiConfiguration
28
     */
29
    private $apiConfiguration;
30
31
    /**
32
     * @var CurlRequest
33
     */
34
    private $curlClient;
35
36
    /**
37
     * SpotifyConnection constructor.
38
     * @param SpotifyApiConfiguration $apiConfiguration
39
     * @param CurlRequest $curlClient
40
     */
41
    public function __construct(SpotifyApiConfiguration $apiConfiguration, CurlRequest $curlClient)
42
    {
43
        $this->apiConfiguration = $apiConfiguration;
44
        $this->curlClient = $curlClient;
45
    }
46
47
    /**
48
     * Use this to get a link to redirect a user to the third party login
49
     *
50
     * @return string|null
51
     */
52
    public function getGrantUrl()
53
    {
54
        return sprintf(
55
            '%s/authorize?client_id=%s&scope=%s&response_type=code&redirect_uri=%s&state=%s',
56
            self::API_BASE,
57
            $this->apiConfiguration->clientId(),
58
            urlencode('user-read-email'),
59
            urlencode($this->apiConfiguration->redirectUrl()),
60
            $this->apiConfiguration->ourSecretState()
61
        );
62
    }
63
64
    /**
65
     * Grants a new access token
66
     *
67
     * @return CommonAccessToken
68
     * @throws ThirdPartyConnectionFailedException
69
     */
70
    public function grantNewAccessToken()
71
    {
72
        if (empty($_GET['code'])
73
            || empty($_GET['state'])
74
            || $_GET['state'] !== $this->apiConfiguration->ourSecretState()
75
        ) {
76
            throw new ThirdPartyConnectionFailedException('Invalid request!');
77
        }
78
79
        $accessTokenJsonResponse = $this->curlClient->postUrlEncoded(
80
            sprintf("%s/api/token", self::API_BASE),
81
            sprintf(
82
                'client_id=%s&client_secret=%s&grant_type=authorization_code&redirect_uri=%s&code=%s',
83
                $this->apiConfiguration->clientId(),
84
                $this->apiConfiguration->clientSecret(),
85
                urlencode($this->apiConfiguration->redirectUrl()),
86
                $_GET['code']
87
            )
88
        );
89
90
        $accessTokenData = json_decode($accessTokenJsonResponse, true);
91
        if (empty($accessTokenData['access_token'])) {
92
            throw new ThirdPartyConnectionFailedException('Failed to establish a new third party vendor connection.');
93
        }
94
95
        return new CommonAccessToken(
96
            $accessTokenData['access_token'],
97
            ThirdParty::SPOTIFY
98
        );
99
    }
100
101
    /**
102
     * Use this to retrieve the current user's third party user data using there existing granted access token
103
     *
104
     * @param CommonAccessToken $accessToken
105
     * @return ThirdPartyUser
106
     * @throws NoThirdPartyEmailFoundException
107
     * @throws ThirdPartyConnectionFailedException
108
     */
109
    public function getSelf(CommonAccessToken $accessToken)
110
    {
111
        $userJsonInfo = $this->curlClient->get(
112
            'https://api.spotify.com/v1/me',
113
            array(
114
                sprintf('Authorization: Bearer %s', $accessToken->token()),
115
            )
116
        );
117
118
        $userInfo = json_decode($userJsonInfo, true);
119
        if (empty($userInfo['email'])) {
120
            throw new NoThirdPartyEmailFoundException('An email address cannot be found from vendor');
121
        }
122
123
        return new ThirdPartyUser(
124
            $userInfo['id'],
125
            $userInfo['display_name'],
126
            $userInfo['email']
127
        );
128
    }
129
130
    /**
131
     * Use this to revoke the access to the third party data.
132
     * This will completely remove the access from the vendor side.
133
     *
134
     * @param CommonAccessToken $accessToken
135
     * @return bool
136
     */
137
    public function revokeAccess(CommonAccessToken $accessToken)
138
    {
139
        // noop : cannot find documentation on how to revoke the app's access.
140
        return true;
141
    }
142
}
143