Passed
Push — master ( 392926...b4a664 )
by Darko
13:01
created

MovieBrowseService   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 30
eloc 117
c 1
b 0
f 0
dl 0
loc 167
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getGenres() 0 29 1
A getMovieOrder() 0 11 4
A __construct() 0 3 1
F getMovieRange() 0 76 17
A getMovieOrdering() 0 3 1
A getBrowseBy() 0 19 6
1
<?php
2
3
namespace App\Services;
4
5
use App\Models\Category;
6
use App\Models\MovieInfo;
7
use App\Models\Release;
8
use Illuminate\Support\Facades\Cache;
9
use Illuminate\Support\Facades\DB;
10
11
/**
12
 * Service class for movie browsing operations (frontend).
13
 */
14
class MovieBrowseService
15
{
16
    protected string $showPasswords;
17
18
    public function __construct()
19
    {
20
        $this->showPasswords = app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords();
21
    }
22
23
    /**
24
     * Get movie releases with covers for movie browse page.
25
     */
26
    public function getMovieRange(int $page, array $cat, int $start, int $num, string $orderBy, int $maxAge = -1, array $excludedCats = []): mixed
27
    {
28
        $page = max(1, $page);
29
        $start = max(0, $start);
30
        $catsrch = '';
31
        if (count($cat) > 0 && $cat[0] !== -1) {
32
            $catsrch = Category::getCategorySearch($cat);
33
        }
34
        $order = $this->getMovieOrder($orderBy);
35
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium'));
36
        $whereAge = $maxAge > 0 ? 'AND r.postdate > NOW() - INTERVAL '.$maxAge.' DAY ' : '';
37
        $whereExcluded = count($excludedCats) > 0 ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : '';
38
        $limitClause = $start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start;
39
        $moviesSql = "SELECT SQL_CALC_FOUND_ROWS m.imdbid, GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_id "
40
            ."FROM movieinfo m LEFT JOIN releases r USING (imdbid) WHERE m.title != '' AND m.imdbid != '0000000' "
41
            ."AND r.passwordstatus {$this->showPasswords} "
42
            .$this->getBrowseBy().' '
43
            .(! empty($catsrch) ? $catsrch.' ' : '')
44
            .$whereAge
45
            .$whereExcluded.' '
46
            ."GROUP BY m.imdbid ORDER BY {$order[0]} {$order[1]} {$limitClause}";
47
        $movieCache = Cache::get(md5($moviesSql.$page));
48
        if ($movieCache !== null) {
49
            $movies = $movieCache;
50
        } else {
51
            $data = MovieInfo::fromQuery($moviesSql);
52
            $movies = ['total' => DB::select('SELECT FOUND_ROWS() AS total'), 'result' => $data];
53
            Cache::put(md5($moviesSql.$page), $movies, $expiresAt);
54
        }
55
        $movieIDs = $releaseIDs = [];
56
        if (! empty($movies['result'])) {
57
            foreach ($movies['result'] as $id) {
58
                $movieIDs[] = $id->imdbid;
59
                $releaseIDs[] = $id->grp_release_id;
60
            }
61
        }
62
        $inMovieIds = (is_array($movieIDs) && ! empty($movieIDs)) ? implode(',', $movieIDs) : -1;
63
        $inReleaseIds = (is_array($releaseIDs) && ! empty($releaseIDs)) ? implode(',', $releaseIDs) : -1;
64
        $sql = 'SELECT '
65
            ."GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_id, "
66
            ."GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_rarinnerfilecount, "
67
            ."GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_haspreview, "
68
            ."GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_password, "
69
            ."GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_guid, "
70
            ."GROUP_CONCAT(rn.releases_id ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_nfoid, "
71
            ."GROUP_CONCAT(g.name ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_grpname, "
72
            ."GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name, "
73
            ."GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_postdate, "
74
            ."GROUP_CONCAT(r.adddate ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_adddate, "
75
            ."GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_size, "
76
            ."GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_totalparts, "
77
            ."GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_comments, "
78
            ."GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_grabs, "
79
            ."GROUP_CONCAT(df.failed ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_failed, "
80
            ."GROUP_CONCAT(cp.title, ' > ', c.title ORDER BY r.postdate DESC SEPARATOR ',' ) AS grp_release_catname, "
81
            .'m.*, g.name AS group_name, rn.releases_id AS nfoid FROM releases r '
82
            .'LEFT OUTER JOIN usenet_groups g ON g.id = r.groups_id '
83
            .'LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id '
84
            .'LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id '
85
            .'LEFT OUTER JOIN categories c ON c.id = r.categories_id '
86
            .'LEFT OUTER JOIN root_categories cp ON cp.id = c.root_categories_id '
87
            .'INNER JOIN movieinfo m ON m.imdbid = r.imdbid '
88
            ."WHERE m.imdbid IN ($inMovieIds) AND r.id IN ($inReleaseIds) "
89
            .(! empty($catsrch) ? $catsrch.' ' : '')
90
            ."GROUP BY m.imdbid ORDER BY {$order[0]} {$order[1]}";
91
        $return = Cache::get(md5($sql.$page));
92
        if ($return !== null) {
93
            return $return;
94
        }
95
        $return = Release::fromQuery($sql);
96
        if (count($return) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $return can also be of type Illuminate\Database\Eloq...gHasThroughRelationship; however, parameter $value of count() does only seem to accept Countable|array, 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

96
        if (count(/** @scrutinizer ignore-type */ $return) > 0) {
Loading history...
97
            $return[0]->_totalcount = $movies['total'][0]->total ?? 0;
98
        }
99
        Cache::put(md5($sql.$page), $return, $expiresAt);
100
101
        return $return;
102
    }
103
104
    /**
105
     * Get the order type the user requested on the movies page.
106
     */
107
    protected function getMovieOrder(string $orderBy): array
108
    {
109
        $orderArr = explode('_', (($orderBy === '') ? 'MAX(r.postdate)' : $orderBy));
110
        $orderField = match ($orderArr[0]) {
111
            'title' => 'm.title',
112
            'year' => 'm.year',
113
            'rating' => 'm.rating',
114
            default => 'MAX(r.postdate)',
115
        };
116
117
        return [$orderField, isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1]) ? $orderArr[1] : 'desc'];
118
    }
