Completed
Push — master ( 014e8e...109000 )
by Paweł
9s
created

Authenticator::authenticate()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.0416

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 10
cts 12
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 13
nc 2
nop 1
crap 3.0416
1
<?php
2
3
namespace Xsolve\SalesforceClient\Security\Authentication;
4
5
use Xsolve\SalesforceClient\Http\ClientInterface;
6
use Xsolve\SalesforceClient\Http\HttpException;
7
use Xsolve\SalesforceClient\Request\RequestInterface;
8
use Xsolve\SalesforceClient\Security\Authentication\Strategy\RegenerateStrategyInterface;
9
use Xsolve\SalesforceClient\Security\Token\Token;
10
use Xsolve\SalesforceClient\Security\Token\TokenInterface;
11
12
class Authenticator implements AuthenticatorInterface
13
{
14
    const ENDPOINT = '/services/oauth2/token';
15
16
    /**
17
     * @var ClientInterface
18
     */
19
    protected $client;
20
21
    /**
22
     * @var RegenerateStrategyInterface[]
23
     */
24
    protected $regenerateStrategies;
25
26
    /**
27
     * @param ClientInterface               $client
28
     * @param RegenerateStrategyInterface[] $regenerateStrategies
29
     */
30 5
    public function __construct(ClientInterface $client, array $regenerateStrategies = [])
31
    {
32 5
        $this->client = $client;
33 5
        $this->regenerateStrategies = $regenerateStrategies;
34 5
    }
35
36
    /**
37
     * {@inheritdoc}
38
     */
39 4
    public function authenticate(Credentials $credentials): TokenInterface
40
    {
41
        try {
42 4
            $response = $this->client->request(RequestInterface::METHOD_POST, self::ENDPOINT, [
43 4
                'form_params' => $credentials->getParameters(),
44 4
            ])->getBody();
45
        } catch (HttpException $e) {
46
            throw new Exception\AuthenticationRequestException('Authentication request failed.', 400, $e);
47
        }
48
49 4
        $parsedBody = $this->parse($response);
50
51 2
        return new Token(
52 2
            $parsedBody['token_type'],
53 2
            $parsedBody['access_token'],
54 2
            $parsedBody['instance_url'],
55 2
            isset($parsedBody['refresh_token']) ? $parsedBody['refresh_token'] : ''
56
        );
57
    }
58
59
    /**
60
     * @throws Exception\InvalidAuthenticationResponseException
61
     */
62 4
    private function parse($rawResponse): array
63
    {
64 4
        $parsedBody = json_decode($rawResponse, true);
65
66 4
        if (!$parsedBody) {
67 1
            throw new Exception\InvalidAuthenticationResponseException(
68 1
                sprintf('Cannot decode response: %s', $rawResponse)
69
            );
70
        }
71
72 3
        if (!$this->hasRequiredFields($parsedBody)) {
73 1
            throw new Exception\InvalidAuthenticationResponseException(
74 1
                'Response does not contains required fields: token_type, access_token, instance_url.'
75
            );
76
        }
77
78 2
        return $parsedBody;
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84 2
    public function regenerate(Credentials $credentials, TokenInterface $token): TokenInterface
85
    {
86 2
        foreach ($this->regenerateStrategies as $strategy) {
87 2
            if ($strategy->supports($credentials, $token)) {
88 2
                return $this->authenticate($strategy->getCredentials($credentials, $token));
89
            }
90
        }
91
92 1
        throw new Exception\UnsupportedCredentialsException('Strategy not found for given credentials and token.');
93
    }
94
95 3
    protected function hasRequiredFields(array $array): bool
96
    {
97 3
        if (!isset($array['token_type'])) {
98 1
            return false;
99
        }
100
101 2
        if (!isset($array['access_token'])) {
102
            return false;
103
        }
104
105 2
        if (!isset($array['instance_url'])) {
106
            return false;
107
        }
108
109 2
        return true;
110
    }
111
}
112