Passed
Push — master ( 4f5b3b...1c5d75 )
by Darko
09:48
created

MovieController::showTrending()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 61
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 40
c 0
b 0
f 0
dl 0
loc 61
rs 9.28
cc 1
nc 1
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Http\Controllers;
4
5
use App\Models\Category;
6
use Blacklight\Movie;
7
use Illuminate\Http\Request;
8
9
class MovieController extends BasePageController
10
{
11
    /**
12
     * @throws \Exception
13
     */
14
    public function showMovies(Request $request, string $id = '')
15
    {
16
        $movie = new Movie(['Settings' => $this->settings]);
0 ignored issues
show
Unused Code introduced by
The call to Blacklight\Movie::__construct() has too many arguments starting with array('Settings' => $this->settings). ( Ignorable by Annotation )

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

16
        $movie = /** @scrutinizer ignore-call */ new Movie(['Settings' => $this->settings]);

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.

Loading history...
17
18
        $moviecats = Category::getChildren(Category::MOVIE_ROOT)->map(function ($mcat) {
19
            return ['id' => $mcat->id, 'title' => $mcat->title];
20
        });
21
22
        $category = $request->has('imdb') ? -1 : ($request->input('t', Category::MOVIE_ROOT));
23
        if ($id && $moviecats->pluck('title')->contains($id)) {
24
            $cat = Category::where(['title' => $id, 'root_categories_id' => Category::MOVIE_ROOT])->first(['id']);
25
            $category = $cat->id ?? Category::MOVIE_ROOT;
26
        }
27
28
        $catarray = $category !== -1 ? [$category] : [];
29
30
        $page = $request->input('page', 1);
31
        $offset = ($page - 1) * config('nntmux.items_per_cover_page');
32
33
        $orderby = $request->input('ob', '');
34
        $ordering = $movie->getMovieOrdering();
35
        if (! in_array($orderby, $ordering, false)) {
36
            $orderby = '';
37
        }
38
39
        $rslt = $movie->getMovieRange($page, $catarray, $offset, config('nntmux.items_per_cover_page'), $orderby, -1, $this->userdata->categoryexclusions);
0 ignored issues
show
Bug introduced by
The property categoryexclusions does not seem to exist on App\Models\User.
Loading history...
40
        $results = $this->paginate($rslt ?? [], $rslt[0]->_totalcount ?? 0, config('nntmux.items_per_cover_page'), $page, $request->url(), $request->query());
41
42
        $movies = $results->map(function ($result) {
43
            $result['genre'] = makeFieldLinks($result, 'genre', 'movies');
44
            $result['actors'] = makeFieldLinks($result, 'actors', 'movies');
45
            $result['director'] = makeFieldLinks($result, 'director', 'movies');
46
            $result['languages'] = explode(', ', $result['language']);
47
48
            // Add cover image URL using helper function
49
            $result['cover'] = getReleaseCover($result);
50
51
            return $result;
52
        });
53
54
        $years = range(1903, now()->addYear()->year);
55
        rsort($years);
56
57
        $catname = $category === -1 ? 'All' : Category::find($category) ?? 'All';
58
59
        $this->viewData = array_merge($this->viewData, [
60
            'cpapi' => $this->userdata->cp_api,
61
            'cpurl' => $this->userdata->cp_url,
62
            'catlist' => $moviecats,
63
            'category' => $category,
64
            'categorytitle' => $id,
65
            'title' => stripslashes($request->input('title', '')),
66
            'actors' => stripslashes($request->input('actors', '')),
67
            'director' => stripslashes($request->input('director', '')),
68
            'ratings' => range(1, 9),
69
            'rating' => $request->input('rating', ''),
70
            'genres' => $movie->getGenres(),
71
            'genre' => $request->input('genre', ''),
72
            'years' => $years,
73
            'year' => $request->input('year', ''),
74
            'catname' => $catname,
75
            'resultsadd' => $movies,
76
            'results' => $results,
77
            'covgroup' => 'movies',
78
            'meta_title' => 'Browse Movies',
79
            'meta_keywords' => 'browse,nzb,description,details',
80
            'meta_description' => 'Browse for Movies',
81
            'movie_layout' => $this->userdata->movie_layout ?? 2,
0 ignored issues
show
Bug introduced by
The property movie_layout does not seem to exist on App\Models\User.
Loading history...
82
        ]);
83
84
        // Return the appropriate view
85
        $viewName = $request->has('imdb') ? 'movies.viewmoviefull' : 'movies.index';
86
87
        return view($viewName, $this->viewData);
88
    }
89
90
    /**
91
     * Show a single movie with all its releases
92
     *
93
     * @throws \Exception
94
     */
95
    public function showMovie(Request $request, string $imdbid)
96
    {
97
        $movie = new Movie(['Settings' => $this->settings]);
0 ignored issues
show
Unused Code introduced by
The call to Blacklight\Movie::__construct() has too many arguments starting with array('Settings' => $this->settings). ( Ignorable by Annotation )

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

97
        $movie = /** @scrutinizer ignore-call */ new Movie(['Settings' => $this->settings]);

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.

Loading history...
98
99
        // Get movie info
100
        $movieInfo = $movie->getMovieInfo($imdbid);
101
102
        if (! $movieInfo) {
0 ignored issues
show
introduced by
$movieInfo is of type App\Models\MovieInfo, thus it always evaluated to true.
Loading history...
103
            return redirect()->route('Movies')->with('error', 'Movie not found');
104
        }
105
106
        // Get all releases for this movie
107
        $rslt = $movie->getMovieRange(1, [], 0, 1000, '', -1, $this->userdata->categoryexclusions);
0 ignored issues
show
Bug introduced by
The property categoryexclusions does not seem to exist on App\Models\User.
Loading history...
108
109
        // Filter to only this movie's IMDB ID
110
        $movieData = collect($rslt)->firstWhere('imdbid', $imdbid);
0 ignored issues
show
Bug introduced by
It seems like $rslt can also be of type array; however, parameter $value of collect() does only seem to accept Illuminate\Contracts\Support\Arrayable, 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

110
        $movieData = collect(/** @scrutinizer ignore-type */ $rslt)->firstWhere('imdbid', $imdbid);
Loading history...
111
112
        if (! $movieData) {
113
            return redirect()->route('Movies')->with('error', 'No releases found for this movie');
114
        }
115
116
        // Process movie data - ensure we handle both objects and arrays
117
        if (is_object($movieInfo)) {
118
            // If it's an Eloquent model, use toArray()
119
            if (method_exists($movieInfo, 'toArray')) {
120
                $movieArray = $movieInfo->toArray();
121
            } else {
122
                $movieArray = get_object_vars($movieInfo);
123
            }
124
        } else {
125
            $movieArray = $movieInfo;
126
        }
127
128
        // Ensure we have at least the basic fields
129
        if (empty($movieArray['title'])) {
130
            $movieArray['title'] = 'Unknown Title';
131
        }
132
        if (empty($movieArray['imdbid'])) {
133
            $movieArray['imdbid'] = $imdbid;
134
        }
135
136
        // Only process fields if they exist and are not empty
137
        if (! empty($movieArray['genre'])) {
138
            $movieArray['genre'] = makeFieldLinks($movieArray, 'genre', 'movies');
139
        }
140
        if (! empty($movieArray['actors'])) {
141
            $movieArray['actors'] = makeFieldLinks($movieArray, 'actors', 'movies');
142
        }
143
        if (! empty($movieArray['director'])) {
144
            $movieArray['director'] = makeFieldLinks($movieArray, 'director', 'movies');
145
        }
146
147
        // Add cover image URL using helper function
148
        $movieArray['cover'] = getReleaseCover($movieArray);
149
150
        // Process all releases
151
        $releaseNames = isset($movieData->grp_release_name) ? explode('#', $movieData->grp_release_name) : [];
152
        $releaseSizes = isset($movieData->grp_release_size) ? explode(',', $movieData->grp_release_size) : [];
153
        $releaseGuids = isset($movieData->grp_release_guid) ? explode(',', $movieData->grp_release_guid) : [];
154
        $releasePostDates = isset($movieData->grp_release_postdate) ? explode(',', $movieData->grp_release_postdate) : [];
155
        $releaseAddDates = isset($movieData->grp_release_adddate) ? explode(',', $movieData->grp_release_adddate) : [];
156
157
        $releases = [];
158
        foreach ($releaseNames as $index => $releaseName) {
159
            if ($releaseName && isset($releaseGuids[$index])) {
160
                $releases[] = [
161
                    'name' => $releaseName,
162
                    'guid' => $releaseGuids[$index],
163
                    'size' => $releaseSizes[$index] ?? 0,
164
                    'postdate' => $releasePostDates[$index] ?? null,
165
                    'adddate' => $releaseAddDates[$index] ?? null,
166
                ];
167
            }
168
        }
169
170
        $this->viewData = array_merge($this->viewData, [
171
            'movie' => $movieArray,
172
            'releases' => $releases,
173
            'meta_title' => ($movieArray['title'] ?? 'Movie').' - Movie Details',
174
            'meta_keywords' => 'movie,details,releases',
175
            'meta_description' => 'View all releases for '.($movieArray['title'] ?? 'this movie'),
176
        ]);
177
178
        return view('movies.viewmoviefull', $this->viewData);
179
    }
180
181
    /**
182
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
183
     */
184
    public function showTrailer(Request $request)
185
    {
186
        $movie = new Movie;
187
188
        if ($request->has('id') && ctype_digit($request->input('id'))) {
189
            $mov = $movie->getMovieInfo($request->input('id'));
190
191
            if (! $mov) {
0 ignored issues
show
introduced by
$mov is of type App\Models\MovieInfo, thus it always evaluated to true.
Loading history...
192
                return response()->json(['message' => 'There is no trailer for this movie.'], 404);
193
            }
194
195
            $modal = $request->has('modal');
196
197
            $viewData = [
198
                'movie' => $mov,
199
            ];
200
201
            // Return different views for modal vs full page
202
            if ($modal) {
203
                return view('movies.trailer-modal', $viewData);
204
            }
205
206
            $this->viewData = array_merge($this->viewData, [
207
                'movie' => $mov,
208
                'title' => 'Info for '.$mov['title'],
209
                'meta_title' => '',
210
                'meta_keywords' => '',
211
                'meta_description' => '',
212
            ]);
213
214
            return view('movies.viewmovietrailer', $this->viewData);
215
        }
216
217
        return response()->json(['message' => 'Invalid movie ID.'], 400);
218
    }
219
220
    /**
221
     * Show trending movies (top 15 most downloaded in last 48 hours)
222
     *
223
     * @throws \Exception
224
     */
225
    public function showTrending(Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

225
    public function showTrending(/** @scrutinizer ignore-unused */ Request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
226
    {
227
        $movie = new Movie(['Settings' => $this->settings]);
0 ignored issues
show
Unused Code introduced by
The call to Blacklight\Movie::__construct() has too many arguments starting with array('Settings' => $this->settings). ( Ignorable by Annotation )

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

227
        $movie = /** @scrutinizer ignore-call */ new Movie(['Settings' => $this->settings]);

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.

Loading history...
Unused Code introduced by
The assignment to $movie is dead and can be removed.
Loading history...
228
229
        // Cache key for trending movies (48 hours)
230
        $cacheKey = 'trending_movies_top_15_48h';
231
232
        // Get trending movies from cache or calculate (refresh every hour)
233
        $trendingMovies = \Illuminate\Support\Facades\Cache::remember($cacheKey, 3600, function () {
234
            // Calculate timestamp for 48 hours ago
235
            $fortyEightHoursAgo = \Illuminate\Support\Carbon::now()->subHours(48);
236
237
            // Get movies with their download counts from last 48 hours
238
            // Join with user_downloads to get actual download timestamps
239
            $query = \Illuminate\Support\Facades\DB::table('movieinfo as m')
240
                ->join('releases as r', 'm.imdbid', '=', 'r.imdbid')
241
                ->leftJoin('user_downloads as ud', 'r.id', '=', 'ud.releases_id')
242
                ->select([
243
                    'm.imdbid',
244
                    'm.title',
245
                    'm.year',
246
                    'm.rating',
247
                    'm.plot',
248
                    'm.genre',
249
                    'm.cover',
250
                    'm.tmdbid',
251
                    'm.traktid',
252
                    \Illuminate\Support\Facades\DB::raw('COUNT(DISTINCT ud.id) as total_downloads'),
253
                    \Illuminate\Support\Facades\DB::raw('COUNT(DISTINCT r.id) as release_count'),
254
                ])
255
                ->where('m.title', '!=', '')
256
                ->where('m.imdbid', '!=', '0000000')
257
                ->where('ud.timestamp', '>=', $fortyEightHoursAgo)
258
                ->groupBy('m.imdbid', 'm.title', 'm.year', 'm.rating', 'm.plot', 'm.genre', 'm.cover', 'm.tmdbid', 'm.traktid')
259
                ->havingRaw('COUNT(DISTINCT ud.id) > 0')
260
                ->orderByDesc('total_downloads')
0 ignored issues
show
Bug introduced by
'total_downloads' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderByDesc(). ( Ignorable by Annotation )

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

260
                ->orderByDesc(/** @scrutinizer ignore-type */ 'total_downloads')
Loading history...
261
                ->limit(15)
262
                ->get();
263
264
            // Process the results
265
            return $query->map(function ($item) {
266
                // Add cover image URL using helper function
267
                $coverArray = [
268
                    'imdbid' => $item->imdbid,
269
                    'tmdbid' => $item->tmdbid,
270
                    'cover' => $item->cover,
271
                ];
272
                $item->cover = getReleaseCover($coverArray);
273
274
                return $item;
275
            });
276
        });
277
278
        $this->viewData = array_merge($this->viewData, [
279
            'trendingMovies' => $trendingMovies,
280
            'meta_title' => 'Trending Movies - Last 48 Hours',
281
            'meta_keywords' => 'trending,movies,popular,downloads,recent',
282
            'meta_description' => 'Browse the most popular and downloaded movies in the last 48 hours',
283
        ]);
284
285
        return view('movies.trending', $this->viewData);
286
    }
287
288
    /**
289
     * Update user's movie layout preference
290
     */
291
    public function updateLayout(Request $request)
292
    {
293
        $request->validate([
294
            'layout' => 'required|integer|in:1,2',
295
        ]);
296
297
        $user = auth()->user();
298
        if ($user) {
299
            $user->movie_layout = (int) $request->input('layout');
300
            $user->save();
301
302
            return response()->json(['success' => true, 'layout' => $user->movie_layout]);
303
        }
304
305
        return response()->json(['success' => false, 'message' => 'User not authenticated'], 401);
306
    }
307
}
308