119
120
    /**
121
     * Order types for movies page.
122
     */
123
    public function getMovieOrdering(): array
124
    {
125
        return ['title_asc', 'title_desc', 'year_asc', 'year_desc', 'rating_asc', 'rating_desc'];
126
    }
127
128
    protected function getBrowseBy(): string
129
    {
130
        $browseBy = ' ';
131
        $browseByArr = ['title', 'director', 'actors', 'genre', 'rating', 'year', 'imdb'];
132
        foreach ($browseByArr as $bb) {
133
            if (request()->has($bb) && ! empty(request()->input($bb))) {
134
                $bbv = stripslashes(request()->input($bb));
135
                if ($bb === 'rating') {
136
                    $bbv .= '.';
137
                }
138
                if ($bb === 'imdb') {
139
                    $browseBy .= sprintf(' AND m.imdbid = %d', $bbv);
140
                } else {
141
                    $browseBy .= ' AND m.'.$bb.' '.'LIKE '.escapeString('%'.$bbv.'%');
142
                }
143
            }
144
        }
145
146
        return $browseBy;
147
    }
148
149
    /**
150
     * Get IMDB genres.
151
     */
152
    public function getGenres(): array
153
    {
154
        return [
155
            'Action',
156
            'Adventure',
157
            'Animation',
158
            'Biography',
159
            'Comedy',
160
            'Crime',
161
            'Documentary',
162
            'Drama',
163
            'Family',
164
            'Fantasy',
165
            'Film-Noir',
166
            'Game-Show',
167
            'History',
168
            'Horror',
169
            'Music',
170
            'Musical',
171
            'Mystery',
172
            'News',
173
            'Reality-TV',
174
            'Romance',
175
            'Sci-Fi',
176
            'Sport',
177
            'Talk-Show',
178
            'Thriller',
179
            'War',
180
            'Western',
181
        ];
182
    }
183
}
184
185