Completed
Push — master ( f1c499...e64319 )
by Blackred
05:35
created

ComradeReader::buildParameters()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 30
rs 8.5806
cc 4
eloc 15
nc 5
nop 3
1
<?php
2
3
namespace ComradeReader\Service;
4
5
use ComradeReader\Exception\InvalidArgumentException;
6
use ComradeReader\Exception\ResourceNotFoundException;
7
use Doctrine\Common\Cache\CacheProvider;
8
use GuzzleHttp\Client;
9
use GuzzleHttp\Exception\ClientException;
10
use Symfony\Component\Serializer\Serializer;
11
12
/**
13
 * Comrade Reader
14
 * ==============
15
 *   Makes requests to API and allows
16
 *   to decode response to objects
17
 *
18
 * Written for Wolnościowiec as a bridge
19
 * between microservices and comrades who
20
 * wants to share the anarchist events,
21
 * articles and news
22
 *
23
 * @url http://wolnosciowiec.net
24
 * @package ComradeReader\Service
25
 */
26
class ComradeReader
27
{
28
    /** @var Client $client */
29
    protected $client;
30
31
    /** @var string $url */
32
    protected $url;
33
34
    /** @var string $secretToken */
35
    protected $secretToken;
36
37
    /** @var string $tokenFieldName */
38
    protected $tokenFieldName = 'token';
39
40
    /** @var Serializer $serializer */
41
    protected $serializer;
42
43
    /** @var CacheProvider $cache */
44
    protected $cache;
45
46
    /**
47
     * @param string        $apiUrl
48
     * @param string        $apiKey
49
     * @param Serializer    $serializer
50
     * @param CacheProvider $cache
51
     */
52
    public function __construct(
53
        $apiUrl,
54
        $apiKey,
55
        Serializer $serializer,
56
        CacheProvider $cache)
57
    {
58
        $this->url        = $apiUrl;
59
        $this->secretToken     = $apiKey;
60
        $this->serializer = $serializer;
61
        $this->cache      = $cache;
62
        $this->client     = new Client([
63
            'headers' => [
64
                'Content-Type' => 'application/json'
65
            ],
66
        ]);
67
    }
68
69
    /**
70
     * @param string $tokenFieldName
71
     * @return ComradeReader
72
     */
73
    public function setTokenFieldName($tokenFieldName)
74
    {
75
        $this->tokenFieldName = $tokenFieldName;
76
        return $this;
77
    }
78
79
    /**
80
     * @return string
81
     */
82
    public function getTokenFieldName()
83
    {
84
        return $this->tokenFieldName;
85
    }
86
87
    /**
88
     * @return array
89
     */
90
    protected function getConnectionOptions()
91
    {
92
        return [
93
            'connect_timeout' => 15,
94
            'timeout'         => 15,
95
            //'debug'           => true,
96
        ];
97
    }
98
99
    /**
100
     * Make a request to the server
101
     * and return a decoded response
102
     *
103
     * @param string       $method
104
     * @param string       $url
105
     * @param array        $parameters
106
     * @param int          $cacheLifeTime
107
     *
108
     * @throws InvalidArgumentException
109
     * @throws ResourceNotFoundException
110
     *
111
     * @return ComradeDeserializer
112
     */
113
    public function request(
114
        $method,
115
        $url,
116
        $parameters = [],
117
        $cacheLifeTime = 500
118
    )
119
    {
120
        $parameters = $this->buildParameters($url, $method, $parameters);
121
122
        // read from cache (if available)
123
        if ($cacheLifeTime >= 0 && $this->cache->fetch($this->getCacheId($method, $url, $parameters))) {
124
            return new ComradeDeserializer(
125
                $this->cache->fetch($this->getCacheId($method, $url, $parameters)),
126
                $this->serializer
127
            );
128
        }
129
130
        // send a request
131
        try {
132
            $response = $this->client
133
                ->request(
134
                    $method,
135
                    $this->getPreparedRequestUrl($url),
136
                    $parameters
137
                )->getBody()->getContents();
138
139
        }
140
        catch (ClientException $e) {
141
            if ($e->getCode() === 404) {
142
                throw new ResourceNotFoundException($url);
143
            }
144
145
            throw $e;
146
        }
147
148
        // update cache with a new response from server
149
        if ($cacheLifeTime >= 0) {
150
            $this->cache->save(
151
                $this->getCacheId($method, $url, $parameters),
152
                $response,
153
                $cacheLifeTime
154
            );
155
        }
156
157
        return new ComradeDeserializer($response, $this->serializer);
158
    }
159
160
    /**
161
     * Alias to request()
162
     *
163
     * @param string $url
164
     * @param array  $parameters
165
     * @param int    $cacheLifeTime
166
     *
167
     * @throws ResourceNotFoundException
168
     * @return ComradeDeserializer
169
     */
170
    public function get(
171
        $url,
172
        $parameters = [],
173
        $cacheLifeTime = 500
174
    )
175
    {
176
        return $this->request('GET', $url, $parameters, $cacheLifeTime);
177
    }
178
179
    /**
180
     * Alias to request(), with "POST" preselected as a HTTP method
181
     *
182
     * @param string $url
183
     * @param array  $parameters
184
     * @param int    $cacheLifeTime
185
     *
186
     * @throws ResourceNotFoundException
187
     * @return ComradeDeserializer
188
     */
189
    public function post(
190
        $url,
191
        $parameters = [],
192
        $cacheLifeTime = 500
193
    )
194
    {
195
        return $this->request('POST', $url, $parameters, $cacheLifeTime);
196
    }
197
198
    /**
199
     * Alias to request(), with "PUT" preselected as a HTTP method
200
     *
201
     * @param string $url
202
     * @param array  $parameters
203
     * @param int    $cacheLifeTime
204
     *
205
     * @throws ResourceNotFoundException
206
     * @return ComradeDeserializer
207
     */
208
    public function put(
209
        $url,
210
        $parameters = [],
211
        $cacheLifeTime = 500
212
    )
213
    {
214
        return $this->request('PUT', $url, $parameters, $cacheLifeTime);
215
    }
216
217
    /**
218
     * Alias to request(), with "DELETE" preselected as a HTTP method
219
     *
220
     * @param string $url
221
     * @param array  $parameters
222
     * @param int    $cacheLifeTime
223
     *
224
     * @throws ResourceNotFoundException
225
     * @return ComradeDeserializer
226
     */
227
    public function delete(
228
        $url,
229
        $parameters = [],
230
        $cacheLifeTime = 500
231
    )
232
    {
233
        return $this->request('DELETE', $url, $parameters, $cacheLifeTime);
234
    }
235
236
    /**
237
     * @param string $path
238
     * @return string
239
     */
240
    protected function getPreparedRequestUrl($path)
241
    {
242
        return $this->url . $path;
243
    }
244
245
    /**
246
     * @param string $method
247
     * @param string $url
248
     * @param array $parameters
249
     * @return string
250
     */
251
    protected function getCacheId($method, $url, $parameters)
252
    {
253
        return md5($method . $url . json_encode($parameters));
254
    }
255
256
    /**
257
     * @param string $url
258
     * @param string $method
259
     * @param array  $parameters
260
     *
261
     * @throws \InvalidArgumentException
262
     * @return string
263
     */
264
    protected function buildParameters($url, $method, $parameters)
265
    {
266
        if (!is_array($parameters)) {
267
            throw new \InvalidArgumentException('$parameters should be of type array');
268
        }
269
270
        $query = [
271
            $this->getTokenFieldName() => $this->secretToken
272
        ];
273
274
        // merge query string from the url
275
        $extractedQueryFromUrl = parse_url($url, PHP_URL_QUERY);
276
277
        if (strlen($extractedQueryFromUrl) > 0) {
278
            parse_str($extractedQueryFromUrl, $queryArray);
279
280
            $query = array_merge($query, $queryArray);
281
        }
282
283
        if ('POST' === $method) {
284
            return array_merge($this->getConnectionOptions(), [
285
                'query'       => $query,
286
                'form_params' => $parameters,
287
            ]);
288
        }
289
290
        return array_merge($this->getConnectionOptions(), [
291
            'query' => array_merge($query, $parameters),
292
        ]);
293
    }
294
}