Completed
Branch dev (4bcb34)
by Darko
13:52
created

Movie::parseMovieSearchName()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 40
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 12
nop 1
dl 0
loc 40
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
namespace Blacklight;
4
5
use Imdb\Title;
6
use Imdb\Config;
7
use Tmdb\ApiToken;
8
use aharen\OMDbAPI;
9
use Blacklight\db\DB;
10
use GuzzleHttp\Client;
11
use App\Models\Release;
12
use App\Models\Category;
13
use App\Models\Settings;
14
use App\Models\MovieInfo;
15
use Tmdb\Helper\ImageHelper;
16
use Illuminate\Support\Carbon;
17
use Tmdb\Client as TmdbClient;
18
use Blacklight\utility\Utility;
19
use Blacklight\libraries\FanartTV;
20
use Tmdb\Exception\TmdbApiException;
21
use Blacklight\processing\tv\TraktTv;
22
use Illuminate\Support\Facades\Cache;
23
use Tmdb\Repository\ConfigurationRepository;
24
25
/**
26
 * Class Movie.
27
 */
28
class Movie
29
{
30
    protected const MATCH_PERCENT = 75;
31
32
    protected const YEAR_MATCH_PERCENT = 80;
33
34
    /**
35
     * @var \Blacklight\db\DB
36
     */
37
    public $pdo;
38
39
    /**
40
     * Current title being passed through various sites/api's.
41
     * @var string
42
     */
43
    protected $currentTitle = '';
44
45
    /**
46
     * Current year of parsed search name.
47
     * @var string
48
     */
49
    protected $currentYear = '';
50
51
    /**
52
     * Current release id of parsed search name.
53
     *
54
     * @var string
55
     */
56
    protected $currentRelID = '';
57
58
    /**
59
     * @var string
60
     */
61
    protected $showPasswords;
62
63
    /**
64
     * @var \Blacklight\ReleaseImage
65
     */
66
    protected $releaseImage;
67
68
    /**
69
     * @var \Tmdb\Client
70
     */
71
    protected $tmdbclient;
72
73
    /**
74
     * @var \GuzzleHttp\Client
75
     */
76
    protected $client;
77
78
    /**
79
     * Language to fetch from IMDB.
80
     * @var string
81
     */
82
    protected $lookuplanguage;
83
84
    /**
85
     * @var \Blacklight\libraries\FanartTV
86
     */
87
    public $fanart;
88
89
    /**
90
     * @var null|string
91
     */
92
    public $fanartapikey;
93
94
    /**
95
     * @var null|string
96
     */
97
    public $omdbapikey;
98
99
    /**
100
     * @var bool
101
     */
102
    public $imdburl;
103
104
    /**
105
     * @var array|bool|int|string
106
     */
107
    public $movieqty;
108
109
    /**
110
     * @var bool
111
     */
112
    public $echooutput;
113
114
    /**
115
     * @var string
116
     */
117
    public $imgSavePath;
118
119
    /**
120
     * @var string
121
     */
122
    public $service;
123
124
    /**
125
     * @var \Tmdb\ApiToken
126
     */
127
    public $tmdbtoken;
128
129
    /**
130
     * @var null|TraktTv
131
     */
132
    public $traktTv;
133
134
    /**
135
     * @var OMDbAPI|null
136
     */
137
    public $omdbApi;
138
139
    /**
140
     * @var \Imdb\Config
141
     */
142
    private $config;
143
144
    /**
145
     * @var \Tmdb\Repository\ConfigurationRepository
146
     */
147
    protected $configRepository;
148
149
    /**
150
     * @var \Tmdb\Helper\ImageHelper
151
     */
152
    protected $helper;
153
154
    /**
155
     * @var \Tmdb\Model\Configuration
156
     */
157
    protected $tmdbconfig;
158
159
    /**
160
     * @param array $options Class instances / Echo to CLI.
161
     * @throws \Exception
162
     */
163
    public function __construct(array $options = [])
164
    {
165
        $defaults = [
166
            'Echo'         => false,
167
            'Logger'    => null,
168
            'ReleaseImage' => null,
169
            'Settings'     => null,
170
            'TMDb'         => null,
171
        ];
172
        $options += $defaults;
173
174
        $this->pdo = ($options['Settings'] instanceof DB ? $options['Settings'] : new DB());
175
        $this->releaseImage = ($options['ReleaseImage'] instanceof ReleaseImage ? $options['ReleaseImage'] : new ReleaseImage());
176
        $this->client = new Client();
177
        $this->tmdbtoken = new ApiToken(Settings::settingValue('APIs..tmdbkey'));
0 ignored issues
show
Bug introduced by
'APIs..tmdbkey' of type string is incompatible with the type boolean|array expected by parameter $setting of App\Models\Settings::settingValue(). ( Ignorable by Annotation )

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

177
        $this->tmdbtoken = new ApiToken(Settings::settingValue(/** @scrutinizer ignore-type */ 'APIs..tmdbkey'));
Loading history...
178
        $this->tmdbclient = new TmdbClient(
179
            $this->tmdbtoken,
180
            [
181
            'cache' => [
182
                'enabled' => false,
183
            ],
184
        ]
185
        );
186
        $this->configRepository = new ConfigurationRepository($this->tmdbclient);
187
        $this->tmdbconfig = $this->configRepository->load();
188
        $this->helper = new ImageHelper($this->tmdbconfig);
189
        $this->fanartapikey = Settings::settingValue('APIs..fanarttvkey');
190
        $this->fanart = new FanartTV($this->fanartapikey);
191
        $this->omdbapikey = Settings::settingValue('APIs..omdbkey');
192
        if ($this->omdbapikey !== null) {
193
            $this->omdbApi = new OMDbAPI($this->omdbapikey);
194
        }
195
196
        $this->lookuplanguage = Settings::settingValue('indexer.categorise.imdblanguage') !== '' ? (string) Settings::settingValue('indexer.categorise.imdblanguage') : 'en';
197
        $this->config = new Config();
198
        $this->config->language = $this->lookuplanguage;
199
        $this->config->throwHttpExceptions = false;
200
201
        $this->imdburl = (int) Settings::settingValue('indexer.categorise.imdburl') !== 0;
202
        $this->movieqty = Settings::settingValue('..maximdbprocessed') !== '' ? (int) Settings::settingValue('..maximdbprocessed') : 100;
203
        $this->showPasswords = Releases::showPasswords();
204
205
        $this->echooutput = ($options['Echo'] && config('nntmux.echocli'));
206
        $this->imgSavePath = NN_COVERS.'movies/';
207
        $this->service = '';
208
    }
209
210
    /**
211
     * @param $imdbId
212
     * @return array|bool|\Illuminate\Database\Eloquent\Model|null|static
213
     */
214
    public function getMovieInfo($imdbId)
215
    {
216
        return MovieInfo::query()->where('imdbid', $imdbId)->first();
217
    }
218
219
    /**
220
     * Get movie releases with covers for movie browse page.
221
     *
222
     * @param       $cat
223
     * @param       $start
224
     * @param       $num
225
     * @param       $orderBy
226
     * @param       $maxAge
227
     * @param array $excludedCats
228
     *
229
     * @return array|bool|\PDOStatement
230
     * @throws \Exception
231
     */
232
    public function getMovieRange($cat, $start, $num, $orderBy, $maxAge = -1, array $excludedCats = [])
233
    {
234
        $catsrch = '';
235
        if (\count($cat) > 0 && $cat[0] !== -1) {
236
            $catsrch = Category::getCategorySearch($cat);
237
        }
238
239
        $order = $this->getMovieOrder($orderBy);
240
        $expiresAt = Carbon::now()->addSeconds(config('nntmux.cache_expiry_medium'));
241
242
        $moviesSql =
243
                sprintf(
244
                    "
245
					SELECT SQL_CALC_FOUND_ROWS
246
						m.imdbid,
247
						GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id
248
					FROM movieinfo m
249
					LEFT JOIN releases r USING (imdbid)
250
					WHERE r.nzbstatus = 1
251
					AND m.title != ''
252
					AND m.imdbid != '0000000'
253
					AND r.passwordstatus %s
254
					%s %s %s %s
255
					GROUP BY m.imdbid
256
					ORDER BY %s %s %s",
257
                        $this->showPasswords,
258
                        $this->getBrowseBy(),
259
                        (! empty($catsrch) ? $catsrch : ''),
260
                        (
261
                            $maxAge > 0
262
                                ? 'AND r.postdate > NOW() - INTERVAL '.$maxAge.'DAY '
263
                                : ''
264
                        ),
265
                        (\count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''),
266
                        $order[0],
267
                        $order[1],
268
                        ($start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start)
269
                );
270
        $movieCache = Cache::get(md5($moviesSql));
271
        if ($movieCache !== null) {
272
            $movies = $movieCache;
273
        } else {
274
            $movies = $this->pdo->queryCalc($moviesSql);
275
            Cache::put(md5($moviesSql), $movies, $expiresAt);
276
        }
277
278
        $movieIDs = $releaseIDs = false;
279
280
        if (\is_array($movies['result'])) {
281
            foreach ($movies['result'] as $movie => $id) {
282
                $movieIDs[] = $id['imdbid'];
283
                $releaseIDs[] = $id['grp_release_id'];
284
            }
285
        }
286
287
        $sql = sprintf(
288
            "
289
			SELECT
290
				GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id,
291
				GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',') AS grp_rarinnerfilecount,
292
				GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',') AS grp_haspreview,
293
				GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_password,
294
				GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_guid,
295
				GROUP_CONCAT(rn.releases_id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_nfoid,
296
				GROUP_CONCAT(g.name ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grpname,
297
				GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name,
298
				GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_postdate,
299
				GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_size,
300
				GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_totalparts,
301
				GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_comments,
302
				GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grabs,
303
				GROUP_CONCAT(df.failed ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_failed,
304
				GROUP_CONCAT(cp.title, ' > ', c.title ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_catname,
305
			m.*,
306
			g.name AS group_name,
307
			rn.releases_id AS nfoid
308
			FROM releases r
309
			LEFT OUTER JOIN groups g ON g.id = r.groups_id
310
			LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id
311
			LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id
312
			LEFT OUTER JOIN categories c ON c.id = r.categories_id
313
			LEFT OUTER JOIN categories cp ON cp.id = c.parentid
314
			INNER JOIN movieinfo m ON m.imdbid = r.imdbid
315
			WHERE m.imdbid IN (%s)
316
			AND r.id IN (%s) %s
317
			GROUP BY m.imdbid
318
			ORDER BY %s %s",
319
                (\is_array($movieIDs) ? implode(',', $movieIDs) : -1),
0 ignored issues
show
introduced by
The condition is_array($movieIDs) is always false.
Loading history...
320
                (\is_array($releaseIDs) ? implode(',', $releaseIDs) : -1),
0 ignored issues
show
introduced by
The condition is_array($releaseIDs) is always false.
Loading history...
321
                (! empty($catsrch) ? $catsrch : ''),
322
                $order[0],
323
                $order[1]
324
        );
325
        $return = Cache::get(md5($sql));
326
        if ($return !== null) {
327
            return $return;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $return returns the type Illuminate\Contracts\Cache\Repository which is incompatible with the documented return type PDOStatement|boolean|array.
Loading history...
328
        }
329
        $return = $this->pdo->query($sql);
330
        if (! empty($return)) {
331
            $return[0]['_totalcount'] = $movies['total'] ?? 0;
332
        }
333
334
        Cache::put(md5($sql), $return, $expiresAt);
335
336
        return $return;
337
    }
338
339
    /**
340
     * Get the order type the user requested on the movies page.
341
     *
342
     * @param $orderBy
343
     *
344
     * @return array
345
     */
346
    protected function getMovieOrder($orderBy): array
347
    {
348
        $orderArr = explode('_', (($orderBy === '') ? 'MAX(r.postdate)' : $orderBy));
349
        switch ($orderArr[0]) {
350
            case 'title':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
351
                $orderField = 'm.title';
352
                break;
353
            case 'year':
354
                $orderField = 'm.year';
355
                break;
356
            case 'rating':
357
                $orderField = 'm.rating';
358
                break;
359
            case 'posted':
360
            default:
361
                $orderField = 'MAX(r.postdate)';
362
                break;
363
        }
364
365
        return [$orderField, isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1]) ? $orderArr[1] : 'desc'];
366
    }
367
368
    /**
369
     * Order types for movies page.
370
     *
371
     * @return array
372
     */
373
    public function getMovieOrdering(): array
374
    {
375
        return ['title_asc', 'title_desc', 'year_asc', 'year_desc', 'rating_asc', 'rating_desc'];
376
    }
377
378
    /**
379
     * @return string
380
     */
381
    protected function getBrowseBy(): string
382
    {
383
        $browseBy = ' ';
384
        $browseByArr = ['title', 'director', 'actors', 'genre', 'rating', 'year', 'imdb'];
385
        foreach ($browseByArr as $bb) {
386
            if (request()->has($bb) && ! empty(request()->input($bb))) {
387
                $bbv = stripslashes(request()->input($bb));
388
                if ($bb === 'rating') {
389
                    $bbv .= '.';
390
                }
391
                if ($bb === 'imdb') {
392
                    $browseBy .= sprintf('AND m.imdbid = %d', $bbv);
393
                } else {
394
                    $browseBy .= 'AND m.'.$bb.' '.$this->pdo->likeString($bbv, true, true);
395
                }
396
            }
397
        }
398
399
        return $browseBy;
400
    }
401
402
    /**
403
     * Get trailer using IMDB Id.
404
     *
405
     * @param int $imdbID
406
     *
407
     * @return bool|string
408
     * @throws \Exception
409
     */
410
    public function getTrailer($imdbID)
411
    {
412
        if (! is_numeric($imdbID)) {
0 ignored issues
show
introduced by
The condition is_numeric($imdbID) is always true.
Loading history...
413
            return false;
414
        }
415
416
        $trailer = MovieInfo::query()->where('imdbid', $imdbID)->where('trailer', '!=', '')->first(['trailer']);
417
        if ($trailer !== null) {
418
            return $trailer['trailer'];
419
        }
420
421
        if ($this->traktTv === null) {
422
            $this->traktTv = new TraktTv(['Settings' => $this->pdo]);
423
        }
424
425
        $data = $this->traktTv->client->movieSummary('tt'.$imdbID, 'full');
426
        if ($data) {
0 ignored issues
show
introduced by
The condition $data is always false.
Loading history...
427
            $this->parseTraktTv($data);
428
            if (! empty($data['trailer'])) {
429
                return $data['trailer'];
430
            }
431
        }
432
433
        $trailer = Utility::imdb_trailers($imdbID);
434
        if ($trailer) {
435
            MovieInfo::query()->where('imdbid', $imdbID)->update(['trailer' => $trailer]);
436
437
            return $trailer;
438
        }
439
440
        return false;
441
    }
442
443
    /**
444
     * Parse trakt info, insert into DB.
445
     *
446
     * @param array $data
447
     *
448
     * @return mixed
449
     */
450
    public function parseTraktTv(&$data)
451
    {
452
        if (empty($data['ids']['imdb'])) {
453
            return false;
454
        }
455
456
        if (! empty($data['trailer'])) {
457
            $data['trailer'] = str_ireplace(
458
                'http://',
459
                'https://',
460
                str_ireplace('watch?v=', 'embed/', $data['trailer'])
461
            );
462
463
            return $data['trailer'];
464
        }
465
        $imdbid = (strpos($data['ids']['imdb'], 'tt') === 0) ? substr($data['ids']['imdb'], 2) : $data['ids']['imdb'];
466
        $cover = 0;
467
        if (is_file($this->imgSavePath.$imdbid).'-cover.jpg') {
468
            $cover = 1;
469
        }
470
471
        return $this->update([
472
            'genres'   => $this->checkTraktValue($data['genres']),
473
            'imdbid'   => $this->checkTraktValue($imdbid),
474
            'language' => $this->checkTraktValue($data['language']),
475
            'plot'     => $this->checkTraktValue($data['overview']),
476
            'rating'   => round($this->checkTraktValue($data['rating']), 1),
0 ignored issues
show
Bug introduced by
$this->checkTraktValue($data['rating']) of type string is incompatible with the type double expected by parameter $val of round(). ( Ignorable by Annotation )

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

476
            'rating'   => round(/** @scrutinizer ignore-type */ $this->checkTraktValue($data['rating']), 1),
Loading history...
477
            'tagline'  => $this->checkTraktValue($data['tagline']),
478
            'title'    => $this->checkTraktValue($data['title']),
479
            'tmdbid'   => $this->checkTraktValue($data['ids']['tmdb']),
480
            'trailer'  => $this->checkTraktValue($data['trailer']),
481
            'cover'    => $cover,
482
            'year'     => $this->checkTraktValue($data['year']),
483
        ]);
484
    }
485
486
    /**
487
     * Checks if the value is set and not empty, returns it, else empty string.
488
     *
489
     * @param mixed $value
490
     *
491
     * @return string
492
     */
493
    private function checkTraktValue($value): string
494
    {
495
        if (\is_array($value) && ! empty($value)) {
496
            $temp = '';
497
            foreach ($value as $val) {
498
                if (! \is_array($val) && ! \is_object($val)) {
499
                    $temp .= (string) $val;
500
                }
501
            }
502
            $value = $temp;
503
        }
504
505
        return ! empty($value) ? $value : '';
506
    }
507
508
    /**
509
     * Get array of column keys, for inserting / updating.
510
     *
511
     * @return array
512
     */
513
    public function getColumnKeys(): array
514
    {
515
        return [
516
            'actors', 'backdrop', 'cover', 'director', 'genre', 'imdbid', 'language',
517
            'plot', 'rating', 'rtrating', 'tagline', 'title', 'tmdbid', 'trailer', 'type', 'year',
518
        ];
519
    }
520
521
    /**
522
     * Update movie on movie-edit page.
523
     *
524
     * @param array $values Array of keys/values to update. See $validKeys
525
     *
526
     * @return int|bool
527
     */
528
    public function update(array $values)
529
    {
530
        if (! \count($values)) {
531
            return false;
532
        }
533
534
        $validKeys = $this->getColumnKeys();
535
536
        $query = [
537
            '0' => 'INSERT INTO movieinfo (updated_at, created_at, ',
538
            '1' => ' VALUES (NOW(), NOW(), ',
539
            '2' => 'ON DUPLICATE KEY UPDATE updated_at = NOW(), ',
540
        ];
541
        $found = 0;
542
        foreach ($values as $key => $value) {
543
            if (! empty($value) && \in_array($key, $validKeys, false)) {
544
                $found++;
545
                $query[0] .= "$key, ";
546
                if (\in_array($key, ['genre', 'language'], false)) {
547
                    $value = substr($value, 0, 64);
548
                }
549
                $value = $this->pdo->escapeString($value);
550
                $query[1] .= "$value, ";
551
                $query[2] .= "$key = $value, ";
552
            }
553
        }
554
        if (! $found) {
555
            return false;
556
        }
557
        foreach ($query as $key => $value) {
558
            $query[$key] = rtrim($value, ', ');
559
        }
560
561
        return $this->pdo->queryInsert($query[0].') '.$query[1].') '.$query[2]);
562
    }
563
564
    /**
565
     * Returns a tmdb, imdb or trakt variable, the one that is set. Empty string if both not set.
566
     *
567
     * @param string $variable1
568
     * @param string $variable2
569
     * @param string $variable3
570
     * @param $variable4
571
     *
572
     * @return array|string
573
     */
574
    protected function setVariables($variable1, $variable2, $variable3, $variable4)
575
    {
576
        if (! empty($variable1)) {
577
            return $variable1;
578
        }
579
        if (! empty($variable2)) {
580
            return $variable2;
581
        }
582
        if (! empty($variable3)) {
583
            return $variable3;
584
        }
585
        if (! empty($variable4)) {
586
            return $variable4;
587
        }
588
589
        return '';
590
    }
591
592
    /**
593
     * Fetch IMDB/TMDB/TRAKT info for the movie.
594
     *
595
     * @param $imdbId
596
     *
597
     * @return bool
598
     * @throws \Exception
599
     */
600
    public function updateMovieInfo($imdbId): bool
601
    {
602
        if ($this->echooutput && $this->service !== '') {
603
            ColorCLI::doEcho(ColorCLI::primary('Fetching IMDB info from TMDB/IMDB/Trakt/OMDB using IMDB id: '.$imdbId), true);
604
        }
605
606
        // Check TMDB for IMDB info.
607
        $tmdb = $this->fetchTMDBProperties($imdbId);
608
609
        // Check IMDB for movie info.
610
        $imdb = $this->fetchIMDBProperties($imdbId);
611
612
        // Check TRAKT for movie info
613
        $trakt = $this->fetchTraktTVProperties($imdbId);
614
615
        // Check OMDb for movie info
616
        $omdb = $this->fetchOmdbAPIProperties($imdbId);
617
        if (! $imdb && ! $tmdb && ! $trakt && ! $omdb) {
618
            return false;
619
        }
620
621
        // Check FanArt.tv for cover and background images.
622
        $fanart = $this->fetchFanartTVProperties($imdbId);
623
624
        $mov = [];
625
626
        $mov['cover'] = $mov['backdrop'] = $mov['banner'] = $movieID = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $movieID is dead and can be removed.
Loading history...
627
        $mov['type'] = $mov['director'] = $mov['actors'] = $mov['language'] = '';
628
629
        $mov['imdbid'] = $imdbId;
630
        $mov['tmdbid'] = (! isset($tmdb['tmdbid']) || $tmdb['tmdbid'] === '') ? 0 : $tmdb['tmdbid'];
631
632
        // Prefer Fanart.tv cover over TMDB,TMDB over IMDB and IMDB over OMDB.
633
        if (! empty($fanart['cover'])) {
634
            $mov['cover'] = $this->releaseImage->saveImage($imdbId.'-cover', $fanart['cover'], $this->imgSavePath);
635
        } elseif (! empty($tmdb['cover'])) {
636
            $mov['cover'] = $this->releaseImage->saveImage($imdbId.'-cover', $tmdb['cover'], $this->imgSavePath);
637
        } elseif (! empty($imdb['cover'])) {
638
            $mov['cover'] = $this->releaseImage->saveImage($imdbId.'-cover', $imdb['cover'], $this->imgSavePath);
639
        } elseif (! empty($omdb['cover'])) {
640
            $mov['cover'] = $this->releaseImage->saveImage($imdbId.'-cover', $omdb['cover'], $this->imgSavePath);
641
        }
642
643
        // Backdrops.
644
        if (! empty($fanart['backdrop'])) {
645
            $mov['backdrop'] = $this->releaseImage->saveImage($imdbId.'-backdrop', $fanart['backdrop'], $this->imgSavePath, 1920, 1024);
646
        } elseif (! empty($tmdb['backdrop'])) {
647
            $mov['backdrop'] = $this->releaseImage->saveImage($imdbId.'-backdrop', $tmdb['backdrop'], $this->imgSavePath, 1920, 1024);
648
        }
649
650
        // Banner
651
        if (! empty($fanart['banner'])) {
652
            $mov['banner'] = $this->releaseImage->saveImage($imdbId.'-banner', $fanart['banner'], $this->imgSavePath);
653
        }
654
655
        //RottenTomatoes rating from OmdbAPI
656
        if (! empty($omdb['rtRating'])) {
657
            $mov['rtrating'] = $omdb['rtRating'];
658
        }
659
660
        $mov['title'] = $this->setVariables($imdb['title'], $tmdb['title'], $trakt['title'], $omdb['title']);
661
        $mov['rating'] = $this->setVariables($imdb['rating'], $tmdb['rating'], $trakt['rating'], $omdb['rating']);
662
        $mov['plot'] = $this->setVariables($imdb['plot'], $tmdb['plot'], $trakt['overview'], $omdb['plot']);
663
        $mov['tagline'] = $this->setVariables($imdb['tagline'], $tmdb['tagline'], $trakt['tagline'], $omdb['tagline']);
664
        $mov['year'] = $this->setVariables($imdb['year'], $tmdb['year'], $trakt['year'], $omdb['year']);
665
        $mov['genre'] = $this->setVariables($imdb['genre'], $tmdb['genre'], $trakt['genres'], $omdb['genre']);
666
667
        if (! empty($imdb['type'])) {
668
            $mov['type'] = $imdb['type'];
669
        }
670
671
        if (! empty($imdb['director'])) {
672
            $mov['director'] = \is_array($imdb['director']) ? implode(', ', array_unique($imdb['director'])) : $imdb['director'];
673
        } elseif (! empty($omdb['director'])) {
674
            $mov['director'] = \is_array($omdb['director']) ? implode(', ', array_unique($omdb['director'])) : $omdb['director'];
675
        }
676
677
        if (! empty($imdb['actors'])) {
678
            $mov['actors'] = \is_array($imdb['actors']) ? implode(', ', array_unique($imdb['actors'])) : $imdb['actors'];
679
        } elseif (! empty($omdb['actors'])) {
680
            $mov['actors'] = \is_array($omdb['actors']) ? implode(', ', array_unique($omdb['actors'])) : $omdb['actors'];
681
        }
682
683
        if (! empty($imdb['language'])) {
684
            $mov['language'] = \is_array($imdb['language']) ? implode(', ', array_unique($imdb['language'])) : $imdb['language'];
685
        } elseif (! empty($omdb['language'])) {
686
            $mov['language'] = \is_array($imdb['language']) ? implode(', ', array_unique($omdb['language'])) : $omdb['language'];
687
        }
688
689
        if (\is_array($mov['genre'])) {
690
            $mov['genre'] = implode(', ', array_unique($mov['genre']));
691
        }
692
693
        if (\is_array($mov['type'])) {
694
            $mov['type'] = implode(', ', array_unique($mov['type']));
695
        }
696
697
        $mov['title'] = html_entity_decode($mov['title'], ENT_QUOTES, 'UTF-8');
698
699
        $mov['title'] = str_replace(['/', '\\'], '', $mov['title']);
700
        $movieID = $this->update([
701
            'actors'    => html_entity_decode($mov['actors'], ENT_QUOTES, 'UTF-8'),
702
            'backdrop'  => $mov['backdrop'],
703
            'cover'     => $mov['cover'],
704
            'director'  => html_entity_decode($mov['director'], ENT_QUOTES, 'UTF-8'),
705
            'genre'     => html_entity_decode($mov['genre'], ENT_QUOTES, 'UTF-8'),
706
            'imdbid'    => $mov['imdbid'],
707
            'language'  => html_entity_decode($mov['language'], ENT_QUOTES, 'UTF-8'),
708
            'plot'      => html_entity_decode(preg_replace('/\s+See full summary »/u', ' ', $mov['plot']), ENT_QUOTES, 'UTF-8'),
709
            'rating'    => round($mov['rating'], 1),
710
            'rtrating' => $mov['rtrating'] ?? 'N/A',
711
            'tagline'   => html_entity_decode($mov['tagline'], ENT_QUOTES, 'UTF-8'),
712
            'title'     => $mov['title'],
713
            'tmdbid'    => $mov['tmdbid'],
714
            'type'      => html_entity_decode(ucwords(preg_replace('/[\.\_]/', ' ', $mov['type'])), ENT_QUOTES, 'UTF-8'),
715
            'year'      => $mov['year'],
716
        ]);
717
718
        if ($this->echooutput && $this->service !== '') {
719
            ColorCLI::doEcho(
720
                ColorCLI::headerOver(($movieID !== 0 ? 'Added/updated movie: ' : 'Nothing to update for movie: ')).
0 ignored issues
show
introduced by
The condition $movieID !== 0 is always true.
Loading history...
721
                ColorCLI::primary(
722
                    $mov['title'].
723
                    ' ('.
724
                    $mov['year'].
725
                    ') - '.
726
                    $mov['imdbid']
727
                ), true
728
            );
729
        }
730
731
        return $movieID !== 0;
732
    }
733
734
    /**
735
     * Fetch FanArt.tv backdrop / cover / title.
736
     *
737
     * @param $imdbId
738
     *
739
     * @return bool|array
740
     */
741
    protected function fetchFanartTVProperties($imdbId)
742
    {
743
        if ($this->fanartapikey !== '') {
744
            $art = $this->fanart->getMovieFanart('tt'.$imdbId);
745
746
            if ($art !== null && $art !== false) {
747
                if (isset($art['status']) && $art['status'] === 'error') {
748
                    return false;
749
                }
750
                $ret = [];
751
                if (! empty($art['moviebackground'][0]['url'])) {
752
                    $ret['backdrop'] = $art['moviebackground'][0]['url'];
753
                } elseif (! empty($art['moviethumb'][0]['url'])) {
754
                    $ret['backdrop'] = $art['moviethumb'][0]['url'];
755
                }
756
                if (! empty($art['movieposter'][0]['url'])) {
757
                    $ret['cover'] = $art['movieposter'][0]['url'];
758
                }
759
                if (! empty($art['moviebanner'][0]['url'])) {
760
                    $ret['banner'] = $art['moviebanner'][0]['url'];
761
                }
762
763
                if (isset($ret['backdrop'], $ret['cover'])) {
764
                    $ret['title'] = $imdbId;
765
                    if (isset($art['name'])) {
766
                        $ret['title'] = $art['name'];
767
                    }
768
                    if ($this->echooutput) {
769
                        ColorCLI::doEcho(ColorCLI::alternateOver('Fanart Found ').ColorCLI::headerOver($ret['title']), true);
770
                    }
771
772
                    return $ret;
773
                }
774
            }
775
        }
776
777
        return false;
778
    }
779
780
    /**
781
     * Fetch info for IMDB id from TMDB.
782
     *
783
     *
784
     * @param      $imdbId
785
     * @param bool $text
786
     *
787
     * @return array|bool
788
     */
789
    public function fetchTMDBProperties($imdbId, $text = false)
790
    {
791
        $lookupId = $text === false && \strlen($imdbId) === 7 ? 'tt'.$imdbId : $imdbId;
792
793
        try {
794
            $tmdbLookup = $this->tmdbclient->getMoviesApi()->getMovie($lookupId);
795
        } catch (TmdbApiException $error) {
796
            ColorCLI::doEcho(ColorCLI::error($error->getMessage()), true);
797
798
            return false;
799
        }
800
801
        if (! empty($tmdbLookup)) {
802
            if ($this->currentTitle !== '') {
803
                // Check the similarity.
804
                similar_text($this->currentTitle, $tmdbLookup['title'], $percent);
805
                if ($percent < self::MATCH_PERCENT) {
806
                    return false;
807
                }
808
            }
809
810
            if ($this->currentYear !== '') {
811
                // Check the similarity.
812
                similar_text($this->currentYear, Carbon::parse($tmdbLookup['release_date'])->year, $percent);
813
                if ($percent < self::YEAR_MATCH_PERCENT) {
814
                    return false;
815
                }
816
            }
817
818
            $ret = [];
819
            $ret['title'] = $tmdbLookup['title'];
820
821
            $ret['tmdbid'] = $tmdbLookup['id'];
822
            $ImdbID = str_replace('tt', '', $tmdbLookup['imdb_id']);
823
            $ret['imdbid'] = $ImdbID;
824
            $vote = $tmdbLookup['vote_average'];
825
            if ($vote !== null) {
826
                $ret['rating'] = ((int) $vote === 0) ? '' : $vote;
827
            } else {
828
                $ret['rating'] = '';
829
            }
830
            $overview = $tmdbLookup['overview'];
831
            if (! empty($overview)) {
832
                $ret['plot'] = $overview;
833
            } else {
834
                $ret['plot'] = '';
835
            }
836
            $tagline = $tmdbLookup['tagline'];
837
            if (! empty($tagline)) {
838
                $ret['tagline'] = $tagline;
839
            } else {
840
                $ret['tagline'] = '';
841
            }
842
            $released = $tmdbLookup['release_date'];
843
            if (! empty($released)) {
844
                $ret['year'] = Carbon::parse($released)->year;
845
            } else {
846
                $ret['year'] = '';
847
            }
848
            $genresa = $tmdbLookup['genres'];
849
            if (! empty($genresa) && \count($genresa) > 0) {
850
                $genres = [];
851
                foreach ($genresa as $genre) {
852
                    $genres[] = $genre['name'];
853
                }
854
                $ret['genre'] = $genres;
855
            } else {
856
                $ret['genre'] = '';
857
            }
858
            $posterp = $tmdbLookup['poster_path'];
859
            if (! empty($posterp)) {
860
                $ret['cover'] = 'https:'.$this->helper->getUrl($posterp);
861
            } else {
862
                $ret['cover'] = '';
863
            }
864
            $backdrop = $tmdbLookup['backdrop_path'];
865
            if (! empty($backdrop)) {
866
                $ret['backdrop'] = 'https:'.$this->helper->getUrl($backdrop);
867
            } else {
868
                $ret['backdrop'] = '';
869
            }
870
            if ($this->echooutput) {
871
                ColorCLI::doEcho(ColorCLI::primaryOver('TMDb Found ').ColorCLI::headerOver($ret['title']), true);
872
            }
873
874
            return $ret;
875
        }
876
877
        return false;
878
    }
879
880
    /**
881
     * @param $imdbId
882
     *
883
     * @return array|bool
884
     */
885
    public function fetchIMDBProperties($imdbId)
886
    {
887
        $result = new Title($imdbId, $this->config);
888
        if (! empty($result->title())) {
889
            similar_text($this->currentTitle, $result->title(), $percent);
890
            if ($percent > self::MATCH_PERCENT) {
891
                similar_text($this->currentYear, $result->year(), $percent);
892
                if ($percent >= self::YEAR_MATCH_PERCENT) {
893
                    $ret = [
894
                        'title' => $result->title(),
895
                        'tagline' => $result->tagline(),
896
                        'plot' => array_get($result->plot_split(), '0.plot'),
897
                        'rating' => $result->rating(),
898
                        'year' => $result->year(),
899
                        'cover' => $result->photo(),
900
                        'genre' => $result->genre(),
901
                        'language' => $result->language(),
902
                        'type' => $result->movietype(),
903
                    ];
904
905
                    if ($this->echooutput) {
906
                        ColorCLI::doEcho(ColorCLI::headerOver('IMDb Found ').ColorCLI::primaryOver($result->title()), true);
907
                    }
908
909
                    return $ret;
910
                }
911
912
                return false;
913
            }
914
915
            return false;
916
        }
917
918
        return false;
919
    }
920
921
    /**
922
     * Fetch TraktTV backdrop / cover / title.
923
     *
924
     * @param $imdbId
925
     *
926
     * @return bool|array
927
     * @throws \Exception
928
     */
929
    protected function fetchTraktTVProperties($imdbId)
930
    {
931
        if ($this->traktTv === null) {
932
            $this->traktTv = new TraktTv(['Settings' => $this->pdo]);
933
        }
934
        $resp = $this->traktTv->client->movieSummary('tt'.$imdbId, 'full');
935
        if ($resp !== false) {
1 ignored issue
show
introduced by
The condition $resp !== false is always false.
Loading history...
936
            similar_text($this->currentTitle, $resp['title'], $percent);
937
            if ($percent > self::MATCH_PERCENT) {
938
                similar_text($this->currentYear, $resp['year'], $percent);
939
                if ($percent >= self::YEAR_MATCH_PERCENT) {
940
                    $ret = [];
941
                    if (isset($resp['ids']['trakt'])) {
942
                        $ret['id'] = $resp['ids']['trakt'];
943
                    }
944
945
                    if (isset($resp['title'])) {
946
                        $ret['title'] = $resp['title'];
947
                    } else {
948
                        return false;
949
                    }
950
                    if ($this->echooutput) {
951
                        ColorCLI::doEcho(ColorCLI::alternateOver('Trakt Found ').ColorCLI::headerOver($ret['title']), true);
952
                    }
953
954
                    return $ret;
955
                }
956
957
                return false;
958
            }
959
960
            return false;
961
        }
962
963
        return false;
964
    }
965
966
    /**
967
     * Fetch OMDb backdrop / cover / title.
968
     *
969
     * @param $imdbId
970
     *
971
     * @return bool|array
972
     */
973
    protected function fetchOmdbAPIProperties($imdbId)
974
    {
975
        if ($this->omdbapikey !== null) {
976
            $resp = $this->omdbApi->fetch('i', 'tt'.$imdbId);
0 ignored issues
show
Bug introduced by
The method fetch() does not exist on null. ( Ignorable by Annotation )

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

976
            /** @scrutinizer ignore-call */ 
977
            $resp = $this->omdbApi->fetch('i', 'tt'.$imdbId);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
977
978
            if (\is_object($resp) && $resp->message === 'OK' && $resp->data->Response !== 'False') {
0 ignored issues
show
introduced by
The condition is_object($resp) is always false.
Loading history...
979
                similar_text($this->currentTitle, $resp->data->Title, $percent);
980
                if ($percent > self::MATCH_PERCENT) {
981
                    similar_text($this->currentYear, $resp->data->Year, $percent);
982
                    if ($percent >= self::YEAR_MATCH_PERCENT) {
983
                        $ret = [
984
                            'title' => $resp->data->Title ?? '',
985
                            'cover' => $resp->data->Poster ?? '',
986
                            'genre' => $resp->data->Genre ?? '',
987
                            'year' => $resp->data->Year ?? '',
988
                            'plot' => $resp->data->Plot ?? '',
989
                            'rating' => $resp->data->imdbRating ?? '',
990
                            'rtRating' => $resp->data->Ratings[1]->Value ?? '',
991
                            'tagline' => $resp->data->Tagline ?? '',
992
                            'director' => $resp->data->Director ?? '',
993
                            'actors' => $resp->data->Actors ?? '',
994
                            'language' => $resp->data->Language ?? '',
995
                            'boxOffice' => $resp->data->BoxOffice ?? '',
996
                        ];
997
998
                        if ($this->echooutput) {
999
                            ColorCLI::doEcho(ColorCLI::alternateOver('OMDbAPI Found ').ColorCLI::headerOver($ret['title']), true);
1000
                        }
1001
1002
                        return $ret;
1003
                    }
1004
1005
                    return false;
1006
                }
1007
1008
                return false;
1009
            }
1010
1011
            return false;
1012
        }
1013
1014
        return false;
1015
    }
1016
1017
    /**
1018
     * Update a release with a IMDB id.
1019
     *
1020
     * @param string $buffer Data to parse a IMDB id/Trakt Id from.
1021
     * @param string $service Method that called this method.
1022
     * @param int $id id of the release.
1023
     * @param int $processImdb To get IMDB info on this IMDB id or not.
1024
     *
1025
     * @return string
1026
     * @throws \Exception
1027
     */
1028
    public function doMovieUpdate($buffer, $service, $id, $processImdb = 1): string
1029
    {
1030
        $imdbID = false;
1031
        if (\is_string($buffer) && preg_match('/(?:imdb.*?)?(?:tt|Title\?)(?P<imdbid>\d{5,7})/i', $buffer, $matches)) {
1032
            $imdbID = $matches['imdbid'];
1033
        }
1034
1035
        if ($imdbID !== false) {
1036
            $this->service = $service;
1037
            if ($this->echooutput && $this->service !== '') {
1038
                ColorCLI::doEcho(ColorCLI::headerOver($service.' found IMDBid: ').ColorCLI::primary('tt'.$imdbID), true);
1039
            }
1040
1041
            Release::query()->where('id', $id)->update(['imdbid' => $imdbID]);
1042
1043
            // If set, scan for imdb info.
1044
            if ($processImdb === 1) {
1045
                $movCheck = $this->getMovieInfo($imdbID);
1046
                if ($movCheck === false || (isset($movCheck['updated_at']) && (time() - strtotime($movCheck['updated_at'])) > 2592000)) {
1047
                    if ($this->updateMovieInfo($imdbID) === false) {
1048
                        Release::query()->where('id', $id)->update(['imdbid' => 0000000]);
1049
                    }
1050
                }
1051
            }
1052
        }
1053
1054
        return $imdbID;
1055
    }
1056
1057
    /**
1058
     * Process releases with no IMDB id's.
1059
     *
1060
     *
1061
     * @param string $groupID
1062
     * @param string $guidChar
1063
     * @param int $lookupIMDB
1064
     * @throws \Exception
1065
     */
1066
    public function processMovieReleases($groupID = '', $guidChar = '', $lookupIMDB = 1): void
1067
    {
1068
        if ($lookupIMDB === 0) {
1069
            return;
1070
        }
1071
1072
        // Get all releases without an IMDB id.
1073
        $sql = Release::query()
1074
            ->whereBetween('categories_id', [Category::MOVIE_ROOT, Category::MOVIE_OTHER])
1075
            ->whereNull('imdbid')
1076
            ->where('nzbstatus', '=', 1);
1077
        if ($groupID !== '') {
1078
            $sql->where('groups_id', $groupID);
1079
        }
1080
1081
        if ($guidChar !== '') {
1082
            $sql->where('leftguid', $guidChar);
1083
        }
1084
1085
        if ((int) $lookupIMDB === 2) {
1086
            $sql->where('isrenamed', '=', 1);
1087
        }
1088
1089
        $res = $sql->limit($this->movieqty)->get(['searchname', 'id'])->toArray();
1090
1091
        $movieCount = \count($res);
1092
1093
        if ($movieCount > 0) {
1094
            if ($this->traktTv === null) {
1095
                $this->traktTv = new TraktTv(['Settings' => $this->pdo]);
1096
            }
1097
            if ($this->echooutput && $movieCount > 1) {
1098
                ColorCLI::doEcho(ColorCLI::header('Processing '.$movieCount.' movie releases.'), true);
1099
            }
1100
1101
            // Loop over releases.
1102
            foreach ($res as $arr) {
1103
                // Try to get a name/year.
1104
                if ($this->parseMovieSearchName($arr['searchname']) === false) {
0 ignored issues
show
Bug introduced by
It seems like $arr['searchname'] can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $releaseName of Blacklight\Movie::parseMovieSearchName() does only seem to accept string, 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

1104
                if ($this->parseMovieSearchName(/** @scrutinizer ignore-type */ $arr['searchname']) === false) {
Loading history...
1105
                    //We didn't find a name, so set to all 0's so we don't parse again.
1106
                    Release::query()->where('id', $arr['id'])->update(['imdbid' => 0000000]);
1107
                    continue;
1108
                }
1109
                $this->currentRelID = $arr['id'];
1110
1111
                $movieName = $this->currentTitle;
1112
                if ($this->currentYear !== false) {
1113
                    $movieName .= ' ('.$this->currentYear.')';
1114
                }
1115
1116
                if ($this->echooutput) {
1117
                    ColorCLI::doEcho(ColorCLI::primaryOver('Looking up: ').ColorCLI::headerOver($movieName), true);
1118
                }
1119
1120
                $movieUpdated = false;
1121
1122
                // Check local DB.
1123
                $getIMDBid = $this->localIMDBSearch();
1124
1125
                if ($getIMDBid !== false) {
1126
                    $imdbID = $this->doMovieUpdate('tt'.$getIMDBid, 'Local DB', $arr['id']);
1127
                    if ($imdbID !== false) {
1128
                        $movieUpdated = true;
1129
                    }
1130
                }
1131
1132
                // Check on OMDbAPI
1133
                if ($movieUpdated === false) {
1134
                    $omdbTitle = strtolower(str_replace(' ', '_', $this->currentTitle));
1135
                    if ($this->omdbapikey !== null) {
1136
                        $buffer = $this->omdbApi->search($omdbTitle, 'movie');
1137
1138
                        if (\is_object($buffer) && $buffer->message === 'OK' && $buffer->data->Response === 'True') {
1139
                            $getIMDBid = $buffer->data->Search[0]->imdbID;
1140
1141
                            if (! empty($getIMDBid)) {
1142
                                $imdbID = $this->doMovieUpdate($getIMDBid, 'OMDbAPI', $arr['id']);
1143
                                if ($imdbID !== false) {
1144
                                    $movieUpdated = true;
1145
                                }
1146
                            }
1147
                        }
1148
                    }
1149
                }
1150
1151
                // Check on Trakt.
1152
                if ($movieUpdated === false) {
1153
                    $data = $this->traktTv->client->movieSummary($movieName, 'full');
1154
                    if ($data !== false) {
1155
                        $this->parseTraktTv($data);
1156
                        if (! empty($data['ids']['imdb'])) {
1157
                            $imdbID = $this->doMovieUpdate($data['ids']['imdb'], 'Trakt', $arr['id']);
1158
                            if ($imdbID !== false) {
1159
                                $movieUpdated = true;
1160
                            }
1161
                        }
1162
                    }
1163
                }
1164
1165
                // Check on The Movie Database.
1166
                if ($movieUpdated === false) {
1167
                    $data = $this->tmdbclient->getSearchApi()->searchMovies($this->currentTitle);
1168
                    if ($data['total_results'] > 0) {
1169
                        if (! empty($data['results'])) {
1170
                            foreach ($data['results'] as $result) {
1171
                                if (! empty($result['id'])) {
1172
                                    similar_text($this->currentYear, Carbon::parse($result['release_date'])->year, $percent);
1173
                                    if ($percent > 80) {
1174
                                        $ret = $this->fetchTMDBProperties($result['id'], true);
1175
                                        if ($ret !== false) {
1176
                                            $imdbID = $this->doMovieUpdate('tt'.$ret['imdbid'], 'TMDB', $arr['id']);
1177
                                            if ($imdbID !== false) {
1178
                                                $movieUpdated = true;
1179
                                            }
1180
                                        }
1181
                                    }
1182
                                } else {
1183
                                    $movieUpdated = false;
1184
                                }
1185
                            }
1186
                        } else {
1187
                            $movieUpdated = false;
1188
                        }
1189
                    } else {
1190
                        $movieUpdated = false;
1191
                    }
1192
                }
1193
1194
                // We failed to get an IMDB id from all sources.
1195
                if ($movieUpdated === false) {
1196
                    Release::query()->where('id', $arr['id'])->update(['imdbid' => 0000000]);
1197
                }
1198
            }
1199
        }
1200
    }
1201
1202
    /**
1203
     * @return bool|mixed
1204
     */
1205
    protected function localIMDBSearch()
1206
    {
1207
        //If we found a year, try looking in a 4 year range.
1208
        $check = MovieInfo::query()
1209
            ->where('title', 'LIKE', '%'.$this->currentTitle.'%');
1210
1211
        if ($this->currentYear !== false) {
0 ignored issues
show
introduced by
The condition $this->currentYear !== false is always true.
Loading history...
1212
            $start = Carbon::parse($this->currentYear)->subYears(2)->year;
1213
            $end = Carbon::parse($this->currentYear)->addYears(2)->year;
1214
            $check->whereBetween('year', [$start, $end]);
1215
        }
1216
        $IMDBCheck = $check->first(['imdbid']);
1217
1218
        return $IMDBCheck === null ? false : $IMDBCheck->imdbid;
1219
    }
1220
1221
    /**
1222
     * Parse a movie name from a release search name.
1223
     *
1224
     * @param string $releaseName
1225
     *
1226
     * @return bool
1227
     */
1228
    protected function parseMovieSearchName($releaseName): bool
1229
    {
1230
        $name = $year = '';
1231
        $followingList = '[^\w]((1080|480|720)p|AC3D|Directors([^\w]CUT)?|DD5\.1|(DVD|BD|BR)(Rip)?|BluRay|divx|HDTV|iNTERNAL|LiMiTED|(Real\.)?Proper|RE(pack|Rip)|Sub\.?(fix|pack)|Unrated|WEB-DL|(x|H)[-._ ]?264|xvid)[^\w]';
1232
1233
        /* Initial scan of getting a year/name.
1234
         * [\w. -]+ Gets 0-9a-z. - characters, most scene movie titles contain these chars.
1235
         * ie: [61420]-[FULL]-[a.b.foreignEFNet]-[ Coraline.2009.DUTCH.INTERNAL.1080p.BluRay.x264-VeDeTT ]-[21/85] - "vedett-coralien-1080p.r04" yEnc
1236
         * Then we look up the year, (19|20)\d\d, so $matches[1] would be Coraline $matches[2] 2009
1237
         */
1238
        if (preg_match('/(?P<name>[\w. -]+)[^\w](?P<year>(19|20)\d\d)/i', $releaseName, $matches)) {
1239
            $name = $matches['name'];
1240
            $year = $matches['year'];
1241
1242
        /* If we didn't find a year, try to get a name anyways.
1243
         * Try to look for a title before the $followingList and after anything but a-z0-9 two times or more (-[ for example)
1244
         */
1245
        } elseif (preg_match('/([^\w]{2,})?(?P<name>[\w .-]+?)'.$followingList.'/i', $releaseName, $matches)) {
1246
            $name = $matches['name'];
1247
        }
1248
1249
        // Check if we got something.
1250
        if ($name !== '') {
1251
1252
            // If we still have any of the words in $followingList, remove them.
1253
            $name = preg_replace('/'.$followingList.'/i', ' ', $name);
1254
            // Remove periods, underscored, anything between parenthesis.
1255
            $name = preg_replace('/\(.*?\)|[._]/i', ' ', $name);
1256
            // Finally remove multiple spaces and trim leading spaces.
1257
            $name = trim(preg_replace('/\s{2,}/', ' ', $name));
1258
            // Check if the name is long enough and not just numbers.
1259
            if (\strlen($name) > 4 && ! preg_match('/^\d+$/', $name)) {
1260
                $this->currentTitle = $name;
1261
                $this->currentYear = ($year === '' ? false : $year);
0 ignored issues
show
Documentation Bug introduced by
It seems like $year === '' ? false : $year can also be of type false. However, the property $currentYear is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1262
1263
                return true;
1264
            }
1265
        }
1266
1267
        return false;
1268
    }
1269
1270
    /**
1271
     * Get IMDB genres.
1272
     *
1273
     * @return array
1274
     */
1275
    public function getGenres(): array
1276
    {
1277
        return [
1278
            'Action',
1279
            'Adventure',
1280
            'Animation',
1281
            'Biography',
1282
            'Comedy',
1283
            'Crime',
1284
            'Documentary',
1285
            'Drama',
1286
            'Family',
1287
            'Fantasy',
1288
            'Film-Noir',
1289
            'Game-Show',
1290
            'History',
1291
            'Horror',
1292
            'Music',
1293
            'Musical',
1294
            'Mystery',
1295
            'News',
1296
            'Reality-TV',
1297
            'Romance',
1298
            'Sci-Fi',
1299
            'Sport',
1300
            'Talk-Show',
1301
            'Thriller',
1302
            'War',
1303
            'Western',
1304
        ];
1305
    }
1306
}
1307