Failed Conditions
Push — master ( 22ddb5...a86abe )
by Florent
03:15
created

Authorization   F

Complexity

Total Complexity 52

Size/Duplication

Total Lines 558
Duplicated Lines 0 %

Coupling/Cohesion

Components 12
Dependencies 1

Importance

Changes 0
Metric Value
wmc 52
lcom 12
cbo 1
dl 0
loc 558
rs 2.9523
c 0
b 0
f 0

43 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A create() 0 4 1
A getQueryParams() 0 4 1
A hasQueryParam() 0 4 1
A getQueryParam() 0 6 1
A getClient() 0 4 1
A withTokenType() 0 7 1
A getTokenType() 0 4 1
A withResponseTypes() 0 8 1
A getResponseTypes() 0 4 1
A withResponseMode() 0 7 1
A getResponseMode() 0 4 1
A withRedirectUri() 0 7 1
A getRedirectUri() 0 4 1
A withUserAccount() 0 8 1
A getUserAccount() 0 4 1
A withResponseParameter() 0 7 1
A getResponseParameters() 0 4 1
A getResponseParameter() 0 6 1
A hasResponseParameter() 0 4 1
A withResponseHeader() 0 7 1
A getResponseHeaders() 0 4 1
A isUserAccountFullyAuthenticated() 0 4 1
A getPrompt() 0 8 2
A hasUiLocales() 0 4 1
A getUiLocales() 0 4 2
A hasPrompt() 0 4 1
A withScopes() 0 7 1
A getScopes() 0 4 1
A hasScope() 0 4 2
A withoutScope() 0 10 2
A addScope() 0 10 2
A isAuthorized() 0 4 1
A allow() 0 7 1
A deny() 0 7 1
A hasData() 0 4 1
A getData() 0 6 1
A withData() 0 7 1
A getResourceServer() 0 4 1
A withResourceServer() 0 7 1
A hasOfflineAccess() 0 15 4
A withConsentScreenOption() 0 7 1
A withoutConsentScreenOption() 0 11 2

How to fix   Complexity   

Complex Class

