Passed
Push — master ( 15a67e...e91196 )
by Ludwig
01:59
created

Client   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 255
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 87
dl 0
loc 255
rs 9.76
c 0
b 0
f 0
wmc 33

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getApiUri() 0 3 1
A setApiUri() 0 5 1
A __construct() 0 8 1
C call() 0 45 16
A getTokenUrl() 0 3 1
A denormalizeObject() 0 15 3
A setTokenUrl() 0 5 1
A setApiUrl() 0 5 1
A authenticatePassword() 0 17 1
A refreshToken() 0 17 1
A getApiVersion() 0 3 1
A getClient() 0 3 1
A getApiUrl() 0 3 1
A setToken() 0 5 1
A getSerializer() 0 3 1
A setApiVersion() 0 5 1
1
<?php
2
3
/*
4
 * This file is part of datamolino client.
5
 *
6
 * (c) 2018 cwd.at GmbH <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cwd\Datamolino;
15
16
use Cwd\Datamolino\Model\Token;
17
use GuzzleHttp\Psr7\Request;
18
use Http\Client\HttpClient;
19
use Http\Discovery\HttpClientDiscovery;
20
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
21
use Symfony\Component\Serializer\Encoder\JsonEncoder;
22
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
23
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
24
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
25
use Symfony\Component\Serializer\Serializer;
26
27
class Client
28
{
29
    private $apiUrl = 'https://beta.datamolino.com';
30
    private $apiVersion = 'v1_2';
31
    private $apiUri;
32
    private $tokenUrl;
33
    /** @var Token */
34
    private $token;
35
36
    /** @var HttpClient */
37
    private $client;
38
39
    /** @var Serializer */
40
    private $serializer;
41
42
    public function __construct()
43
    {
44
        $this->client = HttpClientDiscovery::find();
45
        $this->apiUri = sprintf('%s/api/%s/', $this->apiUrl, $this->apiVersion);
46
        $this->tokenUrl = $this->apiUrl.'/oauth/token';
47
48
        $normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter(), null, new ReflectionExtractor());
49
        $this->serializer = new Serializer([new DateTimeNormalizer(), $normalizer], ['json' => new JsonEncoder()]);
50
    }
51
52
    /**
53
     * @param string|null     $payload
54
     * @param int|string|null $id
55
     * @param string          $endpoint
56
     * @param string|null     $hydrationClass
57
     * @param bool            $isList
58
     * @param string          $method
59
     * @param string|null     $urlExtension   - Special case only needed when retrieving original file!
60
     *
61
     * @return mixed
62
     *
63
     * @throws \Http\Client\Exception
64
     */
65
    public function call($payload = null, $id = null, $endpoint = '', $hydrationClass = null, $isList = false, $method = 'POST', $urlExtension = null)
66
    {
67
        if (!$this->token instanceof Token) {
68
            throw new \Exception('Token not set - Authenticate first - or store refresh token for later use');
69
        }
70
71
        if (in_array($method, ['GET', 'PUT', 'DELETE'])) {
72
            $format = (is_int($id)) ? '%s%s/%s' : '%s%s%s';
73
            $uri = sprintf($format, $this->apiUri, $endpoint, $id);
74
        } else {
75
            $uri = (null !== $id) ? sprintf('%s%s/%s', $this->apiUri, $endpoint, $id) : $this->apiUri.$endpoint;
76
        }
77
78
        /* Special case only needed for retrieve original file */
79
        if (null !== $urlExtension) {
80
            $uri .= $urlExtension;
81
        }
82
83
        $request = new Request($method, $uri, [
84
            'Authorization' => sprintf('Bearer %s', $this->token->getAccessToken()),
85
            'Content-Type' => 'application/json',
86
        ], $payload);
87
88
        $response = $this->client->sendRequest($request);
89
        $responseBody = $response->getBody()->getContents();
90
        $responseData = json_decode($responseBody);
91
92
        if ('dev' === getenv('APP_ENV')) {
93
            dump([$request, $responseData]);
0 ignored issues
show
Bug introduced by
The function dump was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
            /** @scrutinizer ignore-call */ 
94
            dump([$request, $responseData]);
Loading history...
94
        }
95
96
        if ($response->getStatusCode() > 299) {
97
            $message = isset($responseData->message) ? $responseData->message : 'Unknown';
98
            throw new \Exception(sprintf('Error on request %s: %s', $response->getStatusCode(), $message));
99
        }
100
101
        if (null !== $hydrationClass && class_exists($hydrationClass) && isset($responseData->$endpoint)) {
102
            return $this->denormalizeObject($hydrationClass, $responseData->$endpoint, $isList);
103
        } elseif (null !== $hydrationClass && !class_exists($hydrationClass)) {
104
            throw new \Exception(sprintf('HydrationClass (%s) does not exist', $hydrationClass));
105
        } elseif (null !== $hydrationClass && !isset($responseData->$endpoint)) {
106
            throw new \Exception(sprintf('Datapoint (%s) does not exist', $endpoint));
107
        }
108
109
        return $responseData;
110
    }
