Test Failed
Push — development ( 08a77c...77a08a )
by Philippe
02:02
created

HubicService::getHost()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/*
3
 * This program is free software: you can redistribute it and/or modify
4
 * it under the terms of the GNU General Public License as published by
5
 * the Free Software Foundation, either version 3 of the License, or
6
 * (at your option) any later version.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 * GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 */
16
17
namespace Filoucrackeur\Hubic\Service;
18
19
use Filoucrackeur\Hubic\Domain\Model\Account;
20
use GuzzleHttp\RequestOptions;
21
use Psr\Http\Message\ResponseInterface;
22
use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
23
use TYPO3\CMS\Core\Http\RequestFactory;
24
use TYPO3\CMS\Core\SingletonInterface;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
27
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
28
29
class HubicService implements SingletonInterface
30
{
31
    const AUTHORIZATION_ENDPOINT = 'https://api.hubic.com/oauth/auth/';
32
33
    const TOKEN_ENDPOINT = 'https://api.hubic.com/oauth/token/';
34
35
    const DOMAIN_API = 'https://api.hubic.com/';
36
37
    const VERSION_API = '1.0';
38
39
    /**
40
     * @var RequestFactory
41
     */
42
    protected $requestFactory;
43
44
    /**
45
     * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
46
     */
47
    protected $persistenceManager;
48
49
    /**
50
     * @var \Filoucrackeur\Hubic\Domain\Model\Account
51
     */
52
    protected $account;
53
54
    /**
55
     * @param Account $account
56
     *
57
     * @return bool
58
     * @throws \RuntimeException
59
     */
60
    public function accessToken(Account $account)
61
    {
62
        $credentials = base64_encode($account->getClientId() . ':' . $account->getClientSecret());
63
        $additionalOptions = [
64
            'headers' => [
65
                'Content-Type' => 'application/x-www-form-urlencoded',
66
                'Authorization' => 'Basic ' . $credentials,
67
            ],
68
            RequestOptions::FORM_PARAMS => [
69
                'code' => GeneralUtility::_GET('code'),
70
                'redirect_uri' => $this->getHost() . '/',
71
                'grant_type' => 'authorization_code',
72
            ],
73
            RequestOptions::VERSION => '1.1',
74
        ];
75
76
        $response = $this->requestFactory->request(self::TOKEN_ENDPOINT, 'POST', $additionalOptions);
77
78
        if (200 === $response->getStatusCode()) {
79
            $content = json_decode($response->getBody()->getContents());
80
            $account->setAccessToken($content->access_token);
81
            $account->setRefreshToken($content->refresh_token);
82
            $this->persistenceManager->update($account);
83
            $this->persistenceManager->persistAll();
84
        }
85
86
        return true;
87
    }
88
89
    /**
90
     * @return string
91
     */
92
    public function getHost(): string
93
    {
94
        return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'];
95
    }
96
97
    /**
98
     * @param Account $account
99
     */
100
    public function redirectUrlRequestToken(Account $account)
101
    {
102
        $arguments = [
103
            'client_id' => $account->getClientId(),
104
            'redirect_uri' => $this->getRedirectUri($account),
105
            'scope' => $account->getScope(),
106
            'response_type' => 'code',
107
            'state' => time(),
108
        ];
109
110
        $uri = self::AUTHORIZATION_ENDPOINT . '?' . urldecode(http_build_query($arguments));
111
        header('Location: ' . $uri);
112
        die();
113
    }
114
115
    /**
116
     * @param Account $account
117
     *
118
     * @return string
119
     */
120
    private function getRedirectUri(Account $account): string
121
    {
122
        $formProtection = FormProtectionFactory::get();
123
        $formToken = $formProtection->generateToken('AuthorizationRequest');
124
125
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
126
127
        return urlencode($this->getHost() . $uriBuilder
128
                ->setCreateAbsoluteUri(true)
129
                ->setArguments([
130
                    'tx_hubic_tools_hubichubic' => [
131
                        'action' => 'callback',
132
                        'controller' => 'Backend\Account',
133
                        'account' => $account->getUid(),
134
                    ],
135
                    'formToken' => $formToken
136
                ])->buildBackendUri());
137
    }
138
139
    public function getAccount()
140
    {
141
        return $this->fetch('/account');
142
    }
143
144
    /**
145
     * @param Account $account
146
     */
147
    public function setAccount(Account $account)
148
    {
149
        $this->account = $account;
150
    }
151
152
    /**
153
     * @param string $path
154
     * @param string $method
155
     *
156
     * @return \Psr\Http\Message\ResponseInterface|string
157
     */
158
    public function fetch(string $path, $method = 'GET')
159
    {
160
161
        $additionalOptions = [
162
            'headers' => [
163
                'Content-Type' => 'application/x-www-form-urlencoded',
164
                'Authorization' => 'Bearer ' . $this->account->getAccessToken(),
165
            ],
166
            RequestOptions::VERSION => '1.1',
167
        ];
168
169
        try {
170
            $response = $this->requestFactory->request(self::DOMAIN_API . self::VERSION_API . $path, $method,
171
                $additionalOptions);
172
173
            if (200 === $response->getStatusCode()) {
174
                return json_decode($response->getBody()->getContents());
175
            }
176
        } catch (\Exception $e) {
177
            if ($this->refreshToken($this->account)) {
178
                return $this->fetch($path, $method);
179
            }
180
        }
181
        return null;
182
    }
183
184
    /**
185
     * @param Account $account
186
     * @return bool
187
     */
188
    public function refreshToken(Account $account): bool
189
    {
190
191
        $credentials = base64_encode($account->getClientId() . ':' . $account->getClientSecret());
192
        $additionalOptions = [
193
            'headers' => [
194
                'Content-Type' => 'application/x-www-form-urlencoded',
195
                'Authorization' => 'Basic ' . $credentials,
196
            ],
197
            RequestOptions::FORM_PARAMS => [
198
                'refresh_token' => $account->getRefreshToken(),
199
                'grant_type' => 'refresh_token',
200
            ],
201
            RequestOptions::VERSION => '1.1',
202
        ];
203
204
        $response = $this->requestFactory->request(self::TOKEN_ENDPOINT, 'POST', $additionalOptions);
205
206
        if (200 === $response->getStatusCode()) {
207
            $content = json_decode($response->getBody()->getContents());
208
            $account->setAccessToken($content->access_token);
209
            $this->persistenceManager->update($account);
210
            $this->persistenceManager->persistAll();
211
        }
212
213
        return true;
214
    }
215
216
    /**
217
     * Get hubiC account Quota.
218
     *
219
     * @see https://api.hubic.com/console/
220
     *
221
     * @return ResponseInterface
222
     */
223
    public function getAccountQuota()
224
    {
225
        return $this->fetch('/account/usage');
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->fetch('/account/usage'); of type Psr\Http\Message\ResponseInterface|string adds the type string to the return on line 225 which is incompatible with the return type documented by Filoucrackeur\Hubic\Serv...ervice::getAccountQuota of type Psr\Http\Message\ResponseInterface.
Loading history...
226
    }
227
228
    /**
229
     * Get hubiC agreements.
230
     *
231
     * @see https://api.hubic.com/console/
232
     *
233
     * @return ResponseInterface
234
     */
235
    public function getAgreement()
236
    {
237
        return $this->fetch('/agreement');
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->fetch('/agreement'); of type Psr\Http\Message\ResponseInterface|string adds the type string to the return on line 237 which is incompatible with the return type documented by Filoucrackeur\Hubic\Serv...icService::getAgreement of type Psr\Http\Message\ResponseInterface.
Loading history...
238
    }
239
240
    /**
241
     * Get hubiC getAllLinks.
242
     *
243
     * @see https://api.hubic.com/console/
244
     *
245
     * @return ResponseInterface
246
     */
247
    public function getAllLinks()
248
    {
249
        return $this->fetch('/account/getAllLinks');
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->fetch('/account/getAllLinks'); of type Psr\Http\Message\ResponseInterface|string adds the type string to the return on line 249 which is incompatible with the return type documented by Filoucrackeur\Hubic\Serv...bicService::getAllLinks of type Psr\Http\Message\ResponseInterface.
Loading history...
250
    }
251
252
    /**
253
     * @param RequestFactory $requestFactory
254
     */
255
    public function injectRequestFactory(RequestFactory $requestFactory): void
256
    {
257
        $this->requestFactory = $requestFactory;
258
    }
259
260
    /**
261
     * @param PersistenceManager $persistenceManager
262
     */
263
    public function injectPersistenceManager(PersistenceManager $persistenceManager): void
264
    {
265
        $this->persistenceManager = $persistenceManager;
266
    }
267
}
268