HubicService   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 24
c 0
b 0
f 0
lcom 2
cbo 7
dl 0
loc 302
ccs 0
cts 106
cp 0
rs 10

18 Methods

Rating   Name   Duplication   Size   Complexity  
B accessToken() 0 30 2
A getHost() 0 4 1
A redirectUrlRequestToken() 0 14 1
A getRedirectUri() 0 18 1
A getAccount() 0 4 1
A setAccount() 0 4 1
B fetch() 0 28 5
B refreshToken() 0 27 2
A delete() 0 5 1
A unlink() 0 7 1
A getAccounts() 0 4 1
A getAccountQuota() 0 4 1
A getAgreement() 0 4 1
A getAllLinks() 0 4 1
A deleteLink() 0 8 1
A injectRequestFactory() 0 4 1
A injectPersistenceManager() 0 4 1
A injectAccountRepository() 0 4 1
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 Filoucrackeur\Hubic\Domain\Repository\AccountRepository;
21
use GuzzleHttp\RequestOptions;
22
use Psr\Http\Message\ResponseInterface;
23
use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
24
use TYPO3\CMS\Core\Http\RequestFactory;
25
use TYPO3\CMS\Core\SingletonInterface;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
28
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
29
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
30
31
class HubicService implements SingletonInterface
32
{
33
    const AUTHORIZATION_ENDPOINT = 'https://api.hubic.com/oauth/auth/';
34
35
    const TOKEN_ENDPOINT = 'https://api.hubic.com/oauth/token/';
36
37
    const DOMAIN_API = 'https://api.hubic.com/';
38
39
    const VERSION_API = '1.0';
40
41
    /**
42
     * @var RequestFactory
43
     */
44
    protected $requestFactory;
45
46
    /**
47
     * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
48
     */
49
    protected $persistenceManager;
50
51
    /**
52
     * @var \Filoucrackeur\Hubic\Domain\Repository\AccountRepository
53
     */
54
    protected $accountRepository;
55
56
    /**
57
     * @var \Filoucrackeur\Hubic\Domain\Model\Account
58
     */
59
    protected $account;
60
61
    /**
62
     * @param Account $account
63
     *
64
     * @return bool
65
     * @throws \RuntimeException
66
     */
67
    public function accessToken(Account $account)
68
    {
69
        $credentials = base64_encode($account->getClientId() . ':' . $account->getClientSecret());
70
        $additionalOptions = [
71
            'headers' => [
72
                'Content-Type' => 'application/x-www-form-urlencoded',
73
                'Authorization' => 'Basic ' . $credentials,
74
            ],
75
            RequestOptions::FORM_PARAMS => [
76
                'code' => GeneralUtility::_GET('code'),
77
                'redirect_uri' => $this->getHost() . '/',
78
                'grant_type' => 'authorization_code',
79
            ],
80
            RequestOptions::VERSION => '1.1',
81
        ];
82
83
        $response = $this->requestFactory->request(self::TOKEN_ENDPOINT, 'POST', $additionalOptions);
84
85
        if (200 === $response->getStatusCode()) {
86
            $content = json_decode($response->getBody()->getContents());
87
            $account->setAccessToken($content->access_token);
88
            $account->setRefreshToken($content->refresh_token);
89
            $expireIn = new \DateTime('+ ' . $content->expires_in . ' seconds');
90
            $account->setExpirationDate($expireIn);
91
            $this->persistenceManager->update($account);
92
            $this->persistenceManager->persistAll();
93
        }
94
95
        return true;
96
    }
97
98
    /**
99
     * @return string
100
     */
101
    public function getHost(): string
102
    {
103
        return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'];
104
    }
105
106
    /**
107
     * @param Account $account
108
     */
109
    public function redirectUrlRequestToken(Account $account)
110
    {
111
        $arguments = [
112
            'client_id' => $account->getClientId(),
113
            'redirect_uri' => $this->getRedirectUri($account),
114
            'scope' => $account->getScope(),
115
            'response_type' => 'code',
116
            'state' => time(),
117
        ];
118
119
        $uri = self::AUTHORIZATION_ENDPOINT . '?' . urldecode(http_build_query($arguments));
120
        header('Location: ' . $uri);
121
        die();
122
    }
123
124
    /**
125
     * @param Account $account
126
     *
127
     * @return string
128
     */
129
    private function getRedirectUri(Account $account): string
130
    {
131
        $formProtection = FormProtectionFactory::get();
132
        $formToken = $formProtection->generateToken('AuthorizationRequest');
133
134
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
135
136
        return urlencode($this->getHost() . $uriBuilder
137
                ->setCreateAbsoluteUri(true)
138
                ->setArguments([
139
                    'tx_hubic_tools_hubichubic' => [
140
                        'action' => 'callback',
141
                        'controller' => 'Backend\Account',
142
                        'account' => $account->getUid(),
143
                    ],
144
                    'formToken' => $formToken
145
                ])->buildBackendUri());
146
    }
147
148
    public function getAccount()
149
    {
150
        return $this->fetch('/account');
151
    }
152
153
    /**
154
     * @param Account $account
155
     */
156
    public function setAccount(Account $account)
157
    {
158
        $this->account = $account;
159
    }
160
161
    /**
162
     * @param string $path
163
     * @param string $method
164
     * @param array $arguments
165
     * @return \Psr\Http\Message\ResponseInterface|string
166
     */
167
    public function fetch(string $path, $method = 'GET', array $arguments = [])
168
    {
169
        $additionalOptions = [
170
            'headers' => [
171
                'Content-Type' => 'application/x-www-form-urlencoded',
172
                'Authorization' => 'Bearer ' . $this->account->getAccessToken(),
173
            ],
174
            RequestOptions::VERSION => '1.1',
175
        ];
176
177
        if (!empty($arguments)) {
178
            $additionalOptions[RequestOptions::FORM_PARAMS] = $arguments;
179
        }
180
181
        try {
182
            $response = $this->requestFactory->request(self::DOMAIN_API . self::VERSION_API . $path, $method,
183
                $additionalOptions);
184
185
            if (200 === $response->getStatusCode()) {
186
                return json_decode($response->getBody()->getContents());
187
            }
188
        } catch (\Exception $e) {
189
            if ($this->refreshToken($this->account)) {
190
                return $this->fetch($path, $method);
191
            }
192
        }
193
        return null;
194
    }
195
196
    /**
197
     * @param Account $account
198
     * @return bool
199
     */
200
    public function refreshToken(Account $account): bool
201
    {
202
203
        $credentials = base64_encode($account->getClientId() . ':' . $account->getClientSecret());
204
        $additionalOptions = [
205
            'headers' => [
206
                'Content-Type' => 'application/x-www-form-urlencoded',
207
                'Authorization' => 'Basic ' . $credentials,
208
            ],
209
            RequestOptions::FORM_PARAMS => [
210
                'refresh_token' => $account->getRefreshToken(),
211
                'grant_type' => 'refresh_token',
212
            ],
213
            RequestOptions::VERSION => '1.1',
214
        ];
215
216
        $response = $this->requestFactory->request(self::TOKEN_ENDPOINT, 'POST', $additionalOptions);
217
218
        if (200 === $response->getStatusCode()) {
219
            $content = json_decode($response->getBody()->getContents());
220
            $account->setAccessToken($content->access_token);
221
            $this->persistenceManager->update($account);
222
            $this->persistenceManager->persistAll();
223
        }
224
225
        return true;
226
    }
227
228
    /**
229
     * @param Account $account
230
     */
231
    public function delete(Account $account): void
232
    {
233
        $this->persistenceManager->remove($account);
234
        $this->persistenceManager->persistAll();
235
    }
236
237
    /**
238
     * @param Account $account
239
     */
240
    public function unlink(Account $account): void
241
    {
242
        $account->setAccessToken('');
243
        $account->setRefreshToken('');
244
        $this->persistenceManager->update($account);
245
        $this->persistenceManager->persistAll();
246
    }
247
248
    /**
249
     * @return QueryResult|null
250
     */
251
    public function getAccounts()
252
    {
253
        return $this->accountRepository->findAll();
254
    }
255
256
    /**
257
     * Get hubiC account Quota.
258
     *
259
     * @see https://api.hubic.com/console/
260
     *
261
     * @return ResponseInterface|null
262
     */
263
    public function getAccountQuota()
264
    {
265
        return $this->fetch('/account/usage');
266
    }
267
268
    /**
269
     * Get hubiC agreements.
270
     *
271
     * @see https://api.hubic.com/console/
272
     *
273
     * @return ResponseInterface|null
274
     */
275
    public function getAgreement()
276
    {
277
        return $this->fetch('/agreement');
278
    }
279
280
    /**
281
     * Get hubiC getAllLinks.
282
     *
283
     * @see https://api.hubic.com/console/
284
     *
285
     * @return ResponseInterface|null
286
     */
287
    public function getAllLinks()
288
    {
289
        return $this->fetch('/account/getAllLinks');
290
    }
291
292
    /**
293
     * Delete hubiC link.
294
     *
295
     * @see https://api.hubic.com/console/
296
     *
297
     * @param string $uri
298
     * @return ResponseInterface|null
299
     */
300
    public function deleteLink(string $uri)
301
    {
302
        $arguments = [
303
            'uri' => $uri
304
        ];
305
306
        return $this->fetch('/account/link', 'DELETE', $arguments);
307
    }
308
309
    /**
310
     * @param RequestFactory $requestFactory
311
     */
312
    public function injectRequestFactory(RequestFactory $requestFactory): void
313
    {
314
        $this->requestFactory = $requestFactory;
315
    }
316
317
    /**
318
     * @param PersistenceManager $persistenceManager
319
     */
320
    public function injectPersistenceManager(PersistenceManager $persistenceManager): void
321
    {
322
        $this->persistenceManager = $persistenceManager;
323
    }
324
325
    /**
326
     * @param AccountRepository $accountRepository
327
     */
328
    public function injectAccountRepository(AccountRepository $accountRepository): void
329
    {
330
        $this->accountRepository = $accountRepository;
331
    }
332
}
333