Completed
Push — main ( 293a96...661ea7 )
by Dylan
02:41 queued 02:41
created

App::curl_api()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 2
nop 5
dl 0
loc 10
rs 10
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
            'site_key'      => $this->getSiteKey()
209
        ]);
210
211
        $curl->setMethod('POST');
212
        $response = $curl->curl();
213
        $json = $response->getJSON();
214
215
        if (!$response->isValid() || !$json || !array_key_exists('access_token', $json)) {
216
            throw new OAuthException($response->getError());
217
        } else {
218
            $this->setAccessToken($json['access_token']);
219
        }
220
221
        return $this;
222
    }
223
224
225
    /**
226
     * @return array
227
     * @throws OAuthException
228
     */
229
    public function getSites(): array
230
    {
231
        $curl = new Curl($this->auth_url(self::SITES_URL), [
232
            'access_token'  => $this->getAccessToken(),
233
            'app_id'        => $this->getAppID()
234
        ]);
235
236
        $curl->setMethod('POST');
237
        $response = $curl->curl();
238
239
        if (!$response->isValid()) {
240
            $error = $response->getJSON();
241
            throw new OAuthException($error['error'], $error['code']);
242
        }
243
244
        return $response->getJSON() ?? [];
245
    }
246
247
    /**
248
     * @param string $url
249
     * @param string $method
250
     * @param array $data
251
     * @param array $headers
252
     * @param bool $retry
253
     * @return CurlResponse
254
     * @throws OAuthException
255
     */
256
    public function curl_api(string $url, string $method = 'GET', array $data = [], array $headers = [], bool $retry = true): CurlResponse
257
    {
258
        $response = parent::curl_api($url, $method, $data, $headers);
259
260
        if ($retry && $response->getHTTPCode() === 401) {
261
            $this->fetchAccessToken();
262
            return $this->curl_api($url, $method, $data, $headers, false);
263
        }
264
265
        return $response;
266
    }
267
268
    /**
269
     * @return array
270
     * @throws Exceptions\OAuthException
271
     */
272
    public function getAuthHeaders(): array
273
    {
274
        $headers = parent::getAuthHeaders();
275
        $headers['app-id'] = $this->getAppID();
276
        return $headers;
277
    }
278
}
279