Passed
Push — main ( 2560cc...5cc9d7 )
by Dylan
02:43 queued 14s
created

App::refreshAccessToken()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 18
rs 9.9
1
<?php
2
3
namespace Lifeboat;
4
5
use Lifeboat\Exceptions\InvalidArgumentException;
6
use Lifeboat\Exceptions\OAuthException;
7
use Lifeboat\Utils\Curl;
8
use Lifeboat\Utils\URL;
9
use Lifeboat\Utils\Utils;
10
11
/**
12
 * Class App
13
 * @package Lifeboat
14
 */
15
class App extends Connector {
16
17
    const CODE_URL      = '/oauth/code';
18
19
    const ACCESS_TOKEN_PARAM    = 'lb_app_access_token';
20
    const API_CHALLENGE_PARAM   = 'lb_app_api_challenge';
21
22
    private $_app_id;
23
    private $_app_secret;
24
    private $_api_challenge = '';
25
26
    /**
27
     * @param string $app_id
28
     * @param string $app_secret
29
     * @param string $auth_domain
30
     */
31
    public function __construct(string $app_id, string $app_secret, string $auth_domain = self::AUTH_DOMAIN)
32
    {
33
        if (!$app_id || !$app_secret) {
34
            throw new InvalidArgumentException(static::class . "expects an app_id and app_secret");
35
        }
36
37
        $this->setAppID($app_id);
38
        $this->setAppSecret($app_secret);
39
        $this->_auth_domain = rtrim($auth_domain, '/');
40
41
        if (session_status() === PHP_SESSION_ACTIVE) {
42
            $this->setAccessToken($_SESSION[self::ACCESS_TOKEN_PARAM] ?? '');
43
        }
44
    }
45
46
    /**
47
     * @return string
48
     */
49
    public function getAppID(): string
50
    {
51
        return $this->_app_id;
52
    }
53
54
    /**
55
     * @param string $id
56
     * @return $this
57
     */
58
    public function setAppID(string $id): App
59
    {
60
        $this->_app_id = $id;
61
        return $this;
62
    }
63
64
    /**
65
     * @return string
66
     */
67
    public function getAppSecret(): string
68
    {
69
        return $this->_app_secret;
70
    }
71
72
    /**
73
     * @param string $token
74
     * @return $this
75
     */
76
    public function setAccessToken(string $token): App
77
    {
78
        $this->_access_token = $token;
79
80
        if (session_status() === PHP_SESSION_ACTIVE) {
81
            $_SESSION[self::ACCESS_TOKEN_PARAM] = $this->_access_token;
82
        }
83
84
        return $this;
85
    }
86
87
    /**
88
     * @param string $secret
89
     * @return $this
90
     */
91
    public function setAppSecret(string $secret): App
92
    {
93
        $this->_app_secret = $secret;
94
        return $this;
95
    }
96
97
    /**
98
     * @param string $challenge
99
     * @return $this
100
     */
101
    public function setAPIChallenge(string $challenge): App
102
    {
103
        $this->_api_challenge = $challenge;
104
105
        if (session_status() === PHP_SESSION_ACTIVE) {
106
            $_SESSION[self::API_CHALLENGE_PARAM] = $this->_api_challenge;
107
        }
108
109
        return $this;
110
    }
111
112
    /**
113
     * @param bool $check_session
114
     * @return string
115
     */
116
    public function getAPIChallenge(bool $check_session = true): string
117
    {
118
        if ($this->_api_challenge) return $this->_api_challenge;
119
120
        if ($check_session && session_status() === PHP_SESSION_ACTIVE) {
121
            $this->setAPIChallenge($_SESSION[self::API_CHALLENGE_PARAM] ?? '');
122
            return $this->getAPIChallenge(false);
123
        }
124
125
        $this->_api_challenge = Utils::create_random_string(128);
126
        $this->setAPIChallenge($this->_api_challenge);
127
128
        return $this->_api_challenge;
129
    }
130
131
    /**
132
     * @param string $process_url
133
     * @param string $error_url
134
     * @param string $challenge
135
     * @return string
136
     */
137
    public function getAuthURL(string $process_url, string $error_url, string $challenge): string
138
    {
139
        $url    = URL::setGetVar('app_id', $this->getAppID(), $this->auth_url(self::CODE_URL));
140
        $url    = URL::setGetVar('process_url', urlencode($process_url), $url);
141
        $url    = URL::setGetVar('error_url', urlencode($error_url), $url);
142
143
        return URL::setGetVar('challenge', Utils::pack($challenge), $url);
144
    }
145
146
    /**
147
     * @param string|null $code
148
     * @return string
149
     */
150
    public function fetchAccessToken(string $code = null): string
151
    {
152
        $curl = new Curl($this->auth_url('/oauth/token'), [
153
            'app_id'        => $this->getAppID(),
154
            'challenge'     => $this->getAPIChallenge(),
155
            'app_secret'    => $this->getAppSecret(),
156
            'site_key'      => $this->getSiteKey(),
157
            'code'          => $code
158
        ]);
159
160
        $curl->setMethod('POST');
161
        $response = $curl->curl();
162
        $json = $response->getJSON();
163
        
164
        if (!$response->isValid() || !$json || !array_key_exists('access_token', $json)) {
165
            if (array_key_exists('error', $json)) throw new OAuthException($json['error']);
166
            return '';
167
        } else {
168
            $this->setAccessToken($json['access_token']);
169
170
            if (array_key_exists('store_data', $json) &&
171
                array_key_exists('domain', $json['store_data']) &&
172
                array_key_exists('site_key', $json['store_data'])
173
            ) {
174
                $this->setActiveSite($json['store_data']['domain'], $json['store_data']['site_key']);
175
            }
176
177
            return $this->getAccessToken(false);
178
        }
179
    }
180
181
    /**
182
     * @param bool $check_session
183
     * @return string
184
     */
185
    public function getAccessToken(bool $check_session = true): string
186
    {
187
        if ($this->_access_token) return $this->_access_token;
188
189
        if ($check_session && session_status() === PHP_SESSION_ACTIVE) {
190
            $this->setAccessToken($_SESSION[self::ACCESS_TOKEN_PARAM] ?? '');
191
            return $this->getAccessToken(false);
192
        }
193
194
        return '';
195
    }
196
197
    /**
198
     * Makes a request to the API to refresh the current access token
199
     *
200
     * @return $this
201
     * @throws OAuthException
202
     */
203
    public function refreshAccessToken(): Connector
204
    {
205
        $curl = new Curl($this->auth_url('/oauth/refresh_token'), [
206
            'access_token'  => $this->getAccessToken(),
207
            'app_id'        => $this->getAppID()
208
        ]);
209
210
        $curl->setMethod('POST');
211
        $response = $curl->curl();
212
        $json = $response->getJSON();
213
214
        if (!$response->isValid() || !$json || !array_key_exists('access_token', $json)) {
215
            throw new OAuthException($response->getError());
216
        } else {
217
            $this->setAccessToken($json['access_token']);
218
        }
219
220
        return $this;
221
    }
222
223
224
    /**
225
     * @return array
226
     * @throws OAuthException
227
     */
228
    public function getSites(): array
229
    {
230
        $curl = new Curl($this->auth_url(self::SITES_URL), [
231
            'access_token'  => $this->getAccessToken(),
232
            'app_id'        => $this->getAppID()
233
        ]);
234
235
        $curl->setMethod('POST');
236
        $response = $curl->curl();
237
238
        if (!$response->isValid()) {
239
            $error = $response->getJSON();
240
            throw new OAuthException($error['error'], $error['code']);
241
        }
242
243
        return $response->getJSON() ?? [];
244
    }
245
246
    /**
247
     * @return array
248
     * @throws Exceptions\OAuthException
249
     */
250
    public function getAuthHeaders(): array
251
    {
252
        $headers = parent::getAuthHeaders();
253
        $headers['app-id'] = $this->getAppID();
254
        
255
        if (!$this->getAccessToken()) $this->fetchAccessToken();
256
        if (!$this->getAccessToken()) throw new OAuthException("Access token has not been retreived");
257
        
258
        $headers['access-token'] = $this->getAccessToken();
259
        
260
        return $headers;
261
    }
262
}
263