Total Complexity | 253 |
Total Lines | 1266 |
Duplicated Lines | 0 % |
Changes | 14 | ||
Bugs | 7 | Features | 0 |
Complex classes like Movie often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Movie, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
37 | class Movie |
||
38 | { |
||
39 | /** |
||
40 | * @var int |
||
41 | */ |
||
42 | protected const MATCH_PERCENT = 75; |
||
43 | |||
44 | /** |
||
45 | * @var int |
||
46 | */ |
||
47 | protected const YEAR_MATCH_PERCENT = 80; |
||
48 | |||
49 | /** |
||
50 | * Current title being passed through various sites/api's. |
||
51 | */ |
||
52 | protected string $currentTitle = ''; |
||
53 | |||
54 | /** |
||
55 | * Current year of parsed search name. |
||
56 | */ |
||
57 | protected string $currentYear = ''; |
||
58 | |||
59 | /** |
||
60 | * Current release id of parsed search name. |
||
61 | */ |
||
62 | protected string $currentRelID = ''; |
||
63 | |||
64 | protected string $showPasswords; |
||
65 | |||
66 | protected ReleaseImage $releaseImage; |
||
67 | |||
68 | protected Client $client; |
||
69 | |||
70 | /** |
||
71 | * Language to fetch from IMDB. |
||
72 | */ |
||
73 | protected string $lookuplanguage; |
||
74 | |||
75 | public FanartTV $fanart; |
||
76 | |||
77 | /** |
||
78 | * @var null|string |
||
79 | */ |
||
80 | public mixed $fanartapikey; |
||
81 | |||
82 | /** |
||
83 | * @var null|string |
||
84 | */ |
||
85 | public mixed $omdbapikey; |
||
86 | |||
87 | /** |
||
88 | * @var bool |
||
89 | */ |
||
90 | public $imdburl; |
||
91 | |||
92 | public int $movieqty; |
||
93 | |||
94 | public bool $echooutput; |
||
95 | |||
96 | public string $imgSavePath; |
||
97 | |||
98 | public string $service; |
||
99 | |||
100 | public TraktTv $traktTv; |
||
101 | |||
102 | public ?OMDbAPI $omdbApi; |
||
103 | |||
104 | private Config $config; |
||
105 | |||
106 | /** |
||
107 | * @var null|string |
||
108 | */ |
||
109 | protected mixed $traktcheck; |
||
110 | |||
111 | protected ColorCLI $colorCli; |
||
112 | |||
113 | /** |
||
114 | * @throws \Exception |
||
115 | */ |
||
116 | public function __construct() |
||
117 | { |
||
118 | |||
119 | $this->releaseImage = new ReleaseImage; |
||
120 | $this->colorCli = new ColorCLI; |
||
121 | $this->traktcheck = config('nntmux_api.trakttv_api_key'); |
||
122 | if ($this->traktcheck !== null) { |
||
123 | $this->traktTv = new TraktTv(['Settings' => null]); |
||
|
|||
124 | } |
||
125 | $this->client = new Client; |
||
126 | $this->fanartapikey = config('nntmux_api.fanarttv_api_key'); |
||
127 | if ($this->fanartapikey !== null) { |
||
128 | $this->fanart = new FanartTV($this->fanartapikey); |
||
129 | } |
||
130 | $this->omdbapikey = config('nntmux_api.omdb_api_key'); |
||
131 | if ($this->omdbapikey !== null) { |
||
132 | $this->omdbApi = new OMDbAPI($this->omdbapikey); |
||
133 | } |
||
134 | |||
135 | $this->lookuplanguage = Settings::settingValue('indexer.categorise.imdblanguage') !== '' ? (string) Settings::settingValue('indexer.categorise.imdblanguage') : 'en'; |
||
136 | $this->config = new Config; |
||
137 | $this->config->language = $this->lookuplanguage; |
||
138 | $this->config->throwHttpExceptions = false; |
||
139 | $cacheDir = storage_path('framework/cache/imdb_cache'); |
||
140 | if (! File::isDirectory($cacheDir)) { |
||
141 | File::makeDirectory($cacheDir, 0777, false, true); |
||
142 | } |
||
143 | $this->config->cachedir = $cacheDir; |
||
144 | |||
145 | $this->imdburl = (int) Settings::settingValue('indexer.categorise.imdburl') !== 0; |
||
146 | $this->movieqty = Settings::settingValue('..maximdbprocessed') !== '' ? (int) Settings::settingValue('..maximdbprocessed') : 100; |
||
147 | $this->showPasswords = (new Releases)->showPasswords(); |
||
148 | |||
149 | $this->echooutput = config('nntmux.echocli'); |
||
150 | $this->imgSavePath = storage_path('covers/movies/'); |
||
151 | $this->service = ''; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * @return Builder|Model|null|object |
||
156 | */ |
||
157 | public function getMovieInfo($imdbId) |
||
158 | { |
||
159 | return MovieInfo::query()->where('imdbid', $imdbId)->first(); |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Get movie releases with covers for movie browse page. |
||
164 | * |
||
165 | * |
||
166 | * @return array|mixed |
||
167 | */ |
||
168 | public function getMovieRange($page, $cat, $start, $num, $orderBy, int $maxAge = -1, array $excludedCats = []) |
||
169 | { |
||
170 | $catsrch = ''; |
||
171 | if (\count($cat) > 0 && $cat[0] !== -1) { |
||
172 | $catsrch = Category::getCategorySearch($cat); |
||
173 | } |
||
174 | $order = $this->getMovieOrder($orderBy); |
||
175 | $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium')); |
||
176 | $moviesSql = |
||
177 | sprintf( |
||
178 | " |
||
179 | SELECT SQL_CALC_FOUND_ROWS |
||
180 | m.imdbid, |
||
181 | GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id |
||
182 | FROM movieinfo m |
||
183 | LEFT JOIN releases r USING (imdbid) |
||
184 | WHERE r.nzbstatus = 1 |
||
185 | AND m.title != '' |
||
186 | AND m.imdbid != '0000000' |
||
187 | AND r.passwordstatus %s |
||
188 | %s %s %s %s |
||
189 | GROUP BY m.imdbid |
||
190 | ORDER BY %s %s %s", |
||
191 | $this->showPasswords, |
||
192 | $this->getBrowseBy(), |
||
193 | (! empty($catsrch) ? $catsrch : ''), |
||
194 | ( |
||
195 | $maxAge > 0 |
||
196 | ? 'AND r.postdate > NOW() - INTERVAL '.$maxAge.'DAY ' |
||
197 | : '' |
||
198 | ), |
||
199 | \count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : '', |
||
200 | $order[0], |
||
201 | $order[1], |
||
202 | $start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start |
||
203 | ); |
||
204 | $movieCache = Cache::get(md5($moviesSql.$page)); |
||
205 | if ($movieCache !== null) { |
||
206 | $movies = $movieCache; |
||
207 | } else { |
||
208 | $data = MovieInfo::fromQuery($moviesSql); |
||
209 | $movies = ['total' => DB::select('SELECT FOUND_ROWS() AS total'), 'result' => $data]; |
||
210 | Cache::put(md5($moviesSql.$page), $movies, $expiresAt); |
||
211 | } |
||
212 | $movieIDs = $releaseIDs = []; |
||
213 | if (! empty($movies['result'])) { |
||
214 | foreach ($movies['result'] as $movie => $id) { |
||
215 | $movieIDs[] = $id->imdbid; |
||
216 | $releaseIDs[] = $id->grp_release_id; |
||
217 | } |
||
218 | } |
||
219 | |||
220 | $sql = sprintf( |
||
221 | " |
||
222 | SELECT |
||
223 | GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id, |
||
224 | GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',') AS grp_rarinnerfilecount, |
||
225 | GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',') AS grp_haspreview, |
||
226 | GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_password, |
||
227 | GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_guid, |
||
228 | GROUP_CONCAT(rn.releases_id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_nfoid, |
||
229 | GROUP_CONCAT(g.name ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grpname, |
||
230 | GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name, |
||
231 | GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_postdate, |
||
232 | GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_size, |
||
233 | GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_totalparts, |
||
234 | GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_comments, |
||
235 | GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grabs, |
||
236 | GROUP_CONCAT(df.failed ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_failed, |
||
237 | GROUP_CONCAT(cp.title, ' > ', c.title ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_catname, |
||
238 | m.*, |
||
239 | g.name AS group_name, |
||
240 | rn.releases_id AS nfoid |
||
241 | FROM releases r |
||
242 | LEFT OUTER JOIN usenet_groups g ON g.id = r.groups_id |
||
243 | LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id |
||
244 | LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id |
||
245 | LEFT OUTER JOIN categories c ON c.id = r.categories_id |
||
246 | LEFT OUTER JOIN root_categories cp ON cp.id = c.root_categories_id |
||
247 | INNER JOIN movieinfo m ON m.imdbid = r.imdbid |
||
248 | WHERE m.imdbid IN (%s) |
||
249 | AND r.id IN (%s) %s |
||
250 | GROUP BY m.imdbid |
||
251 | ORDER BY %s %s", |
||
252 | (\is_array($movieIDs) && ! empty($movieIDs) ? implode(',', $movieIDs) : -1), |
||
253 | (\is_array($releaseIDs) && ! empty($releaseIDs) ? implode(',', $releaseIDs) : -1), |
||
254 | (! empty($catsrch) ? $catsrch : ''), |
||
255 | $order[0], |
||
256 | $order[1] |
||
257 | ); |
||
258 | $return = Cache::get(md5($sql.$page)); |
||
259 | if ($return !== null) { |
||
260 | return $return; |
||
261 | } |
||
262 | $return = Release::fromQuery($sql); |
||
263 | if (\count($return) > 0) { |
||
264 | $return[0]->_totalcount = $movies['total'][0]->total ?? 0; |
||
265 | } |
||
266 | Cache::put(md5($sql.$page), $return, $expiresAt); |
||
267 | |||
268 | return $return; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Get the order type the user requested on the movies page. |
||
273 | */ |
||
274 | protected function getMovieOrder($orderBy): array |
||
275 | { |
||
276 | $orderArr = explode('_', (($orderBy === '') ? 'MAX(r.postdate)' : $orderBy)); |
||
277 | $orderField = match ($orderArr[0]) { |
||
278 | 'title' => 'm.title', |
||
279 | 'year' => 'm.year', |
||
280 | 'rating' => 'm.rating', |
||
281 | default => 'MAX(r.postdate)', |
||
282 | }; |
||
283 | |||
284 | return [$orderField, isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1]) ? $orderArr[1] : 'desc']; |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Order types for movies page. |
||
289 | */ |
||
290 | public function getMovieOrdering(): array |
||
291 | { |
||
292 | return ['title_asc', 'title_desc', 'year_asc', 'year_desc', 'rating_asc', 'rating_desc']; |
||
293 | } |
||
294 | |||
295 | protected function getBrowseBy(): string |
||
296 | { |
||
297 | $browseBy = ' '; |
||
298 | $browseByArr = ['title', 'director', 'actors', 'genre', 'rating', 'year', 'imdb']; |
||
299 | foreach ($browseByArr as $bb) { |
||
300 | if (request()->has($bb) && ! empty(request()->input($bb))) { |
||
301 | $bbv = stripslashes(request()->input($bb)); |
||
302 | if ($bb === 'rating') { |
||
303 | $bbv .= '.'; |
||
304 | } |
||
305 | if ($bb === 'imdb') { |
||
306 | $browseBy .= sprintf(' AND m.imdbid = %d', $bbv); |
||
307 | } else { |
||
308 | $browseBy .= ' AND m.'.$bb.' '.'LIKE '.escapeString('%'.$bbv.'%'); |
||
309 | } |
||
310 | } |
||
311 | } |
||
312 | |||
313 | return $browseBy; |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * Get trailer using IMDB Id. |
||
318 | * |
||
319 | * @return bool|string |
||
320 | * |
||
321 | * @throws \Exception |
||
322 | * @throws GuzzleException |
||
323 | */ |
||
324 | public function getTrailer(int $imdbId) |
||
325 | { |
||
326 | $trailer = MovieInfo::query()->where('imdbid', $imdbId)->where('trailer', '<>', '')->first(['trailer']); |
||
327 | if ($trailer !== null) { |
||
328 | return $trailer['trailer']; |
||
329 | } |
||
330 | |||
331 | if ($this->traktcheck !== null) { |
||
332 | $data = $this->traktTv->client->movieSummary('tt'.$imdbId, 'full'); |
||
333 | if (($data !== false) && ! empty($data['trailer'])) { |
||
334 | return $data['trailer']; |
||
335 | } |
||
336 | } |
||
337 | |||
338 | $trailer = Utility::imdb_trailers($imdbId); |
||
339 | if ($trailer) { |
||
340 | MovieInfo::query()->where('imdbid', $imdbId)->update(['trailer' => $trailer]); |
||
341 | |||
342 | return $trailer; |
||
343 | } |
||
344 | |||
345 | return false; |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * Parse trakt info, insert into DB. |
||
350 | * |
||
351 | * @return mixed |
||
352 | */ |
||
353 | public function parseTraktTv(array &$data) |
||
354 | { |
||
355 | if (empty($data['ids']['imdb'])) { |
||
356 | return false; |
||
357 | } |
||
358 | |||
359 | if (! empty($data['trailer'])) { |
||
360 | $data['trailer'] = str_ireplace( |
||
361 | ['watch?v=', 'http://'], |
||
362 | ['embed/', 'https://'], |
||
363 | $data['trailer'] |
||
364 | ); |
||
365 | } |
||
366 | $imdbId = (str_starts_with($data['ids']['imdb'], 'tt')) ? substr($data['ids']['imdb'], 2) : $data['ids']['imdb']; |
||
367 | $cover = 0; |
||
368 | if (File::isFile($this->imgSavePath.$imdbId).'-cover.jpg') { |
||
369 | $cover = 1; |
||
370 | } |
||
371 | |||
372 | return $this->update([ |
||
373 | 'genre' => implode(', ', $data['genres']), |
||
374 | 'imdbid' => $this->checkTraktValue($imdbId), |
||
375 | 'language' => $this->checkTraktValue($data['language']), |
||
376 | 'plot' => $this->checkTraktValue($data['overview']), |
||
377 | 'rating' => $this->checkTraktValue($data['rating']), |
||
378 | 'tagline' => $this->checkTraktValue($data['tagline']), |
||
379 | 'title' => $this->checkTraktValue($data['title']), |
||
380 | 'tmdbid' => $this->checkTraktValue($data['ids']['tmdb']), |
||
381 | 'traktid' => $this->checkTraktValue($data['ids']['trakt']), |
||
382 | 'trailer' => $this->checkTraktValue($data['trailer']), |
||
383 | 'cover' => $cover, |
||
384 | 'year' => $this->checkTraktValue($data['year']), |
||
385 | ]); |
||
386 | } |
||
387 | |||
388 | /** |
||
389 | * @return mixed|string |
||
390 | */ |
||
391 | private function checkTraktValue($value) |
||
392 | { |
||
393 | if (\is_array($value) && ! empty($value)) { |
||
394 | $temp = ''; |
||
395 | foreach ($value as $val) { |
||
396 | if (! \is_array($val) && ! \is_object($val)) { |
||
397 | $temp .= $val; |
||
398 | } |
||
399 | } |
||
400 | $value = $temp; |
||
401 | } |
||
402 | |||
403 | return ! empty($value) ? $value : ''; |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * Get array of column keys, for inserting / updating. |
||
408 | */ |
||
409 | public function getColumnKeys(): array |
||
410 | { |
||
411 | return [ |
||
412 | 'actors', 'backdrop', 'cover', 'director', 'genre', 'imdbid', 'language', |
||
413 | 'plot', 'rating', 'rtrating', 'tagline', 'title', 'tmdbid', 'traktid', 'trailer', 'type', 'year', |
||
414 | ]; |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * Update movie on movie-edit page. |
||
419 | * |
||
420 | * @param array $values Array of keys/values to update. See $validKeys |
||
421 | */ |
||
422 | public function update(array $values): bool |
||
451 | } |
||
452 | |||
453 | /** |
||
454 | * @return array|string |
||
455 | */ |
||
456 | protected function setVariables(string|array $variable1, string|array $variable2, string|array $variable3, string|array $variable4, string|array $variable5) |
||
457 | { |
||
458 | if (! empty($variable1)) { |
||
459 | return $variable1; |
||
460 | } |
||
461 | if (! empty($variable2)) { |
||
462 | return $variable2; |
||
463 | } |
||
464 | if (! empty($variable3)) { |
||
465 | return $variable3; |
||
466 | } |
||
467 | if (! empty($variable4)) { |
||
468 | return $variable4; |
||
469 | } |
||
470 | if (! empty($variable5)) { |
||
471 | return $variable5; |
||
472 | } |
||
473 | |||
474 | return ''; |
||
475 | } |
||
476 | |||
477 | /** |
||
478 | * Fetch IMDB/TMDB/TRAKT/OMDB/iTunes info for the movie. |
||
479 | * |
||
480 | * |
||
481 | * @throws \Exception |
||
482 | */ |
||
483 | public function updateMovieInfo($imdbId): bool |
||
626 | } |
||
627 | |||
628 | /** |
||
629 | * Fetch FanArt.tv backdrop / cover / title. |
||
630 | * |
||
631 | * @return array|false |
||
632 | */ |
||
633 | protected function fetchFanartTVProperties($imdbId) |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * Fetch info for IMDB id from TMDB. |
||
674 | * |
||
675 | * |
||
676 | * @return array|false |
||
677 | */ |
||
678 | public function fetchTMDBProperties($imdbId, bool $text = false) |
||
773 | } |
||
774 | |||
775 | /** |
||
776 | * @return array|false |
||
777 | */ |
||
778 | public function fetchIMDBProperties($imdbId) |
||
779 | { |
||
780 | $realId = (new Title($imdbId, $this->config))->real_id(); |
||
781 | $result = new Title($realId, $this->config); |
||
782 | $title = ! empty($result->orig_title()) ? $result->orig_title() : $result->title(); |
||
783 | if (! empty($title)) { |
||
784 | if (! empty($this->currentTitle)) { |
||
785 | similar_text($this->currentTitle, $title, $percent); |
||
786 | if ($percent >= self::MATCH_PERCENT) { |
||
787 | similar_text($this->currentYear, $result->year(), $percent); |
||
788 | if ($percent >= self::YEAR_MATCH_PERCENT) { |
||
789 | $ret = [ |
||
790 | 'title' => $title, |
||
791 | 'tagline' => $result->tagline() ?? '', |
||
792 | 'plot' => Arr::get($result->plot_split(), '0.plot'), |
||
793 | 'rating' => ! empty($result->rating()) ? $result->rating() : '', |
||
794 | 'year' => $result->year() ?? '', |
||
795 | 'cover' => $result->photo() ?? '', |
||
796 | 'genre' => $result->genre() ?? '', |
||
797 | 'language' => $result->language() ?? '', |
||
798 | 'type' => $result->movietype() ?? '', |
||
799 | ]; |
||
800 | |||
801 | if ($this->echooutput) { |
||
802 | $this->colorCli->climate()->info('IMDb found '.$title); |
||
803 | } |
||
804 | |||
805 | return $ret; |
||
806 | } |
||
807 | |||
808 | return false; |
||
809 | } |
||
810 | |||
811 | return false; |
||
812 | } |
||
813 | |||
814 | return [ |
||
815 | 'title' => $title, |
||
816 | 'tagline' => $result->tagline() ?? '', |
||
817 | 'plot' => Arr::get($result->plot_split(), '0.plot'), |
||
818 | 'rating' => ! empty($result->rating()) ? $result->rating() : '', |
||
819 | 'year' => $result->year() ?? '', |
||
820 | 'cover' => $result->photo() ?? '', |
||
821 | 'genre' => $result->genre() ?? '', |
||
822 | 'language' => $result->language() ?? '', |
||
823 | 'type' => $result->movietype() ?? '', |
||
824 | ]; |
||
825 | } |
||
826 | |||
827 | return false; |
||
828 | } |
||
829 | |||
830 | /** |
||
831 | * Fetch TraktTV backdrop / cover / title. |
||
832 | * |
||
833 | * @return array|false |
||
834 | * |
||
835 | * @throws \Exception |
||
836 | * @throws GuzzleException |
||
837 | */ |
||
838 | public function fetchTraktTVProperties($imdbId) |
||
839 | { |
||
840 | if ($this->traktcheck !== null) { |
||
841 | $resp = $this->traktTv->client->movieSummary('tt'.$imdbId, 'full'); |
||
842 | if ($resp !== false) { |
||
843 | similar_text($this->currentTitle, $resp['title'], $percent); |
||
844 | if ($percent >= self::MATCH_PERCENT) { |
||
845 | similar_text($this->currentYear, $resp['year'], $percent); |
||
846 | if ($percent >= self::YEAR_MATCH_PERCENT) { |
||
847 | $ret = []; |
||
848 | if (isset($resp['ids']['trakt'])) { |
||
849 | $ret['id'] = $resp['ids']['trakt']; |
||
850 | } |
||
851 | |||
852 | $ret['overview'] = $resp['overview'] ?? ''; |
||
853 | $ret['tagline'] = $resp['tagline'] ?? ''; |
||
854 | $ret['year'] = $resp['year'] ?? ''; |
||
855 | $ret['genres'] = $resp['genres'] ?? ''; |
||
856 | |||
857 | if (isset($resp['title'])) { |
||
858 | $ret['title'] = $resp['title']; |
||
859 | } else { |
||
860 | return false; |
||
861 | } |
||
862 | |||
863 | if ($this->echooutput) { |
||
864 | $this->colorCli->climate()->info('Trakt found '.$ret['title']); |
||
865 | } |
||
866 | |||
867 | return $ret; |
||
868 | } |
||
869 | |||
870 | return false; |
||
871 | } |
||
872 | |||
873 | return false; |
||
874 | } |
||
875 | |||
876 | return false; |
||
877 | } |
||
878 | |||
879 | return false; |
||
880 | } |
||
881 | |||
882 | /** |
||
883 | * Fetch OMDb backdrop / cover / title. |
||
884 | * |
||
885 | * @return array|false |
||
886 | */ |
||
887 | public function fetchOmdbAPIProperties($imdbId) |
||
888 | { |
||
889 | if ($this->omdbapikey !== null) { |
||
890 | $resp = $this->omdbApi->fetch('i', 'tt'.$imdbId); |
||
891 | |||
892 | if (\is_object($resp) && $resp->message === 'OK' && ! Str::contains($resp->data->Response, 'Error:') && $resp->data->Response !== 'False') { |
||
893 | similar_text($this->currentTitle, $resp->data->Title, $percent); |
||
894 | if ($percent >= self::MATCH_PERCENT) { |
||
895 | similar_text($this->currentYear, $resp->data->Year, $percent); |
||
896 | if ($percent >= self::YEAR_MATCH_PERCENT) { |
||
897 | $ret = [ |
||
898 | 'title' => $resp->data->Title ?? '', |
||
899 | 'cover' => $resp->data->Poster ?? '', |
||
900 | 'genre' => $resp->data->Genre ?? '', |
||
901 | 'year' => $resp->data->Year ?? '', |
||
902 | 'plot' => $resp->data->Plot ?? '', |
||
903 | 'rating' => $resp->data->imdbRating ?? '', |
||
904 | 'rtRating' => $resp->data->Ratings[1]->Value ?? '', |
||
905 | 'tagline' => $resp->data->Tagline ?? '', |
||
906 | 'director' => $resp->data->Director ?? '', |
||
907 | 'actors' => $resp->data->Actors ?? '', |
||
908 | 'language' => $resp->data->Language ?? '', |
||
909 | 'boxOffice' => $resp->data->BoxOffice ?? '', |
||
910 | ]; |
||
911 | |||
912 | if ($this->echooutput) { |
||
913 | $this->colorCli->climate()->info('OMDbAPI Found '.$ret['title']); |
||
914 | } |
||
915 | |||
916 | return $ret; |
||
917 | } |
||
918 | |||
919 | return false; |
||
920 | } |
||
921 | |||
922 | return false; |
||
923 | } |
||
924 | |||
925 | return false; |
||
926 | } |
||
927 | |||
928 | return false; |
||
929 | } |
||
930 | |||
931 | /** |
||
932 | * @return array|bool |
||
933 | * |
||
934 | * @throws InvalidProviderException |
||
935 | * @throws \Exception |
||
936 | */ |
||
937 | public function fetchItunesMovieProperties(string $title) |
||
938 | { |
||
939 | $movie = true; |
||
940 | try { |
||
941 | $iTunesMovie = iTunes::load('movie')->fetchOneByName($title); |
||
942 | } catch (MovieNotFoundException $e) { |
||
943 | $movie = false; |
||
944 | } catch (SearchNoResultsException $e) { |
||
945 | $movie = false; |
||
946 | } |
||
947 | |||
948 | if ($movie !== false) { |
||
949 | similar_text($this->currentTitle, $iTunesMovie->getName(), $percent); |
||
950 | if ($percent >= self::MATCH_PERCENT) { |
||
951 | $movie = [ |
||
952 | 'title' => $iTunesMovie->getName(), |
||
953 | 'director' => $iTunesMovie->getDirector() ?? '', |
||
954 | 'tagline' => $iTunesMovie->getTagLine() ?? '', |
||
955 | 'cover' => str_replace('100x100', '800x800', $iTunesMovie->getCover()), |
||
956 | 'genre' => $iTunesMovie->getGenre() ?? '', |
||
957 | 'plot' => $iTunesMovie->getDescription() ?? '', |
||
958 | 'year' => $iTunesMovie->getReleaseDate() ? $iTunesMovie->getReleaseDate()->format('Y') : '', |
||
959 | ]; |
||
960 | } else { |
||
961 | $movie = false; |
||
962 | } |
||
963 | } |
||
964 | |||
965 | return $movie; |
||
966 | } |
||
967 | |||
968 | /** |
||
969 | * Update a release with a IMDB id. |
||
970 | * |
||
971 | * @param string $buffer Data to parse a IMDB id/Trakt Id from. |
||
972 | * @param string $service Method that called this method. |
||
973 | * @param int $id id of the release. |
||
974 | * @param int $processImdb To get IMDB info on this IMDB id or not. |
||
975 | * |
||
976 | * @throws \Exception |
||
977 | */ |
||
978 | public function doMovieUpdate(string $buffer, string $service, int $id, int $processImdb = 1): string |
||
979 | { |
||
980 | $imdbId = false; |
||
981 | if (preg_match('/(?:imdb.*?)?(?:tt|Title\?)(?P<imdbid>\d{5,8})/i', $buffer, $hits)) { |
||
982 | $imdbId = $hits['imdbid']; |
||
983 | } |
||
984 | |||
985 | if ($imdbId !== false) { |
||
986 | $this->service = $service; |
||
987 | if ($this->echooutput && $this->service !== '') { |
||
988 | $this->colorCli->climate()->info($this->service.' found IMDBid: tt'.$imdbId); |
||
989 | } |
||
990 | |||
991 | $movieInfoId = MovieInfo::query()->where('imdbid', $imdbId)->first(['id']); |
||
992 | |||
993 | Release::query()->where('id', $id)->update(['imdbid' => $imdbId, 'movieinfo_id' => $movieInfoId !== null ? $movieInfoId['id'] : null]); |
||
994 | |||
995 | // If set, scan for imdb info. |
||
996 | if ($processImdb === 1) { |
||
997 | $movCheck = $this->getMovieInfo($imdbId); |
||
998 | if ($movCheck === null || (isset($movCheck['updated_at']) && (time() - strtotime($movCheck['updated_at'])) > 2592000)) { |
||
999 | $info = $this->updateMovieInfo($imdbId); |
||
1000 | if ($info === false) { |
||
1001 | Release::query()->where('id', $id)->update(['imdbid' => 0000000]); |
||
1002 | } elseif ($info === true) { |
||
1003 | $movieInfoId = MovieInfo::query()->where('imdbid', $imdbId)->first(['id']); |
||
1004 | |||
1005 | Release::query()->where('id', $id)->update(['imdbid' => $imdbId, 'movieinfo_id' => $movieInfoId !== null ? $movieInfoId['id'] : null]); |
||
1006 | } |
||
1007 | } |
||
1008 | } |
||
1009 | } |
||
1010 | |||
1011 | return $imdbId; |
||
1012 | } |
||
1013 | |||
1014 | /** |
||
1015 | * Process releases with no IMDB id's. |
||
1016 | * |
||
1017 | * |
||
1018 | * |
||
1019 | * @throws \Exception |
||
1020 | * @throws GuzzleException |
||
1021 | */ |
||
1022 | public function processMovieReleases(string $groupID = '', string $guidChar = '', int $lookupIMDB = 1): void |
||
1023 | { |
||
1024 | if ($lookupIMDB === 0) { |
||
1025 | return; |
||
1026 | } |
||
1027 | |||
1028 | // Get all releases without an IMDB id. |
||
1029 | $sql = Release::query() |
||
1030 | ->select(['searchname', 'id']) |
||
1031 | ->whereBetween('categories_id', [Category::MOVIE_ROOT, Category::MOVIE_OTHER]) |
||
1032 | ->whereNull('imdbid') |
||
1033 | ->where('nzbstatus', '=', 1); |
||
1034 | if ($groupID !== '') { |
||
1035 | $sql->where('groups_id', $groupID); |
||
1036 | } |
||
1037 | |||
1038 | if ($guidChar !== '') { |
||
1039 | $sql->where('leftguid', $guidChar); |
||
1040 | } |
||
1041 | |||
1042 | if ((int) $lookupIMDB === 2) { |
||
1043 | $sql->where('isrenamed', '=', 1); |
||
1044 | } |
||
1045 | |||
1046 | $res = $sql->limit($this->movieqty)->get(); |
||
1047 | |||
1048 | $movieCount = \count($res); |
||
1049 | |||
1050 | if ($movieCount > 0) { |
||
1051 | if ($this->echooutput && $movieCount > 1) { |
||
1052 | $this->colorCli->header('Processing '.$movieCount.' movie releases.'); |
||
1053 | } |
||
1054 | |||
1055 | // Loop over releases. |
||
1056 | foreach ($res as $arr) { |
||
1057 | // Try to get a name/year. |
||
1058 | if (! $this->parseMovieSearchName($arr['searchname'])) { |
||
1059 | //We didn't find a name, so set to all 0's so we don't parse again. |
||
1060 | Release::query()->where('id', $arr['id'])->update(['imdbid' => 0000000]); |
||
1061 | |||
1062 | continue; |
||
1063 | } |
||
1064 | $this->currentRelID = $arr['id']; |
||
1065 | |||
1066 | $movieName = $this->currentTitle; |
||
1067 | if ($this->currentYear !== '') { |
||
1068 | $movieName .= ' ('.$this->currentYear.')'; |
||
1069 | } |
||
1070 | |||
1071 | if ($this->echooutput) { |
||
1072 | $this->colorCli->climate()->info('Looking up: '.$movieName); |
||
1073 | } |
||
1074 | |||
1075 | $movieUpdated = false; |
||
1076 | |||
1077 | // Check local DB. |
||
1078 | $getIMDBid = $this->localIMDBSearch(); |
||
1079 | |||
1080 | if ($getIMDBid !== false) { |
||
1081 | $imdbId = $this->doMovieUpdate('tt'.$getIMDBid, 'Local DB', $arr['id']); |
||
1082 | if ($imdbId !== false) { |
||
1083 | $movieUpdated = true; |
||
1084 | } |
||
1085 | } |
||
1086 | |||
1087 | // Check on IMDb first |
||
1088 | if ($movieUpdated === false) { |
||
1089 | try { |
||
1090 | $imdbSearch = new TitleSearch($this->config); |
||
1091 | foreach ($imdbSearch->search($this->currentTitle, [TitleSearch::MOVIE]) as $imdbTitle) { |
||
1092 | if (! empty($imdbTitle->title())) { |
||
1093 | similar_text($imdbTitle->title(), $this->currentTitle, $percent); |
||
1094 | if ($percent >= self::MATCH_PERCENT) { |
||
1095 | similar_text($this->currentYear, $imdbTitle->year(), $percent); |
||
1096 | if ($percent >= self::YEAR_MATCH_PERCENT) { |
||
1097 | $getIMDBid = $imdbTitle->imdbid(); |
||
1098 | $imdbId = $this->doMovieUpdate('tt'.$getIMDBid, 'IMDb', $arr['id']); |
||
1099 | if ($imdbId !== false) { |
||
1100 | $movieUpdated = true; |
||
1101 | } |
||
1102 | } |
||
1103 | } |
||
1104 | } |
||
1105 | } |
||
1106 | } catch (\ErrorException $e) { |
||
1107 | $this->colorCli->error('Error fetching data from imdb occurred', true); |
||
1108 | Log::debug($e->getMessage()); |
||
1109 | } |
||
1110 | } |
||
1111 | |||
1112 | // Check on OMDbAPI |
||
1113 | if ($movieUpdated === false) { |
||
1114 | $omdbTitle = strtolower(str_replace(' ', '_', $this->currentTitle)); |
||
1115 | if ($this->omdbapikey !== null) { |
||
1116 | if ($this->currentYear !== '') { |
||
1117 | $buffer = $this->omdbApi->search($omdbTitle, 'movie', $this->currentYear); |
||
1118 | } else { |
||
1119 | $buffer = $this->omdbApi->search($omdbTitle, 'movie'); |
||
1120 | } |
||
1121 | |||
1122 | if (\is_object($buffer) && $buffer->message === 'OK' && ! Str::contains($buffer->data->Response, 'Error:') && $buffer->data->Response === 'True') { |
||
1123 | $getIMDBid = $buffer->data->Search[0]->imdbID; |
||
1124 | |||
1125 | if (! empty($getIMDBid)) { |
||
1126 | $imdbId = $this->doMovieUpdate($getIMDBid, 'OMDbAPI', $arr['id']); |
||
1127 | if ($imdbId !== false) { |
||
1128 | $movieUpdated = true; |
||
1129 | } |
||
1130 | } |
||
1131 | } |
||
1132 | } |
||
1133 | } |
||
1134 | |||
1135 | // Check on Trakt. |
||
1136 | if ($movieUpdated === false && $this->traktcheck !== null) { |
||
1137 | $data = $this->traktTv->client->movieSummary($movieName, 'full'); |
||
1138 | if ($data !== false) { |
||
1139 | $this->parseTraktTv($data); |
||
1140 | if (! empty($data['ids']['imdb'])) { |
||
1141 | $imdbId = $this->doMovieUpdate($data['ids']['imdb'], 'Trakt', $arr['id']); |
||
1142 | if ($imdbId !== false) { |
||
1143 | $movieUpdated = true; |
||
1144 | } |
||
1145 | } |
||
1146 | } |
||
1147 | } |
||
1148 | |||
1149 | // Check on The Movie Database. |
||
1150 | if ($movieUpdated === false) { |
||
1151 | try { |
||
1152 | $data = Tmdb::getSearchApi()->searchMovies($this->currentTitle); |
||
1153 | if (($data['total_results'] > 0) && ! empty($data['results'])) { |
||
1154 | foreach ($data['results'] as $result) { |
||
1155 | if (! empty($result['id']) && ! empty($result['release_date'])) { |
||
1156 | similar_text($this->currentYear, Carbon::parse($result['release_date'])->year, $percent); |
||
1157 | if ($percent >= self::YEAR_MATCH_PERCENT) { |
||
1158 | $ret = $this->fetchTMDBProperties($result['id'], true); |
||
1159 | if ($ret !== false && ! empty($ret['imdbid'])) { |
||
1160 | $imdbId = $this->doMovieUpdate('tt'.$ret['imdbid'], 'TMDB', $arr['id']); |
||
1161 | if ($imdbId !== false) { |
||
1162 | $movieUpdated = true; |
||
1163 | } |
||
1164 | } |
||
1165 | } |
||
1166 | } else { |
||
1167 | $movieUpdated = false; |
||
1168 | } |
||
1169 | } |
||
1170 | } else { |
||
1171 | $movieUpdated = false; |
||
1172 | } |
||
1173 | } catch (TmdbApiException|\ErrorException $error) { |
||
1174 | $movieUpdated = false; |
||
1175 | } |
||
1176 | } |
||
1177 | |||
1178 | // We failed to get an IMDB id from all sources. |
||
1179 | if ($movieUpdated === false) { |
||
1180 | Release::query()->where('id', $arr['id'])->update(['imdbid' => 0000000]); |
||
1181 | } |
||
1182 | } |
||
1183 | } |
||
1184 | } |
||
1185 | |||
1186 | /** |
||
1187 | * @return false|mixed |
||
1188 | */ |
||
1189 | protected function localIMDBSearch() |
||
1190 | { |
||
1191 | //If we found a year, try looking in a 4 year range. |
||
1192 | $check = MovieInfo::query() |
||
1193 | ->where('title', 'like', '%'.$this->currentTitle.'%'); |
||
1194 | |||
1195 | if ($this->currentYear !== '') { |
||
1196 | $start = Carbon::createFromFormat('Y', $this->currentYear)->subYears(2)->year; |
||
1197 | $end = Carbon::createFromFormat('Y', $this->currentYear)->addYears(2)->year; |
||
1198 | $check->whereBetween('year', [$start, $end]); |
||
1199 | } |
||
1200 | $IMDBCheck = $check->get(['imdbid']); |
||
1201 | foreach ($IMDBCheck as $check) { |
||
1202 | // match the title and year of the movie as close as possible. |
||
1203 | if ($this->currentYear !== '') { |
||
1204 | $IMDBCheck = MovieInfo::query() |
||
1205 | ->where('imdbid', $check['imdbid']) |
||
1206 | ->where('title', 'like', '%'.$this->currentTitle.'%') |
||
1207 | ->whereBetween('year', [$start, $end]) |
||
1208 | ->first(['imdbid', 'title']); |
||
1209 | } else { |
||
1210 | $IMDBCheck = MovieInfo::query() |
||
1211 | ->where('imdbid', $check['imdbid']) |
||
1212 | ->where('title', 'like', '%'.$this->currentTitle.'%') |
||
1213 | ->first(['imdbid', 'title']); |
||
1214 | } |
||
1215 | // If we found a match, check if percentage is high enough. If so, return the IMDB id. |
||
1216 | if ($IMDBCheck !== null) { |
||
1217 | similar_text($this->currentTitle, $IMDBCheck['title'], $percent); |
||
1218 | if ($percent >= self::MATCH_PERCENT) { |
||
1219 | return $IMDBCheck['imdbid']; |
||
1220 | } |
||
1221 | } |
||
1222 | } |
||
1223 | |||
1224 | return false; |
||
1225 | } |
||
1226 | |||
1227 | /** |
||
1228 | * Parse a movie name from a release search name. |
||
1229 | */ |
||
1230 | protected function parseMovieSearchName(string $releaseName): bool |
||
1269 | } |
||
1270 | |||
1271 | /** |
||
1272 | * Get IMDB genres. |
||
1273 | */ |
||
1274 | public function getGenres(): array |
||
1303 | ]; |
||
1304 | } |
||
1305 | } |
||
1306 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.