Test Failed
Push — main ( 4ed0c7...a27a58 )
by Peter
03:57
created

Credentials::addAuthToRequest()   B

Complexity

Conditions 11
Paths 7

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 14.6926

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 14
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 25
ccs 11
cts 16
cp 0.6875
crap 14.6926
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Pelmered\LaravelHttpOAuthHelper;
4
5
use Closure;
6
use Illuminate\Http\Client\PendingRequest;
7
use Illuminate\Support\Facades\Validator;
8
use Illuminate\Validation\Rule;
9
use InvalidArgumentException;
10
11
class Credentials
12
{
13
    public const AUTH_TYPE_BODY = 'body';
14
15
    public const AUTH_TYPE_QUERY = 'query';
16
17
    public const AUTH_TYPE_BASIC = 'basic';
18
19
    public const AUTH_TYPE_BEARER = 'Bearer';
20
21
    public const AUTH_TYPE_CUSTOM = 'custom';
22
23
    public const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials';
24
25
    public const GRANT_TYPE_PASSWORD_CREDENTIALS = 'password_credentials';
26
27
    //TODO: Add support for authorization_code and implicit grants
28
    public const GRANT_TYPE_AUTHORIZATION_CODE = 'authorization_code';
29
30
    public const GRANT_TYPE_IMPLICIT = 'implicit';
31
32
    private ?Closure $customCallback;
33
34
    /**
35
     * @param  array<string, mixed>  $credentials
36 12
     */
37
    public function __construct(
38
        string|array|callable $credentials = [],
39
        protected ?string $token = null,
40
        protected ?string $clientId = null,
41
        protected ?string $clientSecret = null,
42
        protected string $authType = self::AUTH_TYPE_BASIC, //TODO: Which auth type should be default?
43
        protected string $tokenName = 'token'
44 12
    ) {
45 9
        if (! empty($credentials)) {
46
            $this->parseCredentialsArray($credentials);
47
        }
48
49 12
        $this->validate();
50
    }
51
52
    public function toArray(): array
53
    {
54
        return get_object_vars($this);
55
    }
56
57
    protected function validate(): void
58
    {
59
        Validator::make($this->toArray(), [
60
            'authType' => Rule::in([self::AUTH_TYPE_BEARER, self::AUTH_TYPE_BODY, self::AUTH_TYPE_QUERY, self::AUTH_TYPE_BASIC, self::AUTH_TYPE_CUSTOM]),
61
        ])->validate();
62
    }
63
64
    /**
65
     * @param  string|array<string, mixed>|callable  $credentials
66
     */
67 9
    public function parseCredentialsArray(string|array|callable $credentials): void
68
    {
69 9
        if (is_string($credentials)) {
0 ignored issues
show
introduced by
The condition is_string($credentials) is always false.
Loading history...
70 1
            $this->setRefreshToken($credentials);
71
72 1
            return;
73
        }
74
75 8
        if (is_callable($credentials)) {
76 1
            $this->authType       = self::AUTH_TYPE_CUSTOM;
77 1
            $this->customCallback = $credentials(...);
78
79 1
            return;
80
        }
81
82 7
        $credentials = array_filter($credentials);
83 7
        $arrayLength = count($credentials);
84
85 7
        if ($arrayLength > 0 && array_is_list($credentials)) {
0 ignored issues
show
Bug introduced by
The function array_is_list was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

85
        if ($arrayLength > 0 && /** @scrutinizer ignore-call */ array_is_list($credentials)) {
Loading history...
86 7
            match ($arrayLength) {
87 1
                1 => $this->setRefreshToken($credentials[0]),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setRefreshToken($credentials[0]) targeting Pelmered\LaravelHttpOAut...ials::setRefreshToken() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
88 6
                2, 3 => $this->setClientCredentialsPair($credentials[0], $credentials[1], $credentials[2] ?? $this->authType),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setClientCredenti...[2] ?? $this->authType) targeting Pelmered\LaravelHttpOAut...ClientCredentialsPair() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
89
                default => throw new InvalidArgumentException('Invalid credentials. Check documentation/readme. '),
90 7
            };
91
92 7
            return;
93
        }
94
95
        if (isset($credentials['client_id'], $credentials['client_secret'])) {
96
            $this->setClientCredentialsPair($credentials['client_id'], $credentials['client_secret'], $credentials['auth_type'] ?? 'basic');
97
        }
98
99
        if (isset($credentials['refresh_token'])) {
100
            $this->setRefreshToken($credentials['refresh_token']);
101
        }
102
    }
103
104 12
    public function addAuthToRequest(PendingRequest $httpClient): PendingRequest
105
    {
106 12
        if ($this->authType === self::AUTH_TYPE_BODY) {
107 3
            return $httpClient;
108
        }
109 9
        if ($this->authType === self::AUTH_TYPE_BEARER && $this->token) {
110 2
            return $httpClient->withToken($this->token);
111
        }
112 7
        if ($this->authType === self::AUTH_TYPE_BASIC) {
113 6
            if (! $this->clientId || ! $this->clientSecret) {
114
                throw new InvalidArgumentException('Basic auth requires client id and client secret. Check documentation/readme. ');
115
            }
116
117 6
            return $httpClient->withBasicAuth($this->clientId, $this->clientSecret);
118
        }
119 1
        if ($this->authType === self::AUTH_TYPE_QUERY && $this->token) {
120
            return $httpClient->withQueryParameters([
121
                $this->tokenName => $this->token,
122
            ]);
123
        }
124 1
        if ($this->authType === self::AUTH_TYPE_CUSTOM && is_callable($this->customCallback)) {
125 1
            return ($this->customCallback)($httpClient);
126
        }
127
128
        return $httpClient;
129
    }
130
131
    /**
132
     * @param  array<string, string>  $requestBody
133
     * @return array<string, string>
134
     */
135 12
    public function addAuthToBody(array $requestBody): array
136
    {
137 12
        if ($this->authType !== self::AUTH_TYPE_BODY) {
138 9
            return $requestBody;
139
        }
140 3
        if ($this->clientId && $this->clientSecret) {
141 2
            return $requestBody + ['client_id' => $this->clientId, 'client_secret' => $this->clientSecret];
142
        }
143 1
        if ($this->token) {
144 1
            return $requestBody + [$this->tokenName => $this->token];
145
        }
146
147
        throw new InvalidArgumentException('Invalid credentials. Check documentation/readme.');
148
    }
149
150 2
    public function setRefreshToken(string $token): void
151
    {
152 2
        $this->token = $token;
153 2
        if (empty($this->authType)) {
154 1
            $this->authType = self::AUTH_TYPE_BEARER;
155
        }
156
    }
157
158 6
    public function setClientCredentialsPair(string $clientId, string $clientSecret, ?string $tokenType = null): void
159
    {
160 6
        $this->clientId     = $clientId;
161 6
        $this->clientSecret = $clientSecret;
162
163 6
        if ($tokenType) {
164 2
            $this->authType = $tokenType;
165
        }
166
167 6
        if (empty($this->authType)) {
168 4
            $this->authType = self::AUTH_TYPE_BASIC;
169
        }
170
    }
171
}
172