1<?php
2/**
3 * ParrotFlowerPower service.
4 *
5 * @author  Pedro Amorim <contact@pamorim.fr>
6 * @license http://www.opensource.org/licenses/mit-license.html MIT License
7 * @link    https://flowerpowerdev.parrot.com/projects/flower-power-web-service-api/wiki
8 */
9
10namespace OAuth\OAuth2\Service;
11
12use OAuth\OAuth2\Token\StdOAuth2Token;
13use OAuth\Common\Http\Exception\TokenResponseException;
14use OAuth\Common\Http\Uri\Uri;
15use OAuth\Common\Consumer\CredentialsInterface;
16use OAuth\Common\Http\Client\ClientInterface;
17use OAuth\Common\Storage\TokenStorageInterface;
18use OAuth\Common\Http\Uri\UriInterface;
19use OAuth\OAuth2\Service\Exception\MissingRefreshTokenException;
20use OAuth\Common\Token\TokenInterface;
21
22/**
23 * ParrotFlowerPower service.
24 *
25 * @author  Pedro Amorim <contact@pamorim.fr>
26 * @license http://www.opensource.org/licenses/mit-license.html MIT License
27 * @link    https://flowerpowerdev.parrot.com/projects/flower-power-web-service-api/wiki
28 */
29class ParrotFlowerPower extends AbstractService
30{
31
32    public function __construct(
33        CredentialsInterface $credentials,
34        ClientInterface $httpClient,
35        TokenStorageInterface $storage,
36        $scopes = array(),
37        UriInterface $baseApiUri = null
38    ) {
39        parent::__construct(
40            $credentials,
41            $httpClient,
42            $storage,
43            $scopes,
44            $baseApiUri,
45            true
46        );
47
48        if (null === $baseApiUri) {
49            $this->baseApiUri = new Uri('https://apiflowerpower.parrot.com/');
50        }
51    }
52
53    /**
54     * {@inheritdoc}
55     */
56    public function getAuthorizationEndpoint()
57    {
58        return new Uri($this->baseApiUri.'oauth2/v1/authorize');
59
60    }
61
62    /**
63     * {@inheritdoc}
64     */
65    public function getAccessTokenEndpoint()
66    {
67        return new Uri($this->baseApiUri.'user/v1/authenticate');
68    }
69
70    /**
71     * {@inheritdoc}
72     */
73    protected function getAuthorizationMethod()
74    {
75        return static::AUTHORIZATION_METHOD_HEADER_BEARER;
76    }
77
78    /**
79     * {@inheritdoc}
80     */
81    protected function parseAccessTokenResponse($responseBody)
82    {
83        $data = json_decode($responseBody, true);
84
85        if (null === $data || !is_array($data)) {
86            throw new TokenResponseException('Unable to parse response.');
87        } elseif (isset($data['error'])) {
88            throw new TokenResponseException(
89                'Error in retrieving token: "' . $data['error'] . '"'
90            );
91        }
92
93        $token = new StdOAuth2Token();
94        $token->setAccessToken($data['access_token']);
95        $token->setLifetime($data['expires_in']);
96
97        if (isset($data['refresh_token'])) {
98            $token->setRefreshToken($data['refresh_token']);
99            unset($data['refresh_token']);
100        }
101
102        unset($data['access_token']);
103        unset($data['expires_in']);
104
105        $token->setExtraParams($data);
106
107        return $token;
108    }
109
110
111    /**
112     * Parrot use a different endpoint for refresh a token
113     *
114     * {@inheritdoc}
115     */
116    public function refreshAccessToken(TokenInterface $token)
117    {
118        $refreshToken = $token->getRefreshToken();
119
120        if (empty($refreshToken)) {
121            throw new MissingRefreshTokenException();
122        }
123
124        $parameters = array(
125            'grant_type'    => 'refresh_token',
126            'type'          => 'web_server',
127            'client_id'     => $this->credentials->getConsumerId(),
128            'client_secret' => $this->credentials->getConsumerSecret(),
129            'refresh_token' => $refreshToken,
130        );
131
132        $responseBody = $this->httpClient->retrieveResponse(
133            new Uri($this->baseApiUri.'user/v1/refresh'),
134            $parameters,
135            $this->getExtraOAuthHeaders()
136        );
137        $token = $this->parseAccessTokenResponse($responseBody);
138        $this->storage->storeAccessToken($this->service(), $token);
139
140        return $token;
141    }
142}
143