Completed
Pull Request — master (#1148)
by
unknown
02:05
created

convertTimestampToDateTimeInterface()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright 2017 Facebook, Inc.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 */
23
namespace Facebook\Authentication;
24
25
use DateTimeInterface;
26
use Exception;
27
use Facebook\Exception\SDKException;
28
29
/**
30
 * Represents metadata from an access token.
31
 *
32
 * @package Facebook
33
 *
34
 * @see     https://developers.facebook.com/docs/graph-api/reference/debug_token
35
 */
36
class AccessTokenMetadata
37
{
38
    /**
39
     * The access token metadata.
40
     *
41
     * @var array
42
     */
43
    protected $metadata = [];
44
45
    /**
46
     * Properties that should be cast as DateTime objects.
47
     *
48
     * @var array
49
     */
50
    protected static $dateProperties = ['expires_at', 'issued_at'];
51
52
    /**
53
     * @param array $metadata
54
     *
55
     * @throws SDKException
56
     */
57 10
    public function __construct(array $metadata)
58
    {
59 10
        if (!isset($metadata['data'])) {
60 1
            throw new SDKException('Unexpected debug token response data.', 401);
61
        }
62
63 9
        $this->metadata = $metadata['data'];
64
65 9
        $this->castTimestampsToDateTimeInterface();
66 9
    }
67
68
    /**
69
     * Returns a value from the metadata.
70
     *
71
     * @param string $field   the property to retrieve
72
     * @param mixed  $default the default to return if the property doesn't exist
73
     *
74
     * @return mixed
75
     */
76 9
    public function getField($field, $default = null)
77
    {
78 9
        if (isset($this->metadata[$field])) {
79 9
            return $this->metadata[$field];
80
        }
81
82
        return $default;
83
    }
84
85
    /**
86
     * Returns a value from a child property in the metadata.
87
     *
88
     * @param string $parentField the parent property
89
     * @param string $field       the property to retrieve
90
     * @param mixed  $default     the default to return if the property doesn't exist
91
     *
92
     * @return mixed
93
     */
94 1
    public function getChildProperty($parentField, $field, $default = null)
95
    {
96 1
        if (!isset($this->metadata[$parentField])) {
97
            return $default;
98
        }
99
100 1
        if (!isset($this->metadata[$parentField][$field])) {
101
            return $default;
102
        }
103
104 1
        return $this->metadata[$parentField][$field];
105
    }
106
107
    /**
108
     * Returns a value from the error metadata.
109
     *
110
     * @param string $field   the property to retrieve
111
     * @param mixed  $default the default to return if the property doesn't exist
112
     *
113
     * @return mixed
114
     */
115 1
    public function getErrorProperty($field, $default = null)
116
    {
117 1
        return $this->getChildProperty('error', $field, $default);
118
    }
119
120
    /**
121
     * Returns a value from the "metadata" metadata. *Brain explodes*.
122
     *
123
     * @param string $field   the property to retrieve
124
     * @param mixed  $default the default to return if the property doesn't exist
125
     *
126
     * @return mixed
127
     */
128 1
    public function getMetadataProperty($field, $default = null)
129
    {
130 1
        return $this->getChildProperty('metadata', $field, $default);
131
    }
132
133
    /**
134
     * The ID of the application this access token is for.
135
     *
136
     * @return null|string
137
     */
138 3
    public function getAppId()
139
    {
140 3
        return $this->getField('app_id');
141
    }
142
143
    /**
144
     * Name of the application this access token is for.
145
     *
146
     * @return null|string
147
     */
148 1
    public function getApplication()
149
    {
150 1
        return $this->getField('application');
151
    }
152
153
    /**
154
     * Any error that a request to the graph api
155
     * would return due to the access token.
156
     *
157
     * @return null|bool
158
     */
159 1
    public function isError()
160
    {
161 1
        return $this->getField('error') !== null;
162
    }
163
164
    /**
165
     * The error code for the error.
166
     *
167
     * @return null|int
168
     */
169 1
    public function getErrorCode()
170
    {
171 1
        return $this->getErrorProperty('code');
172
    }
173
174
    /**
175
     * The error message for the error.
176
     *
177
     * @return null|string
178
     */
179 1
    public function getErrorMessage()
180
    {
181 1
        return $this->getErrorProperty('message');
182
    }
183
184
    /**
185
     * The error subcode for the error.
186
     *
187
     * @return null|int
188
     */
189 1
    public function getErrorSubcode()
190
    {
191 1
        return $this->getErrorProperty('subcode');
192
    }
193
194
    /**
195
     * DateTime when this access token expires.
196
     *
197
     * @return null|DateTimeInterface
198
     */
199 3
    public function getExpiresAt()
200
    {
201 3
        return $this->getField('expires_at');
202
    }
203
204
    /**
205
     * Whether the access token is still valid or not.
206
     *
207
     * @return null|bool
208
     */
209 1
    public function getIsValid()
210
    {
211 1
        return $this->getField('is_valid');
212
    }
213
214
    /**
215
     * DateTime when this access token was issued.
216
     *
217
     * Note that the issued_at field is not returned
218
     * for short-lived access tokens.
219
     *
220
     * @see https://developers.facebook.com/docs/facebook-login/access-tokens#debug
221
     *
222
     * @return null|DateTimeInterface
223
     */
224 1
    public function getIssuedAt()
225
    {
226 1
        return $this->getField('issued_at');
227
    }
228
229
    /**
230
     * General metadata associated with the access token.
231
     * Can contain data like 'sso', 'auth_type', 'auth_nonce'.
232
     *
233
     * @return null|array
234
     */
235
    public function getMetadata()
236
    {
237
        return $this->getField('metadata');
238
    }
239
240
    /**
241
     * The 'sso' child property from the 'metadata' parent property.
242
     *
243
     * @return null|string
244
     */
245 1
    public function getSso()
246
    {
247 1
        return $this->getMetadataProperty('sso');
248
    }
249
250
    /**
251
     * The 'auth_type' child property from the 'metadata' parent property.
252
     *
253
     * @return null|string
254
     */
255 1
    public function getAuthType()
256
    {
257 1
        return $this->getMetadataProperty('auth_type');
258
    }
259
260
    /**
261
     * The 'auth_nonce' child property from the 'metadata' parent property.
262
     *
263
     * @return null|string
264
     */
265 1
    public function getAuthNonce()
266
    {
267 1
        return $this->getMetadataProperty('auth_nonce');
268
    }
269
270
    /**
271
     * For impersonated access tokens, the ID of
272
     * the page this token contains.
273
     *
274
     * @return null|string
275
     */
276 1
    public function getProfileId()
277
    {
278 1
        return $this->getField('profile_id');
279
    }
280
281
    /**
282
     * List of permissions that the user has granted for
283
     * the app in this access token.
284
     *
285
     * @return array
286
     */
287 1
    public function getScopes()
288
    {
289 1
        return $this->getField('scopes');
290
    }
291
292
    /**
293
     * The ID of the user this access token is for.
294
     *
295
     * @return null|string
296
     */
297 4
    public function getUserId()
298
    {
299 4
        return $this->getField('user_id');
300
    }
301
302
    /**
303
     * Ensures the app ID from the access token
304
     * metadata is what we expect.
305
     *
306
     * @param string $appId
307
     *
308
     * @throws SDKException
309
     */
310 2
    public function validateAppId($appId)
311
    {
312 2
        if ($this->getAppId() !== $appId) {
313 1
            throw new SDKException('Access token metadata contains unexpected app ID.', 401);
314
        }
315 1
    }
316
317
    /**
318
     * Ensures the user ID from the access token
319
     * metadata is what we expect.
320
     *
321
     * @param string $userId
322
     *
323
     * @throws SDKException
324
     */
325 2
    public function validateUserId($userId)
326
    {
327 2
        if ($this->getUserId() !== $userId) {
328 1
            throw new SDKException('Access token metadata contains unexpected user ID.', 401);
329
        }
330 1
    }
331
332
    /**
333
     * Ensures the access token has not expired yet.
334
     *
335
     * @throws SDKException
336
     */
337 2
    public function validateExpiration()
338
    {
339 2
        if (!$this->getExpiresAt() instanceof \DateTime) {
340 2
            return;
341
        }
342
343
        if ($this->getExpiresAt()->getTimestamp() < time()) {
344
            throw new SDKException('Inspection of access token metadata shows that the access token has expired.', 401);
345
        }
346
    }
347
348
    /**
349
     * Converts a unix timestamp into a DateTime entity.
350
     *
351
     * @param int $timestamp
352
     *
353
     * @return DateTimeInterface
354
     * @throws Exception
355
     */
356 8
    private function convertTimestampToDateTimeInterface($timestamp)
357
    {
358 8
        $dt = new \DateTimeImmutable();
359 8
        $dt->setTimestamp($timestamp);
360
361 8
        return $dt;
362
    }
363
364
    /**
365
     * Casts the unix timestamps as DateTimeInterface entities.
366
     * @throws Exception
367
     */
368 9
    private function castTimestampsToDateTimeInterface()
369
    {
370 9
        foreach (static::$dateProperties as $key) {
371 9
            if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) {
372 9
                $this->metadata[$key] = $this->convertTimestampToDateTimeInterface($this->metadata[$key]);
373
            }
374
        }
375 9
    }
376
}
377