Complex classes like Authorization often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Authorization, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2017 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Component\Server\Endpoint\Authorization;
15
16
use Assert\Assertion;
17
use OAuth2Framework\Component\Server\Model\Client\Client;
18
use OAuth2Framework\Component\Server\Model\ResourceServer\ResourceServerInterface;
19
use OAuth2Framework\Component\Server\Model\UserAccount\UserAccountInterface;
20
use OAuth2Framework\Component\Server\ResponseMode\ResponseModeInterface;
21
use OAuth2Framework\Component\Server\ResponseType\ResponseTypeInterface;
22
use OAuth2Framework\Component\Server\TokenType\TokenTypeInterface;
23
24
final class Authorization
25
{
26
    /**
27
     * @var bool|null
28
     */
29
    private $authorized = null;
30
31
    /**
32
     * @var Client
33
     */
34
    private $client;
35
36
    /**
37
     * @var UserAccountInterface|null
38
     */
39
    private $userAccount = null;
40
41
    /**
42
     * @var null|bool
43
     */
44
    private $userAccountFullyAuthenticated = null;
45
46
    /**
47
     * @var string[]
48
     */
49
    private $scopes = [];
50
51
    /**
52
     * @var array
53
     */
54
    private $data = [];
55
56
    /**
57
     * @var TokenTypeInterface|null
58
     */
59
    private $tokenType = null;
60
61
    /**
62
     * @var ResponseTypeInterface[]
63
     */
64
    private $responseTypes = [];
65
66
    /**
67
     * @var ResponseModeInterface|null
68
     */
69
    private $responseMode = null;
70
71
    /**
72
     * @var array
73
     */
74
    private $queryParameters = [];
75
76
    /**
77
     * @var string|null
78
     */
79
    private $redirectUri = null;
80
81
    /**
82
     * @var array
83
     */
84
    private $consentScreenOptions = [];
85
86
    /**
87
     * @var array
88
     */
89
    private $responseParameters = [];
90
91
    /**
92
     * @var array
93
     */
94
    private $responseHeaders = [];
95
96
    /**
97
     * @var null|ResourceServerInterface
98
     */
99
    private $resourceServer = null;
100
101
    /**
102
     * Authorization constructor.
103
     *
104
     * @param Client $client
105
     * @param array  $queryParameters
106
     */
107
    private function __construct(Client $client, array $queryParameters)
108
    {
109
        $this->client = $client;
110
        $this->queryParameters = $queryParameters;
111
    }
112
113
    /**
114
     * @param Client $client
115
     * @param array  $queryParameters
116
     *
117
     * @return Authorization
118
     */
119
    public static function create(Client $client, array $queryParameters): Authorization
120
    {
121
        return new self($client, $queryParameters);
122
    }
123
124
    /**
125
     * @return array
126
     */
127
    public function getQueryParams(): array
128
    {
129
        return $this->queryParameters;
130
    }
131
132
    /**
133
     * @param string $param
134
     *
135
     * @return bool
136
     */
137
    public function hasQueryParam(string $param): bool
138
    {
139
        return array_key_exists($param, $this->queryParameters);
140
    }
141
142
    /**
143
     * @param string $param
144
     *
145
     * @return mixed
146
     */
147
    public function getQueryParam(string $param)
148
    {
149
        Assertion::true($this->hasQueryParam($param), sprintf('Invalid parameter \'%s\'', $param));
150
151
        return $this->queryParameters[$param];
152
    }
153
154
    /**
155
     * @return Client
156
     */
157
    public function getClient(): Client
158
    {
159
        return $this->client;
160
    }
161
162
    /**
163
     * @param TokenTypeInterface $tokenType
164
     *
165
     * @return Authorization
166
     */
167
    public function withTokenType(TokenTypeInterface $tokenType): Authorization
168
    {
169
        $clone = clone $this;
170
        $clone->tokenType = $tokenType;
171
172
        return $clone;
173
    }
174
175
    /**
176
     * @return null|TokenTypeInterface
177
     */
178
    public function getTokenType(): ? TokenTypeInterface
179
    {
180
        return $this->tokenType;
181
    }
182
183
    /**
184
     * @param ResponseTypeInterface[] $responseTypes
185
     *
186
     * @return Authorization
187
     */
188
    public function withResponseTypes(array $responseTypes): Authorization
189
    {
190
        Assertion::allIsInstanceOf($responseTypes, ResponseTypeInterface::class);
191
        $clone = clone $this;
192
        $clone->responseTypes = $responseTypes;
193
194
        return $clone;
195
    }
196
197
    /**
198
     * @return ResponseTypeInterface[]
199
     */
200
    public function getResponseTypes(): array
201
    {
202
        return $this->responseTypes;
203
    }
204
205
    /**
206
     * @param ResponseModeInterface $responseMode
207
     *
208
     * @return Authorization
209
     */
210
    public function withResponseMode(ResponseModeInterface $responseMode): Authorization
211
    {
212
        $clone = clone $this;
213
        $clone->responseMode = $responseMode;
214
215
        return $clone;
216
    }
217
218
    /**
219
     * @return null|ResponseModeInterface
220
     */
221
    public function getResponseMode(): ? ResponseModeInterface
222
    {
223
        return $this->responseMode;
224
    }
225
226
    /**
227
     * @param string $redirectUri
228
     *
229
     * @return Authorization
230
     */
231
    public function withRedirectUri(string $redirectUri): Authorization
232
    {
233
        $clone = clone $this;
234
        $clone->redirectUri = $redirectUri;
235
236
        return $clone;
237
    }
238
239
    /**
240
     * @return null|string
241
     */
242
    public function getRedirectUri(): ? string
243
    {
244
        return $this->redirectUri;
245
    }
246
247
    /**
248
     * @param UserAccountInterface $userAccount
249
     * @param bool                 $isFullyAuthenticated
250
     *
251
     * @return Authorization
252
     */
253
    public function withUserAccount(UserAccountInterface $userAccount, bool $isFullyAuthenticated): Authorization
254
    {
255
        $clone = clone $this;
256
        $clone->userAccount = $userAccount;
257
        $clone->userAccountFullyAuthenticated = $isFullyAuthenticated;
258
259
        return $clone;
260
    }
261
262
    /**
263
     * @return null|UserAccountInterface
264
     */
265
    public function getUserAccount(): ? UserAccountInterface
266
    {
267
        return $this->userAccount;
268
    }
269
270
    /**
271
     * @param string $responseParameter
272
     * @param mixed  $value
273
     *
274
     * @return Authorization
275
     */
276
    public function withResponseParameter(string $responseParameter, $value): Authorization
277
    {
278
        $clone = clone $this;
279
        $clone->responseParameters[$responseParameter] = $value;
280
281
        return $clone;
282
    }
283
284
    /**
285
     * @return array
286
     */
287
    public function getResponseParameters(): array
288
    {
289
        return $this->responseParameters;
290
    }
291
292
    /**
293
     * @param string $param
294
     *
295
     * @return mixed
296
     */
297
    public function getResponseParameter(string $param)
298
    {
299
        Assertion::true($this->hasResponseParameter($param), sprintf('Invalid response parameter \'%s\'', $param));
300
301
        return $this->getResponseParameters()[$param];
302
    }
303
304
    /**
305
     * @param string $param
306
     *
307
     * @return bool
308
     */
309
    public function hasResponseParameter(string $param): bool
310
    {
311
        return array_key_exists($param, $this->getResponseParameters());
312
    }
313
314
    /**
315
     * @param string $responseHeader
316
     * @param mixed  $value
317
     *
318
     * @return Authorization
319
     */
320
    public function withResponseHeader(string $responseHeader, $value): Authorization
321
    {
322
        $clone = clone $this;
323
        $clone->responseHeaders[$responseHeader] = $value;
324
325
        return $clone;
326
    }
327
328
    /**
329
     * @return array
330
     */
331
    public function getResponseHeaders(): array
332
    {
333
        return $this->responseHeaders;
334
    }
335
336
    /**
337
     * @return bool|null
338
     */
339
    public function isUserAccountFullyAuthenticated(): ? bool
340
    {
341
        return $this->userAccountFullyAuthenticated;
342
    }
343
344
    /**
345
     * @return string[]
346
     */
347
    public function getPrompt(): array
348
    {
349
        if (!$this->hasQueryParam('prompt')) {
350
            return [];
351
        }
352
353
        return explode(' ', $this->getQueryParam('prompt'));
354
    }
355
356
    /**
357
     * @return bool
358
     */
359
    public function hasUiLocales(): bool
360
    {
361
        return $this->hasQueryParam('ui_locales');
362
    }
363
364
    /**
365
     * @return string[]
366
     */
367
    public function getUiLocales(): array
368
    {
369
        return $this->hasQueryParam('ui_locales') ? explode(' ', $this->getQueryParam('ui_locales')) : [];
370
    }
371
372
    /**
373
     * @param string $prompt
374
     *
375
     * @return bool
376
     */
377
    public function hasPrompt(string $prompt): bool
378
    {
379
        return in_array($prompt, $this->getPrompt());
380
    }
381
382
    /**
383
     * @param array $scope
384
     *
385
     * @return Authorization
386
     */
387
    public function withScopes(array $scope): Authorization
388
    {
389
        $clone = clone $this;
390
        $clone->scopes = $scope;
391
392
        return $clone;
393
    }
394
395
    /**
396
     * @return array
397
     */
398
    public function getScopes(): array
399
    {
400
        return $this->scopes;
401
    }
402
403
    /**
404
     * @param string $scope
405
     *
406
     * @return bool
407
     */
408
    public function hasScope(string $scope): bool
409
    {
410
        return null !== $this->scopes && in_array($scope, $this->scopes);
411
    }
412
413
    /**
414
     * @param string $scope
415
     *
416
     * @return Authorization
417
     */
418
    public function withoutScope(string $scope): Authorization
419
    {
420
        if (!$this->hasScope($scope)) {
421
            return $this;
422
        }
423
        $clone = clone $this;
424
        unset($clone->scopes[array_search($scope, $clone->scopes)]);
425
426
        return $clone;
427
    }
428
429
    /**
430
     * @param string $scope
431
     *
432
     * @return Authorization
433
     */
434
    public function addScope(string $scope): Authorization
435
    {
436
        if ($this->hasScope($scope)) {
437
            return $this;
438
        }
439
        $clone = clone $this;
440
        $clone->scopes[] = $scope;
441
442
        return $clone;
443
    }
444
445
    /**
446
     * @return bool|null
447
     */
448
    public function isAuthorized(): ? bool
449
    {
450
        return $this->authorized;
451
    }
452
453
    /**
454
     * @return Authorization
455
     */
456
    public function allow(): Authorization
457
    {
458
        $clone = clone $this;
459
        $clone->authorized = true;
460
461
        return $clone;
462
    }
463
464
    /**
465
     * @return Authorization
466
     */
467
    public function deny(): Authorization
468
    {
469
        $clone = clone $this;
470
        $clone->authorized = false;
471
472
        return $clone;
473
    }
474
475
    /**
476
     * @param string $key
477
     *
478
     * @return bool
479
     */
480
    public function hasData(string $key): bool
481
    {
482
        return array_key_exists($key, $this->data);
483
    }
484
485
    /**
486
     * @param string $key
487
     *
488
     * @return mixed
489
     */
490
    public function getData(string $key)
491
    {
492
        Assertion::true($this->hasData($key), sprintf('Invalid data \'%s\'', $key));
493
494
        return $this->data[$key];
495
    }
496
497
    /**
498
     * @param string $key
499
     * @param mixed  $data
500
     *
501
     * @return Authorization
502
     */
503
    public function withData(string $key, $data): Authorization
504
    {
505
        $clone = clone $this;
506
        $clone->data[$key] = $data;
507
508
        return $clone;
509
    }
510
511
    /**
512
     * @return null|ResourceServerInterface
513
     */
514
    public function getResourceServer(): ? ResourceServerInterface
515
    {
516
        return $this->resourceServer;
517
    }
518
519
    /**
520
     * @param ResourceServerInterface $resourceServer
521
     *
522
     * @return Authorization
523
     */
524
    public function withResourceServer(ResourceServerInterface $resourceServer): Authorization
525
    {
526
        $clone = clone $this;
527
        $clone->resourceServer = $resourceServer;
528
529
        return $clone;
530
    }
531
532
    /**
533
     * @return bool
534
     */
535
    public function hasOfflineAccess(): bool
536
    {
537
        // The scope offline_access is not requested
538
        if (!in_array('offline_access', $this->getScopes())) {
539
            return false;
540
        }
541
542
        // The scope offline_access is requested but prompt is not consent
543
        // The scope offline_access is ignored
544
        if (!$this->hasQueryParam('prompt') || false === mb_strpos('consent', $this->getQueryParam('prompt'), 0, '8bit')) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !(!$this->hasQuer...'prompt'), 0, '8bit'));.
Loading history...
545
            return false;
546
        }
547
548
        return true;
549
    }
550
551
    /**
552
     * @param string $option
553
     * @param mixed  $value
554
     *
555
     * @return Authorization
556
     */
557
    public function withConsentScreenOption(string $option, $value): Authorization
558
    {
559
        $clone = clone $this;
560
        $clone->consentScreenOptions[$option] = $value;
561
562
        return $clone;
563
    }
564
565
    /**
566
     * @param string $option
567
     *
568
     * @return Authorization
569
     */
570
    public function withoutConsentScreenOption(string $option): Authorization
571
    {
572
        if (!array_key_exists($option, $this->consentScreenOptions)) {
573
            return $this;
574
        }
575
576
        $clone = clone $this;
577
        unset($clone->consentScreenOptions[$option]);
578
579
        return $clone;
580
    }
581
}
582