Passed
Pull Request — master (#3)
by
unknown
01:53
created

TVDB::getUpdates()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 12
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
namespace musa11971\TVDB;
4
5
use Illuminate\Support\Facades\Cache;
0 ignored issues
show
Bug introduced by
The type Illuminate\Support\Facades\Cache was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
7
class TVDB {
8
    /*
9
     * Cache key used to store JWT token
10
     */
11
    const TOKEN_CACHE_KEY = 'tvdb_jwt_token';
12
13
    /*
14
     * How many minutes to cache the JWT token for
15
     * Currently a TVDB token is valid for 24 hours
16
     */
17
    const TOKEN_CACHE_TIME = 1440;
18
19
    /*
20
     * How many episodes does TVDB return per page
21
     */
22
    const EPISODES_PER_PAGE = 100;
23
24
    /*
25
     * TVDB API base URL
26
     */
27
    const API_URL = 'https://api.thetvdb.com';
28
29
    /*
30
     * Types of images
31
     */
32
    const IMAGE_TYPE_FANART = 'fanart';
33
    const IMAGE_TYPE_POSTER = 'poster';
34
    const IMAGE_TYPE_SEASON = 'season';
35
    const IMAGE_TYPE_SERIES = 'series';
36
37
    /*
38
     * Image URL prefix
39
     */
40
    const IMAGE_URL_PREFIX = 'https://www.thetvdb.com/banners/';
41
42
    /**
43
     * Searches for series
44
     *
45
     * @param array|string $options
46
     * @throws Exceptions\TVDBUnauthorizedException
47
     * @throws Exceptions\TVDBNotFoundException
48
     *
49
     * @return array
50
     */
51
    public static function search($options) {
52
        // Format search query
53
        $query = [];
54
55
        if((is_array($options) && isset($options['title'])))
56
            $query['name'] = $options['title'];
57
        else if(is_string($options))
58
            $query['name'] = $options;
59
60
        if(is_array($options) && isset($options['imdbId'])) $query['imdbId'] = $options['imdbId'];
61
        if(is_array($options) && isset($options['zap2itId'])) $query['zap2itId'] = $options['zap2itId'];
62
63
        $response = self::request([
64
            'method'    => 'GET',
65
            'url'       => self::apiURL('/search/series'),
66
            'query'     => $query,
67
            'auth'      => true,
68
            'name'      => 'search_series'
69
        ]);
70
71
        if(!$response->isSuccessful()) $response->throwException();
72
73
        $responseData = (isset($response->json()->data)) ? $response->json()->data : [];
74
        $series = [];
75
76
        foreach($responseData as $seriesData)
77
            $series[] = new Series($seriesData);
78
79
        return $series;
80
    }
81
82
    /**
83
     * Retrieves a series' details
84
     *
85
     * @param integer $id
86
     * @throws Exceptions\TVDBUnauthorizedException
87
     * @throws Exceptions\TVDBNotFoundException
88
     *
89
     * @return Series
90
     */
91
    public static function getSeries($id) {
92
        $response = self::request([
93
            'method'    => 'GET',
94
            'url'       => self::apiURL('/series/' . $id),
95
            'auth'      => true,
96
            'name'      => 'get_series'
97
        ]);
98
99
        if(!$response->isSuccessful()) $response->throwException();
100
101
        return new Series($response->json()->data);
102
    }
103
104
    /**
105
     * Retrieves a series' actor details
106
     *
107
     * @param integer $id
108
     * @throws Exceptions\TVDBNotFoundException
109
     * @throws Exceptions\TVDBUnauthorizedException
110
     *
111
     * @return array
112
     */
113
    public static function getSeriesActors($id) {
114
        $response = self::request([
115
            'method'    => 'GET',
116
            'url'       => self::apiURL('/series/' . $id . '/actors'),
117
            'auth'      => true,
118
            'name'      => 'get_series_actors'
119
        ]);
120
121
        if(!$response->isSuccessful()) $response->throwException();
122
123
        $returnData = [];
124
125
        foreach($response->json()->data as $actorData)
126
            $returnData[] = new Actor($actorData);
127
128
        return $returnData;
129
    }
130
131
    /**
132
     * Retrieves a series' images
133
     *
134
     * @param integer $id
135
     *
136
     * @return array
137
     * @throws Exceptions\TVDBNotFoundException
138
     * @throws Exceptions\TVDBUnauthorizedException
139
     */
140
    public static function getSeriesImages($id, $type) {
141
        $response = self::request([
142
            'method'    => 'GET',
143
            'url'       => self::apiURL('/series/' . $id . '/images/query'),
144
            'query'     => ['keyType' => $type],
145
            'auth'      => true,
146
            'name'      => 'get_series_images'
147
        ]);
148
149
        if(!$response->isSuccessful()) $response->throwException();
150
151
        $returnData = [];
152
153
        foreach($response->json()->data as $imageData)
154
            $returnData[] = [
155
                'resolution'    => $imageData->resolution,
156
                'image'         => self::IMAGE_URL_PREFIX . $imageData->fileName,
157
                'image_thumb'   => self::IMAGE_URL_PREFIX . $imageData->thumbnail
158
            ];
159
160
        return $returnData;
161
    }
162
163
    /**
164
     * Retrieves a series' episode details
165
     *
166
     * @param integer $id
167
     * @param int $page
168
     *
169
     * @return EpisodeCollection
170
     * @throws Exceptions\TVDBNotFoundException
171
     * @throws Exceptions\TVDBUnauthorizedException
172
     */
173
    public static function getSeriesEpisodes($id, $page = 1) {
174
        $response = self::request([
175
            'method'    => 'GET',
176
            'url'       => self::apiURL('/series/' . $id . '/episodes'),
177
            'query'     => ['page' => $page],
178
            'auth'      => true,
179
            'name'      => 'get_series_episodes'
180
        ]);
181
182
        if(!$response->isSuccessful()) $response->throwException();
183
184
        $returnData = [];
185
186
        foreach($response->json()->data as $episodeData)
187
            $returnData[] = new Episode($episodeData);
188
189
        return new EpisodeCollection($page, $returnData);
190
    }
191
192
    /**
193
     * Retrieves an episodes details
194
     *
195
     * @param integer $id
196
     * @throws Exceptions\TVDBUnauthorizedException
197
     * @throws Exceptions\TVDBNotFoundException
198
     *
199
     * @return Episode
200
     */
201
    public static function getEpisode($id) {
202
        $response = self::request([
203
            'method'    => 'GET',
204
            'url'       => self::apiURL('/episodes/' . $id),
205
            'auth'      => true,
206
            'name'      => 'get_episode'
207
        ]);
208
209
        if(!$response->isSuccessful()) $response->throwException();
210
211
        return new Episode($response->json()->data);
212
    }
213
214
    /**
215
	 * Retrieves Updates From Minutes Ago (max 7 days in the past)
216
	 *
217
	 * @param integer $from_minutes_ago
218
	 * @throws Exceptions\TVDBUnauthorizedException
219
	 * @throws Exceptions\TVDBNotFoundException
220
	 *
221
	 * @return UpdateCollection
0 ignored issues
show
Bug introduced by
The type musa11971\TVDB\UpdateCollection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
222
	 */
223
	public static function getUpdates($from_minutes_ago) {
224
		$from_time = time() - ($from_minutes_ago * 60);
225
		$response = self::request([
226
			'method'    => 'GET',
227
			'url'       => self::apiURL('/updated/query?fromTime=' . $from_time),
228
			'auth'      => true,
229
			'name'      => 'get_episode'
230
		]);
231
232
		if(!$response->isSuccessful()) $response->throwException();
233
234
		return new Updates($response->json()->data);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new musa11971\TVD...response->json()->data) returns the type musa11971\TVDB\Updates which is incompatible with the documented return type musa11971\TVDB\UpdateCollection.
Loading history...
235
	}
236
    
237
    /**
238
     * Returns a valid TVDB token to use for authentication
239
     *
240
     * @return null
241
     * @throws Exceptions\TVDBUnauthorizedException
242
     * @throws Exceptions\TVDBNotFoundException
243
     */
244
    public static function getToken() {
245
        // Try to to refresh the cached token if there is one
246
        if(Cache::has(self::TOKEN_CACHE_KEY)) {
247
            return Cache::get(self::TOKEN_CACHE_KEY);
248
        }
249
250
        // Create the post fields
251
        $postfields = [
252
            'apikey'    => config('tvdb.api_key'),
0 ignored issues
show
Bug introduced by
The function config 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

252
            'apikey'    => /** @scrutinizer ignore-call */ config('tvdb.api_key'),
Loading history...
253
            'userkey'   => config('tvdb.user_key'),
254
            'username'  => config('tvdb.username')
255
        ];
256
257
        // Make login request
258
        $loginResponse = self::request([
259
            'method'        => 'POST',
260
            'url'           => self::apiURL('/login'),
261
            'postfields'    => $postfields,
262
            'name'          => 'login'
263
        ]);
264
265
        // Login may have failed
266
        if(!$loginResponse->isSuccessful()) $loginResponse->throwException();
267
268
        // Successfully logged in
269
        $token = $loginResponse->json()->token;
270
271
        // Cache the token and return it
272
        Cache::put(self::TOKEN_CACHE_KEY, $token, self::TOKEN_CACHE_TIME);
273
274
        return $token;
275
    }
276
277
    /**
278
     * Internal function used to make requests
279
     *
280
     * @param array $options
281
     * @return TVDBRequestResponse
282
     * @throws Exceptions\TVDBUnauthorizedException
283
     * @throws Exceptions\TVDBNotFoundException
284
     */
285
    protected static function request($options) {
286
        $url = $options['url'];
287
288
        // Add URL query params
289
        if(isset($options['query']))
290
            $url .= '?' . http_build_query($options['query']);
291
292
        // Initialize handle
293
        $curlHandle = curl_init($url);
294
295
        // Create headers
296
        $requestHeaders = ['Content-Type: application/json'];
297
298
        // Add authentication header
299
        $usedToken = null;
300
301
        if(isset($options['auth']) && $options['auth'] === true) {
302
            $usedToken = self::getToken();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $usedToken is correct as self::getToken() targeting musa11971\TVDB\TVDB::getToken() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
303
            $requestHeaders[] = 'Authorization: ' . 'Bearer ' . $usedToken;
304
        }
305
306
        // Add postfields
307
        if(isset($options['postfields'])) {
308
            curl_setopt($curlHandle, CURLOPT_POSTFIELDS, json_encode($options['postfields']));
0 ignored issues
show
Bug introduced by
It seems like $curlHandle can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

308
            curl_setopt(/** @scrutinizer ignore-type */ $curlHandle, CURLOPT_POSTFIELDS, json_encode($options['postfields']));
Loading history...
309
        }
310
311
        // Make request
312
        curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, $options['method']);
313
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
314
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $requestHeaders);
315
        $response = curl_exec($curlHandle);
0 ignored issues
show
Bug introduced by
It seems like $curlHandle can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

315
        $response = curl_exec(/** @scrutinizer ignore-type */ $curlHandle);
Loading history...
316
317
        // Get curl info
318
        $requestInfo = curl_getinfo($curlHandle);
0 ignored issues
show
Bug introduced by
It seems like $curlHandle can also be of type false; however, parameter $ch of curl_getinfo() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

318
        $requestInfo = curl_getinfo(/** @scrutinizer ignore-type */ $curlHandle);
Loading history...
319
320
        // Close handle
321
        curl_close($curlHandle);
0 ignored issues
show
Bug introduced by
It seems like $curlHandle can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

321
        curl_close(/** @scrutinizer ignore-type */ $curlHandle);
Loading history...
322
323
        return new TVDBRequestResponse($requestInfo, $response, $usedToken,
324
            ((isset($options['name'])) ? $options['name'] : '')
325
        );
326
    }
327
328
    /**
329
     * Helper to create an API url with an endpoint appended
330
     *
331
     * @param string $append
332
     * @return string
333
     */
334
    protected static function apiURL($append = '') {
335
        return self::API_URL . $append;
336
    }
337
}
338