Authenticator::authenticate()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 15
c 0
b 0
f 0
ccs 8
cts 10
cp 0.8
rs 9.9332
cc 3
nc 2
nop 1
crap 3.072
1
<?php
2
3
namespace Xsolve\SalesforceClient\Security\Authentication;
4
5
use GuzzleHttp\Psr7\Request;
6
use Http\Client\Exception\HttpException;
7
use Http\Client\HttpClient;
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 HttpClient
18
     */
19
    protected $client;
20
21
    /**
22
     * @var RegenerateStrategyInterface[]
23
     */
24
    protected $regenerateStrategies;
25
26
    /**
27
     * @param HttpClient                    $client
28
     * @param RegenerateStrategyInterface[] $regenerateStrategies
29
     */
30 5
    public function __construct(HttpClient $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->sendRequest($this->getRequest($credentials))->getBody();
43
        } catch (HttpException $e) {
44
            throw new Exception\AuthenticationRequestException('Authentication request failed.', 400, $e);
45
        }
46
47 4
        $parsedBody = $this->parse($response);
48
49 2
        return new Token(
50 2
            $parsedBody['token_type'],
51 2
            $parsedBody['access_token'],
52 2
            $parsedBody['instance_url'],
53 2
            isset($parsedBody['refresh_token']) ? $parsedBody['refresh_token'] : ''
54
        );
55
    }
56
57
    /**
58
     * @throws Exception\InvalidAuthenticationResponseException
59
     */
60 4
    private function parse($rawResponse): array
61
    {
62 4
        $parsedBody = json_decode($rawResponse, true);
63
64 4
        if (!$parsedBody) {
65 1
            throw new Exception\InvalidAuthenticationResponseException(
66 1
                sprintf('Cannot decode response: %s', $rawResponse)
67
            );
68
        }
69
70 3
        if (!$this->hasRequiredFields($parsedBody)) {
71 1
            throw new Exception\InvalidAuthenticationResponseException(
72 1
                'Response does not contains required fields: token_type, access_token, instance_url.'
73
            );
74
        }
75
76 2
        return $parsedBody;
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82 2
    public function regenerate(Credentials $credentials, TokenInterface $token): TokenInterface
83
    {
84 2
        foreach ($this->regenerateStrategies as $strategy) {
85 2
            if ($strategy->supports($credentials, $token)) {
86 2
                return $this->authenticate($strategy->getCredentials($credentials, $token));
87
            }
88
        }
89
90 1
        throw new Exception\UnsupportedCredentialsException('Strategy not found for given credentials and token.');
91
    }
92
93 3
    protected function hasRequiredFields(array $array): bool
94
    {
95 3
        if (!isset($array['token_type'])) {
96 1
            return false;
97
        }
98
99 2
        if (!isset($array['access_token'])) {
100
            return false;
101
        }
102
103 2
        if (!isset($array['instance_url'])) {
104
            return false;
105
        }
106
107 2
        return true;
108
    }
109
110 4
    protected function getRequest(Credentials $credentials): Request
111
    {
112 4
        return new Request(
113 4
            \Xsolve\SalesforceClient\Enum\RequestMethod::POST()->value(),
114 4
            self::ENDPOINT,
115 4
            ['Content-type' => \Xsolve\SalesforceClient\Enum\ContentType::FORM()->value()],
116 4
            http_build_query($credentials->getParameters())
117
        );
118
    }
119
}
120