Completed
Pull Request — master (#1366)
by mingyoung
02:21
created

AccessToken::getRefreshedToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace EasyWeChat\Kernel;
13
14
use EasyWeChat\Kernel\Contracts\AccessTokenInterface;
15
use EasyWeChat\Kernel\Exceptions\HttpException;
16
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
17
use EasyWeChat\Kernel\Traits\HasHttpRequests;
18
use EasyWeChat\Kernel\Traits\InteractsWithCache;
19
use Pimple\Container;
20
use Psr\Http\Message\RequestInterface;
21
use Psr\Http\Message\ResponseInterface;
22
23
/**
24
 * Class AccessToken.
25
 *
26
 * @author overtrue <[email protected]>
27
 */
28
abstract class AccessToken implements AccessTokenInterface
29
{
30
    use HasHttpRequests, InteractsWithCache;
0 ignored issues
show
Bug introduced by
The trait EasyWeChat\Kernel\Traits\HasHttpRequests requires the property $baseUri which is not provided by EasyWeChat\Kernel\AccessToken.
Loading history...
31
32
    /**
33
     * @var \Pimple\Container
34
     */
35
    protected $app;
36
37
    /**
38
     * @var string
39
     */
40
    protected $requestMethod = 'GET';
41
42
    /**
43
     * @var string
44
     */
45
    protected $endpointToGetToken;
46
47
    /**
48
     * @var string
49
     */
50
    protected $queryName;
51
52
    /**
53
     * @var array
54
     */
55
    protected $token;
56
57
    /**
58
     * @var int
59
     */
60
    protected $safeSeconds = 500;
61
62
    /**
63
     * @var string
64
     */
65
    protected $tokenKey = 'access_token';
66
67
    /**
68
     * @var string
69
     */
70
    protected $cachePrefix = 'easywechat.kernel.access_token.';
71
72
    /**
73
     * AccessToken constructor.
74
     *
75
     * @param \Pimple\Container $app
76
     */
77
    public function __construct(Container $app)
78
    {
79
        $this->app = $app;
80
    }
81
82
    /**
83
     * @return array
84
     *
85
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
86
     * @throws \Psr\SimpleCache\InvalidArgumentException
87
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
88
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
89
     */
90
    public function getRefreshedToken(): array
91
    {
92
        return $this->getToken(true);
93
    }
94
95
    /**
96
     * @param bool $refresh
97
     *
98
     * @return array
99
     *
100
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
101
     * @throws \Psr\SimpleCache\InvalidArgumentException
102
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
103
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
104
     */
105
    public function getToken(bool $refresh = false): array
106
    {
107
        $cacheKey = $this->getCacheKey();
108
        $cache = $this->getCache();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
109
110
        if (!$refresh && $cache->has($cacheKey)) {
111
            return $cache->get($cacheKey);
112
        }
113
114
        $token = $this->requestToken($this->getCredentials(), true);
115
116
        $this->setToken($token[$this->tokenKey], $token['expires_in'] ?? 7200);
117
118
        return $token;
119
    }
120
121
    /**
122
     * @param string $token
123
     * @param int    $lifetime
124
     *
125
     * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface
126
     *
127
     * @throws \Psr\SimpleCache\InvalidArgumentException
128
     */
129
    public function setToken(string $token, int $lifetime = 7200): AccessTokenInterface
130
    {
131
        $this->getCache()->set($this->getCacheKey(), [
132
            $this->tokenKey => $token,
133
            'expires_in' => $lifetime,
134
        ], $lifetime - $this->safeSeconds);
135
136
        return $this;
137
    }
138
139
    /**
140
     * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface
141
     *
142
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
143
     * @throws \Psr\SimpleCache\InvalidArgumentException
144
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
145
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
146
     */
147
    public function refresh(): AccessTokenInterface
148
    {
149
        $this->getToken(true);
150
151
        return $this;
152
    }
153
154
    /**
155
     * @param array $credentials
156
     * @param bool  $toArray
157
     *
158
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
159
     *
160
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
161
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
162
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
163
     */
164
    public function requestToken(array $credentials, $toArray = false)
165
    {
166
        $response = $this->sendRequest($credentials);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
167
        $result = json_decode($response->getBody()->getContents(), true);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
168
        $formatted = $this->castResponseToType($response, $this->app['config']->get('response_type'));
169
170
        if (empty($result[$this->tokenKey])) {
171
            throw new HttpException('Request access_token fail: '.json_encode($result, JSON_UNESCAPED_UNICODE), $response, $formatted);
172
        }
173
174
        return $toArray ? $result : $formatted;
175
    }
176
177
    /**
178
     * @param \Psr\Http\Message\RequestInterface $request
179
     * @param array                              $requestOptions
180
     *
181
     * @return \Psr\Http\Message\RequestInterface
182
     *
183
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
184
     * @throws \Psr\SimpleCache\InvalidArgumentException
185
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
186
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
187
     */
188
    public function applyToRequest(RequestInterface $request, array $requestOptions = []): RequestInterface
189
    {
190
        parse_str($request->getUri()->getQuery(), $query);
191
192
        $query = http_build_query(array_merge($this->getQuery(), $query));
193
194
        return $request->withUri($request->getUri()->withQuery($query));
195
    }
196
197
    /**
198
     * Send http request.
199
     *
200
     * @param array $credentials
201
     *
202
     * @return ResponseInterface
203
     *
204
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
205
     */
206
    protected function sendRequest(array $credentials): ResponseInterface
207
    {
208
        $options = [
209
            ('GET' === $this->requestMethod) ? 'query' : 'json' => $credentials,
210
        ];
211
212
        return $this->setHttpClient($this->app['http_client'])->request($this->getEndpoint(), $this->requestMethod, $options);
213
    }
214
215
    /**
216
     * @return string
217
     */
218
    protected function getCacheKey()
219
    {
220
        return $this->cachePrefix.md5(json_encode($this->getCredentials()));
221
    }
222
223
    /**
224
     * The request query will be used to add to the request.
225
     *
226
     * @return array
227
     *
228
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
229
     * @throws \Psr\SimpleCache\InvalidArgumentException
230
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
231
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
232
     */
233
    protected function getQuery(): array
234
    {
235
        return [$this->queryName ?? $this->tokenKey => $this->getToken()[$this->tokenKey]];
236
    }
237
238
    /**
239
     * @return string
240
     *
241
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
242
     */
243
    public function getEndpoint(): string
244
    {
245
        if (empty($this->endpointToGetToken)) {
246
            throw new InvalidArgumentException('No endpoint for access token request.');
247
        }
248
249
        return $this->endpointToGetToken;
250
    }
251
252
    /**
253
     * @return string
254
     */
255
    public function getTokenKey()
256
    {
257
        return $this->tokenKey;
258
    }
259
260
    /**
261
     * Credential for get token.
262
     *
263
     * @return array
264
     */
265
    abstract protected function getCredentials(): array;
266
}
267