NNTmux /
newznab-tmux
| 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
|
|||||
| 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); |
||||
| 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, |
||||
| 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
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
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
|
|||||
| 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); |
||||
| 108 | |||||
| 109 | // Filter to only this movie's IMDB ID |
||||
| 110 | $movieData = collect($rslt)->firstWhere('imdbid', $imdbid); |
||||
|
0 ignored issues
–
show
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
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
|
|||||
| 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
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
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
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
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...
|
|||||
| 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
'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
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 |
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.