Completed
Pull Request — master (#68)
by
unknown
06:34
created

Authenticator::getRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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