mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 18:01:27 +00:00
272 lines
7.6 KiB
PHP
272 lines
7.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Category;
|
|
use App\Models\Settings;
|
|
use App\Models\User;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\View\View;
|
|
|
|
class BasePageController extends Controller
|
|
{
|
|
/**
|
|
* @var Collection<int, mixed>
|
|
*/
|
|
public Collection $settings;
|
|
|
|
public string $title = '';
|
|
|
|
public string $content = '';
|
|
|
|
public string $meta_keywords = '';
|
|
|
|
public string $meta_title = '';
|
|
|
|
public string $meta_description = '';
|
|
|
|
/**
|
|
* Current page the user is browsing. ie browse.
|
|
*/
|
|
public string $page = '';
|
|
|
|
public User $userdata;
|
|
|
|
/**
|
|
* User's theme.
|
|
*/
|
|
protected string $theme = 'Gentele';
|
|
|
|
/**
|
|
* View data array for Blade templates
|
|
*
|
|
* @var array<string, mixed>
|
|
*/
|
|
protected array $viewData = [];
|
|
|
|
/**
|
|
* BasePageController constructor.
|
|
*
|
|
* @throws \Exception
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->middleware(['auth', 'web', '2fa'])->except('api', 'contact', 'showContactForm', 'callback', 'btcPayCallback', 'getNzb', 'terms', 'privacyPolicy', 'capabilities', 'movie', 'apiSearch', 'tv', 'details', 'failed', 'showRssDesc', 'fullFeedRss', 'categoryFeedRss', 'cartRss', 'myMoviesRss', 'myShowsRss', 'trendingMoviesRss', 'trendingShowsRss', 'release', 'reset', 'showLinkRequestForm', 'showStatusPage');
|
|
|
|
// Load settings as collection with caching (5 minutes)
|
|
$this->settings = $this->rememberWithCacheFallback('site_settings', 300, function () {
|
|
return Settings::query()->pluck('value', 'name');
|
|
});
|
|
|
|
// Initialize view data FIRST with serverroot
|
|
$this->viewData = [
|
|
'serverroot' => url('/'),
|
|
];
|
|
|
|
// Then add the converted settings array as 'site' with caching
|
|
$this->viewData['site'] = $this->rememberWithCacheFallback('site_settings_converted', 300, function () {
|
|
return $this->settings->map(function ($value) {
|
|
return Settings::convertValue($value);
|
|
})->all();
|
|
});
|
|
|
|
// Initialize userdata property for controllers that need it
|
|
$this->middleware(function ($request, $next) {
|
|
if (Auth::check()) {
|
|
$userId = Auth::id();
|
|
$this->userdata = User::find($userId);
|
|
if (! $this->userdata?->hasVerifiedEmail()) {
|
|
return $next($request);
|
|
}
|
|
|
|
// Cache category exclusions per user (5 minutes)
|
|
$this->userdata->categoryexclusions = $this->rememberWithCacheFallback(
|
|
User::categoryExclusionCacheKey($userId),
|
|
300,
|
|
fn () => User::getCategoryExclusionById($userId)
|
|
);
|
|
}
|
|
|
|
return $next($request);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Use the cache when available; if the store is unreachable (e.g. Redis down), run the callback directly.
|
|
*
|
|
* @param callable(): mixed $callback
|
|
*/
|
|
private function rememberWithCacheFallback(string $key, int|\DateInterval $ttl, callable $callback): mixed
|
|
{
|
|
try {
|
|
return Cache::remember($key, $ttl, $callback);
|
|
} catch (\Throwable $e) {
|
|
if (config('app.debug')) {
|
|
Log::debug('BasePageController cache bypassed: '.$e->getMessage());
|
|
}
|
|
|
|
return $callback();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return LengthAwarePaginator<int, mixed>
|
|
*/
|
|
public function paginate(mixed $query, mixed $totalCount, mixed $items, mixed $page, mixed $path, mixed $reqQuery): LengthAwarePaginator
|
|
{
|
|
return new LengthAwarePaginator($query, $totalCount, $items, $page, ['path' => $path, 'query' => $reqQuery]);
|
|
}
|
|
|
|
protected function resolvePage(Request $request, string $key = 'page'): int
|
|
{
|
|
$page = $request->input($key, 1);
|
|
if (! is_scalar($page)) {
|
|
return 1;
|
|
}
|
|
|
|
$page = (string) $page;
|
|
if ($page === '' || preg_match('/^\d+$/', $page) !== 1) {
|
|
return 1;
|
|
}
|
|
|
|
return max(1, (int) $page);
|
|
}
|
|
|
|
/**
|
|
* @param array<int, string> $ordering
|
|
*/
|
|
protected function resolveOrderBy(Request $request, array $ordering, string $key = 'ob'): string
|
|
{
|
|
$orderByInput = $request->input($key, '');
|
|
$orderBy = is_scalar($orderByInput) ? (string) $orderByInput : '';
|
|
|
|
return \in_array($orderBy, $ordering, true) ? $orderBy : '';
|
|
}
|
|
|
|
protected function paginationOffset(int $page, int $perPage): int
|
|
{
|
|
return ($page - 1) * $perPage;
|
|
}
|
|
|
|
/**
|
|
* @param array<int, string> $ordering
|
|
* @return array<string, string>
|
|
*/
|
|
protected function buildOrderByUrls(array $ordering, string $basePath, string $prefix = 'orderby'): array
|
|
{
|
|
$orderByUrls = [];
|
|
foreach ($ordering as $orderType) {
|
|
$orderByUrls[$prefix.$orderType] = url($basePath.'?ob='.$orderType);
|
|
}
|
|
|
|
return $orderByUrls;
|
|
}
|
|
|
|
protected function scalarInput(Request $request, string $key, string $default = ''): string
|
|
{
|
|
$value = $request->input($key, $default);
|
|
|
|
return is_scalar($value) ? (string) $value : $default;
|
|
}
|
|
|
|
protected function integerInput(Request $request, string $key, int $default = 0): int
|
|
{
|
|
$value = $this->scalarInput($request, $key, (string) $default);
|
|
|
|
return preg_match('/^-?\d+$/', $value) === 1 ? (int) $value : $default;
|
|
}
|
|
|
|
/**
|
|
* @return array<int|string, mixed>
|
|
*/
|
|
protected function arrayInput(Request $request, string $key): array
|
|
{
|
|
$value = $request->input($key, []);
|
|
|
|
return \is_array($value) ? $value : [];
|
|
}
|
|
|
|
protected function localReturnUrl(Request $request, string $fallback, string $key = 'from'): string
|
|
{
|
|
$from = $this->scalarInput($request, $key);
|
|
if ($from === '') {
|
|
return url($fallback);
|
|
}
|
|
|
|
if (filter_var($from, FILTER_VALIDATE_URL) !== false) {
|
|
return parse_url($from, PHP_URL_HOST) === $request->getHost() ? $from : url($fallback);
|
|
}
|
|
|
|
return url($from);
|
|
}
|
|
|
|
/**
|
|
* Check if request is POST.
|
|
*/
|
|
public function isPostBack(Request $request): bool
|
|
{
|
|
return $request->isMethod('POST');
|
|
}
|
|
|
|
/**
|
|
* Show 404 page.
|
|
*
|
|
* @param string|null $message
|
|
*/
|
|
public function show404($message = null): View
|
|
{
|
|
if ($message !== null) {
|
|
return view('errors.404')->with('Message', $message);
|
|
}
|
|
|
|
return view('errors.404');
|
|
}
|
|
|
|
/**
|
|
* Set admin preferences.
|
|
*/
|
|
public function setAdminPrefs(): void
|
|
{
|
|
$this->viewData['catClass'] = Category::class;
|
|
}
|
|
|
|
/**
|
|
* Output the page using Blade views.
|
|
*/
|
|
public function pagerender(): View
|
|
{
|
|
return view('layouts.main', $this->viewData);
|
|
}
|
|
|
|
/**
|
|
* Output a page using the admin template.
|
|
*
|
|
* @throws \Exception
|
|
*/
|
|
public function adminrender(): View
|
|
{
|
|
return view('layouts.admin', $this->viewData);
|
|
}
|
|
|
|
/**
|
|
* @throws \Exception
|
|
*/
|
|
public function adminBasePage(): View
|
|
{
|
|
$this->setAdminPrefs();
|
|
$this->viewData = array_merge($this->viewData, [
|
|
'meta_title' => 'Admin Home',
|
|
'meta_description' => 'Admin home page',
|
|
]);
|
|
|
|
return $this->adminrender();
|
|
}
|
|
}
|