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

Credentials::toArray()   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
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
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