Completed
Push — master ( f06e9e...7ae67f )
by
unknown
9s
created

AbstractCoreApiClient::getCacheItemPool()   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
namespace MovingImage\Client\VMPro\ApiClient;
4
5
use Cache\Adapter\Void\VoidCachePool;
6
use GuzzleHttp\ClientInterface;
7
use JMS\Serializer\Serializer;
8
use MovingImage\Client\VMPro\Exception;
9
use MovingImage\Client\VMPro\Util\Logging\Traits\LoggerAwareTrait;
10
use Psr\Cache\CacheItemPoolInterface;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Log\LoggerAwareInterface;
13
14
/**
15
 * Class AbstractCoreApiClient.
16
 *
17
 * @author Ruben Knol <[email protected]>
18
 */
19
abstract class AbstractCoreApiClient implements LoggerAwareInterface
20
{
21
    use LoggerAwareTrait;
22
23
    /**
24
     * @const string
25
     */
26
    const OPT_VIDEO_MANAGER_ID = 'videoManagerId';
27
28
    /**
29
     * @var ClientInterface The Guzzle HTTP client
30
     */
31
    protected $httpClient;
32
33
    /**
34
     * @var Serializer The JMS Serializer instance
35
     */
36
    protected $serializer;
37
38
    /**
39
     * @var CacheItemPoolInterface PSR6 cache pool implementation
40
     */
41
    protected $cacheItemPool;
42
43
    /**
44
     * @var mixed time-to-live for cached responses
45
     *            The type of this property might be integer, \DateInterval or null
46
     *
47
     * @see CacheItemInterface::expiresAfter()
48
     */
49
    protected $cacheTtl;
50
51
    /**
52
     * ApiClient constructor.
53
     *
54
     * @param ClientInterface        $httpClient
55
     * @param Serializer             $serializer
56
     * @param CacheItemPoolInterface $cacheItemPool
57
     * @param int                    $cacheTtl
58
     */
59
    public function __construct(
60
        ClientInterface $httpClient,
61
        Serializer $serializer,
62
        CacheItemPoolInterface $cacheItemPool = null,
63
        $cacheTtl = null
64
    ) {
65
        $this->httpClient = $httpClient;
66
        $this->serializer = $serializer;
67
        $this->cacheItemPool = $cacheItemPool ?: new VoidCachePool();
68
        $this->cacheTtl = $cacheTtl;
69
    }
70
71
    /**
72
     * @param CacheItemPoolInterface $cacheItemPool
73
     */
74
    public function setCacheItemPool(CacheItemPoolInterface $cacheItemPool)
75
    {
76
        $this->cacheItemPool = $cacheItemPool;
77
    }
78
79
    /**
80
     * @return CacheItemPoolInterface
81
     */
82
    public function getCacheItemPool()
83
    {
84
        return $this->cacheItemPool;
85
    }
86
87
    /**
88
     * Perform the actual request in the implementation classes.
89
     *
90
     * @param string $method
91
     * @param string $uri
92
     * @param array  $options
93
     *
94
     * @return mixed
95
     */
96
    abstract protected function _doRequest($method, $uri, $options);
97
98
    /**
99
     * Make a request to the API and serialize the result according to our
100
     * serialization strategy.
101
     *
102
     * @param string $method
103
     * @param string $uri
104
     * @param array  $options
105
     *
106
     * @return object|ResponseInterface
107
     */
108
    protected function makeRequest($method, $uri, $options)
109
    {
110
        $logger = $this->getLogger();
111
112
        try {
113
            // Automagically pre-pend videoManagerId if the option is present in the
114
            // options for sending the request
115
            if (isset($options[self::OPT_VIDEO_MANAGER_ID])) {
116
                $uri = sprintf('%d/%s', $options[self::OPT_VIDEO_MANAGER_ID], $uri);
117
            }
118
119
            $cacheKey = $this->generateCacheKey($method, $uri, $options);
120
            $cacheItem = $this->cacheItemPool->getItem($cacheKey);
121
            if ($cacheItem->isHit()) {
122
                $logger->info(sprintf('Getting response from cache for %s request to %s', $method, $uri), [$uri]);
123
124
                return $this->unserializeResponse($cacheItem->get());
125
            }
126
127
            $logger->info(sprintf('Making API %s request to %s', $method, $uri), [$uri]);
128
129
            /** @var ResponseInterface $response */
130
            $response = $this->_doRequest($method, $uri, $options);
131
132
            if ($this->isCachable($method, $uri, $options, $response)) {
133
                $cacheItem->set($this->serializeResponse($response));
134
                $cacheItem->expiresAfter($this->cacheTtl);
135
                $this->cacheItemPool->save($cacheItem);
136
            }
137
138
            $logger->debug('Response from HTTP call was status code:', [$response->getStatusCode()]);
139
            $logger->debug('Response JSON was:', [$response->getBody()]);
140
141
            return $response;
142
        } catch (\Exception $e) {
143
            throw $e; // Just rethrow for now
144
        }
145
    }
146
147
    /**
148
     * Deserialize a response into an instance of it's associated class.
149
     *
150
     * @param string $data
151
     * @param string $serialisationClass
152
     *
153
     * @return object
154
     */
155
    protected function deserialize($data, $serialisationClass)
156
    {
157
        return $this->serializer->deserialize($data, $serialisationClass, 'json');
158
    }
159
160
    /**
161
     * Helper method to build the JSON data array for making a request
162
     * with ::makeRequest(). Optional parameters with empty or null value will be
163
     * omitted from the return value.
164
     *
165
     * Examples:
166
     *
167
     * $this->buildJsonParameters(['title' => 'test'], ['description' => '', 'bla' => 'test'])
168
     *
169
     * Would result in:
170
     *
171
     * [
172
     *     'title' => 'test',
173
     *     'bla' => 'test',
174
     * ]
175
     *
176
     * @param array $required
177
     * @param array $optional
178
     *
179
     * @return array
180
     */
181
    protected function buildJsonParameters(array $required, array $optional)
182
    {
183
        foreach ($required as $key => $value) {
184
            if (empty($value)) {
185
                throw new Exception(sprintf('Required parameter \'%s\' is missing..', $key));
186
            }
187
        }
188
189
        $json = $required;
190
191
        foreach ($optional as $key => $value) {
192
            if (!empty($value) || $value === false) {
193
                $json[$key] = $value;
194
            }
195
        }
196
197
        return $json;
198
    }
199
200
    /**
201
     * Generates the cache key based on the class name, request method, uri and options.
202
     *
203
     * @param string $method
204
     * @param string $uri
205
     * @param array  $options
206
     *
207
     * @return string
208
     */
209
    private function generateCacheKey($method, $uri, array $options = [])
210
    {
211
        return sha1(sprintf('%s.%s.%s.%s', get_class($this), $method, $uri, json_encode($options)));
212
    }
213
214
    /**
215
     * Checks if the request may be cached.
216
     *
217
     * @param string $method
218
     * @param string $uri
219
     * @param array  $options
220
     * @param mixed  $response
221
     *
222
     * @return bool
223
     */
224
    private function isCachable($method, $uri, array $options, $response)
0 ignored issues
show
Unused Code introduced by
The parameter $uri is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
225
    {
226
        /** @var ResponseInterface $statusCode */
227
        $statusCode = $response->getStatusCode();
228
229
        return $method === 'GET' && $statusCode >= 200 && $statusCode < 300;
230
    }
231
232
    /**
233
     * Serializes the provided response to a string, suitable for caching.
234
     * The type of the $response argument varies depending on the guzzle version.
235
     *
236
     * @param mixed $response
237
     *
238
     * @return string
239
     */
240
    abstract protected function serializeResponse($response);
241
242
    /**
243
     * Unserializes the serialized response into a response object.
244
     * The return type varies depending on the guzzle version.
245
     *
246
     * @param string $serialized
247
     *
248
     * @return mixed
249
     *
250
     * @throws Exception
251
     */
252
    abstract protected function unserializeResponse($serialized);
253
}
254