111
112
    /**
113
     * @param string $clientId
114
     * @param string $clientSecret
115
     * @param string $username
116
     * @param string $password
117
     *
118
     * @throws \Http\Client\Exception
119
     * @ToDo Handle Token storage
120
     */
121
    public function authenticatePassword($clientId, $clientSecret, $username, $password): Token
122
    {
123
        $request = new Request('POST', $this->tokenUrl, [
124
            'Content-Type' => 'application/json',
125
        ], json_encode([
126
            'client_id' => $clientId,
127
            'client_secret' => $clientSecret,
128
            'username' => $username,
129
            'password' => $password,
130
            'grant_type' => 'password',
131
        ]));
132
133
        $response = $this->getClient()->sendRequest($request);
134
        $responseBody = $response->getBody()->getContents();
135
        $this->token = $this->denormalizeObject(Token::class, [json_decode($responseBody)], false);
136
137
        return $this->token;
138
    }
139
140
    /**
141
     * @param string $clientId
142
     * @param string $clientSecret
143
     * @param string $refreshToken
144
     *
145
     * @throws \Http\Client\Exception
146
     * @ToDo Handle Token storage
147
     */
148
    public function refreshToken($clientId, $clientSecret, $refreshToken): Token
149
    {
150
        $request = new Request('POST', $this->tokenUrl, [
151
            'Content-Type' => 'application/json',
152
        ], json_encode([
153
            'client_id' => $clientId,
154
            'client_secret' => $clientSecret,
155
            'refresh_token' => $refreshToken,
156
            'grant_type' => 'refresh_token',
157
        ]));
158
159
        $response = $this->getClient()->sendRequest($request);
160
        $responseBody = $response->getBody()->getContents();
161
162
        $this->token = $this->denormalizeObject(Token::class, [json_decode($responseBody)], false);
163
164
        return $this->token;
165
    }
166
167
    public function setToken(Token $token): Client
168
    {
169
        $this->token = $token;
170
171
        return $this;
172
    }
173
174
    /**
175
     * @return string
176
     */
177
    public function getApiUrl(): string
178
    {
179
        return $this->apiUrl;
180
    }
181
182
    /**
183
     * @param string $apiUrl
184
     *
185
     * @return Client
186
     */
187
    public function setApiUrl(string $apiUrl): Client
188
    {
189
        $this->apiUrl = $apiUrl;
190
191
        return $this;
192
    }
193
194
    /**
195
     * @return string
196
     */
197
    public function getApiVersion(): string
198
    {
199
        return $this->apiVersion;
200
    }
201
202
    /**
203
     * @param string $apiVersion
204
     *
205
     * @return Client
206
     */
207
    public function setApiVersion(string $apiVersion): Client
208
    {
209
        $this->apiVersion = $apiVersion;
210
211
        return $this;
212
    }
213
214
    /**
215
     * @return string
216
     */
217
    public function getApiUri(): string
218
    {
219
        return $this->apiUri;
220
    }
221
222
    /**
223
     * @param string $apiUri
224
     *
225
     * @return Client
226
     */
227
    public function setApiUri(string $apiUri): Client
228
    {
229
        $this->apiUri = $apiUri;
230
231
        return $this;
232
    }
233
234
    /**
235
     * @return string
236
     */
237
    public function getTokenUrl(): string
238
    {
239
        return $this->tokenUrl;
240
    }
241
242
    /**
243
     * @param string $tokenUrl
244
     *
245
     * @return Client
246
     */
247
    public function setTokenUrl(string $tokenUrl): Client
248
    {
249
        $this->tokenUrl = $tokenUrl;
250
251
        return $this;
252
    }
253
254
    public function denormalizeObject($hydrationClass, $dataObject, $isList = false)
255
    {
256
        $result = [];
257
258
        foreach ($dataObject as $data) {
259
            $result[] = $this->serializer->denormalize($data, $hydrationClass, null, [
260
                ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true,
261
            ]);
262
        }
263
264
        if ($isList) {
265
            return $result;
266
        }
267
268
        return current($result);
269
    }
270
271
    protected function getClient(): HttpClient
272
    {
273
        return $this->client;
274
    }
275
276
    /**
277
     * @return Serializer
278
     */
279
    public function getSerializer(): Serializer
280
    {
281
        return $this->serializer;
282
    }
283
}
284