Completed
Push — master ( ea3b27...7da27d )
by Valentyn
03:13
created

TmdbSearchService::findActorsByMovieId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 5
cp 0
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Movies\Service;
6
7
use App\Movies\Exception\TmdbMovieNotFoundException;
8
use App\Movies\Exception\TmdbRequestLimitException;
9
use GuzzleHttp\ClientInterface;
10
use GuzzleHttp\Exception\GuzzleException;
11
use Psr\Log\LoggerInterface;
12
use Psr\SimpleCache\CacheInterface;
13
14
// todo refactor cache usage
15
class TmdbSearchService
16
{
17
    private $apiKey;
18
    private $client;
19
    private $logger;
20
    private $cache;
21
    private const ApiUrl = 'https://api.themoviedb.org/3';
22
23 9
    public function __construct(LoggerInterface $logger, ClientInterface $client, CacheInterface $cache)
24
    {
25 9
        $this->apiKey = \getenv('MOVIE_DB_API_KEY'); // is it ok to use \getenv() here?
26 9
        $this->client = $client;
27 9
        $this->logger = $logger;
28 9
        $this->cache = $cache;
29 9
    }
30
31
    /**
32
     * @param string $query
33
     * @param string $locale
34
     * @param array  $data
35
     *
36
     * @throws TmdbMovieNotFoundException
37
     * @throws TmdbRequestLimitException
38
     *
39
     * @return array
40
     */
41 1
    public function findMoviesByQuery(string $query, string $locale = 'en', $data = []): array
42
    {
43 1
        $data = array_merge([
44 1
            'api_key' => $this->apiKey,
45 1
            'language' => $locale,
46 1
            'query' => $query,
47 1
        ], $data);
48
49 1
        $movies = $this->request('/search/movie', 'GET', [
50 1
            'query' => $data,
51
        ]);
52
53 1
        return $movies;
54
    }
55
56
    /**
57
     * @param int $tmdb_id
58
     * @param string $locale
59
     * @return array
60
     * @throws TmdbMovieNotFoundException
61
     * @throws TmdbRequestLimitException
62
     * @throws \Psr\SimpleCache\InvalidArgumentException
63
     */
64 1
    public function findMovieById(int $tmdb_id, string $locale = 'en'): array
65
    {
66 1
        $movie = $this->request("/movie/{$tmdb_id}", 'GET', [
67
            'query' => [
68 1
                'api_key' => $this->apiKey,
69 1
                'language' => $locale,
70 1
                'append_to_response' => 'similar,translations,credits',
71
            ],
72
        ]);
73
74 1
        $similarUrl = "/movie/{$tmdb_id}/similar";
75 1
        $params = ['api_key' => $this->apiKey, 'page' => 1];
76 1
        $this->cache->set($this->getCacheKeyFromParams($similarUrl, 'GET', ['query' => $params]), json_encode($movie['similar']), 1800);
77
78 1
        $translationsUrl = "/movie/{$tmdb_id}/translations";
79 1
        $params = ['api_key' => $this->apiKey];
80 1
        $this->cache->set($this->getCacheKeyFromParams($translationsUrl, 'GET', ['query' => $params]), json_encode($movie['translations']), 1800);
81
82 1
        $creditsUrl = "/movie/{$tmdb_id}/credits";
83 1
        $params = ['api_key' => $this->apiKey, 'language' => $locale];
84 1
        $this->cache->set($this->getCacheKeyFromParams($creditsUrl, 'GET', ['query' => $params]), json_encode($movie['credits']), 1800);
85
86 1
        return $movie;
87
    }
88
89
    /**
90
     * @param int $movieId
91
     * @param string $locale
92
     * @return array
93
     * @throws TmdbMovieNotFoundException
94
     * @throws TmdbRequestLimitException
95
     */
96
    public function findActorsByMovieId(int $movieId, string $locale = 'en'): array
97
    {
98
        $actors = $this->request("/movie/{$movieId}/credits", 'GET', [
99
            'query' => [
100
                'api_key' => $this->apiKey,
101
                'language' => $locale,
102
            ],
103
        ]);
104
105
        return $actors;
106
    }
107
108
    /**
109
     * @param int $personId
110
     * @param string $locale
111
     * @return array
112
     * @throws TmdbMovieNotFoundException
113
     * @throws TmdbRequestLimitException
114
     * @throws \Psr\SimpleCache\InvalidArgumentException
115
     */
116
    public function findActorById(int $personId, string $locale = 'en'): array
117
    {
118
        $actor = $this->request("/person/{$personId}", 'GET', [
119
            'query' => [
120
                'api_key' => $this->apiKey,
121
                'language' => $locale,
122
                'append_to_response' => 'translations'
123
            ],
124
        ]);
125
126
        $translationsUrl = "/person/{$personId}/translations";
127
        $params = ['api_key' => $this->apiKey, 'language' => $locale];
128
        $this->cache->set($this->getCacheKeyFromParams($translationsUrl, 'GET', ['query' => $params]), json_encode($actor['translations']), 1800);
129
130
        return $actor;
131
    }
132
133
    /**
134
     * @param int $personId
135
     * @param string $locale
136
     * @return array
137
     * @throws TmdbMovieNotFoundException
138
     * @throws TmdbRequestLimitException
139
     */
140
    public function findActorTranslationsById(int $personId, string $locale = 'en'): array
141
    {
142
        $actors = $this->request("/person/{$personId}/translations", 'GET', [
143
            'query' => [
144
                'api_key' => $this->apiKey,
145
                'language' => $locale,
146
            ],
147
        ]);
148
149
        return $actors;
150
    }
151
152
    /**
153
     * @param int $tmdb_id
154
     * @return array
155
     * @throws TmdbMovieNotFoundException
156
     * @throws TmdbRequestLimitException
157
     * @throws \Psr\SimpleCache\InvalidArgumentException
158
     */
159
    public function findMovieTranslationsById(int $tmdb_id): array
160
    {
161
        $movie = $this->request("/movie/{$tmdb_id}/translations", 'GET', [
162
            'query' => [
163
                'api_key' => $this->apiKey,
164
            ],
165
        ]);
166
167
        return $movie;
168
    }
169
170
    /**
171
     * @param int $tmdb_id
172
     * @param int $page
173
     *
174
     * @throws TmdbMovieNotFoundException
175
     * @throws TmdbRequestLimitException
176
     *
177
     * @return array
178
     */
179
    public function findSimilarMoviesById(int $tmdb_id, int $page = 1): array
180
    {
181
        $movie = $this->request("/movie/{$tmdb_id}/similar", 'GET', [
182
            'query' => [
183
                'api_key' => $this->apiKey,
184
                'page' => $page,
185
            ],
186
        ]);
187
188
        return $movie;
189
    }
190
191
    /**
192
     * @param string $url
193
     * @param string $method
194
     * @param array $params
195
     * @return array
196
     * @throws TmdbMovieNotFoundException
197
     * @throws TmdbRequestLimitException
198
     * @throws \Psr\SimpleCache\InvalidArgumentException
199
     */
200 2
    private function request(string $url, string $method = 'GET', array $params = []): array
201
    {
202 2
        if (null !== $cachedResponse = $this->getResponseFromCache($url, $method, $params)) {
203
            return $cachedResponse;
204
        }
205
206 2
        $url = self::ApiUrl.$url;
207
208
        try {
209 2
            $response = $this->client->request($method, $url, $params);
210 2
            $responseJson = $response->getBody()->getContents();
211 2
            $response = json_decode($responseJson, true);
212 2
            $this->cache->set($this->getCacheKeyFromParams($url, $method, $params), $responseJson, 1800);
213 2
            getenv('APP_ENV') === 'dev' && $this->logger->debug('Guzzle request:', [
214
                'url' => $url,
215
                'method' => $method,
216
                'params' => $params,
217 2
                'response' => $response,
218
            ]);
219
        } catch (GuzzleException $exception) {
220
            $this->logger->error('Guzzle request failed.', [
221
                'url' => $url,
222
                'method' => $method,
223
                'params' => $params,
224
                'exceptionMessage' => $exception->getMessage(),
225
                'exceptionCode' => $exception->getCode(),
226
            ]);
227
228
            $response = [];
229
230
            if ($exception->getCode() === 404) {
231
                throw new TmdbMovieNotFoundException();
232
            }
233
234
            if ($exception->getCode() === 429) {
235
                throw new TmdbRequestLimitException();
236
            }
237
        }
238
239 2
        return $response;
240
    }
241
242 2
    private function arrayAsString(array $array): string
243
    {
244 2
        $string = '';
245
246 2
        foreach ($array as $key => $value) {
247 2
            if (is_array($value) === true) {
248 2
                $value = $this->arrayAsString($value);
249
            }
250 2
            $string .= "$key-$value";
251
        }
252
253 2
        return $string;
254
    }
255
256 2
    private function getCacheKeyFromParams(string $url, string $method = 'GET', array $params = []): string
257
    {
258 2
        $key = md5($url . mb_strtolower($method) . $this->arrayAsString($params));
259 2
        return $key;
260
    }
261
262
    /**
263
     * @param string $url
264
     * @param string $method
265
     * @param array $params
266
     * @return array|null
267
     * @throws \Psr\SimpleCache\InvalidArgumentException
268
     */
269 2
    private function getResponseFromCache(string $url, string $method = 'GET', array $params = []): ?array
270
    {
271 2
        if (null !== $response = $this->cache->get($this->getCacheKeyFromParams($url, $method, $params))) {
272
            return json_decode($response, true);
273
        }
274
275 2
        return $response;
276
    }
277
}
278