diff --git a/app/Http/Controllers/Admin/AdminAnidbController.php b/app/Http/Controllers/Admin/AdminAnidbController.php index 4f93b62dd..3221f10fe 100644 --- a/app/Http/Controllers/Admin/AdminAnidbController.php +++ b/app/Http/Controllers/Admin/AdminAnidbController.php @@ -23,7 +23,7 @@ class AdminAnidbController extends BasePageController $anidbService = new AnidbService; $title = $meta_title = 'AniDB List'; - $animetitle = $request->input('animetitle', ''); + $animetitle = $this->scalarInput($request, 'animetitle'); $anidblist = $anidbService->getAnimeRange($animetitle); return view('admin.anidb.index', compact('anidblist', 'animetitle', 'title', 'meta_title')); diff --git a/app/Http/Controllers/Admin/AdminCategoryRegexesController.php b/app/Http/Controllers/Admin/AdminCategoryRegexesController.php index 4ca6a090e..ba1681cf5 100644 --- a/app/Http/Controllers/Admin/AdminCategoryRegexesController.php +++ b/app/Http/Controllers/Admin/AdminCategoryRegexesController.php @@ -23,7 +23,7 @@ class AdminCategoryRegexesController extends BasePageController $meta_title = $title = 'Category Regex List'; - $group = $request->has('group') && ! empty($request->input('group')) ? $request->input('group') : ''; + $group = $this->scalarInput($request, 'group'); $regex = $regexes->getRegex($group); $this->viewData = array_merge($this->viewData, [ diff --git a/app/Http/Controllers/Admin/AdminCollectionRegexesController.php b/app/Http/Controllers/Admin/AdminCollectionRegexesController.php index 80fa5ce86..08fbce416 100644 --- a/app/Http/Controllers/Admin/AdminCollectionRegexesController.php +++ b/app/Http/Controllers/Admin/AdminCollectionRegexesController.php @@ -23,7 +23,7 @@ class AdminCollectionRegexesController extends BasePageController $meta_title = $title = 'Collections Regex List'; - $group = ($request->has('group') && ! empty($request->input('group')) ? $request->input('group') : ''); + $group = $this->scalarInput($request, 'group'); $regex = $regexes->getRegex($group); $this->viewData = array_merge($this->viewData, [ diff --git a/app/Http/Controllers/Admin/AdminGameController.php b/app/Http/Controllers/Admin/AdminGameController.php index f692d811d..50e7e56f0 100644 --- a/app/Http/Controllers/Admin/AdminGameController.php +++ b/app/Http/Controllers/Admin/AdminGameController.php @@ -23,7 +23,7 @@ class AdminGameController extends BasePageController $meta_title = $title = 'Game List'; // Get search parameter - $search = $request->input('gamesearch', ''); + $search = $this->scalarInput($request, 'gamesearch'); if (! empty($search)) { $gamelist = $game->getRange($search); diff --git a/app/Http/Controllers/Admin/AdminInvitationController.php b/app/Http/Controllers/Admin/AdminInvitationController.php index 9820fd995..f13f4822f 100644 --- a/app/Http/Controllers/Admin/AdminInvitationController.php +++ b/app/Http/Controllers/Admin/AdminInvitationController.php @@ -33,10 +33,10 @@ class AdminInvitationController extends BasePageController $meta_title = $title = 'Invitation Management'; // Get filter parameters - $status = $request->get('status', ''); - $invited_by = $request->get('invited_by', ''); - $email = $request->get('email', ''); - $orderBy = $request->get('ob', 'created_at_desc'); + $status = $this->scalarInput($request, 'status'); + $invited_by = $this->scalarInput($request, 'invited_by'); + $email = $this->scalarInput($request, 'email'); + $orderBy = $this->scalarInput($request, 'ob', 'created_at_desc'); // Build query $query = Invitation::with(['invitedBy', 'usedBy']); diff --git a/app/Http/Controllers/Admin/AdminMovieController.php b/app/Http/Controllers/Admin/AdminMovieController.php index a532a9315..a536d5fe8 100644 --- a/app/Http/Controllers/Admin/AdminMovieController.php +++ b/app/Http/Controllers/Admin/AdminMovieController.php @@ -33,10 +33,10 @@ class AdminMovieController extends BasePageController */ public function index(Request $request): mixed { - $lastSearch = $request->input('moviesearch', ''); + $lastSearch = $this->scalarInput($request, 'moviesearch'); if ($request->has('moviesearch')) { - $movielist = MovieInfo::getAll($request->input('moviesearch')); + $movielist = MovieInfo::getAll($lastSearch); } else { $movielist = MovieInfo::getAll(); } diff --git a/app/Http/Controllers/Admin/AdminMusicController.php b/app/Http/Controllers/Admin/AdminMusicController.php index 81ab58835..f7c51c18b 100644 --- a/app/Http/Controllers/Admin/AdminMusicController.php +++ b/app/Http/Controllers/Admin/AdminMusicController.php @@ -21,7 +21,7 @@ class AdminMusicController extends BasePageController $meta_title = $title = 'Music List'; // Get search parameter - $search = $request->input('musicsearch', ''); + $search = $this->scalarInput($request, 'musicsearch'); if (! empty($search)) { $musicList = getRange('musicinfo'); diff --git a/app/Http/Controllers/Admin/AdminPredbController.php b/app/Http/Controllers/Admin/AdminPredbController.php index d975ea28f..dd7b26feb 100644 --- a/app/Http/Controllers/Admin/AdminPredbController.php +++ b/app/Http/Controllers/Admin/AdminPredbController.php @@ -18,7 +18,7 @@ class AdminPredbController extends BasePageController { $this->setAdminPrefs(); - $lastSearch = $request->input('presearch', ''); + $lastSearch = $this->scalarInput($request, 'presearch'); if ($lastSearch) { $results = Predb::getAll($lastSearch); diff --git a/app/Http/Controllers/Admin/AdminReleaseNamingRegexesController.php b/app/Http/Controllers/Admin/AdminReleaseNamingRegexesController.php index c28ada27f..99828d315 100644 --- a/app/Http/Controllers/Admin/AdminReleaseNamingRegexesController.php +++ b/app/Http/Controllers/Admin/AdminReleaseNamingRegexesController.php @@ -23,10 +23,7 @@ class AdminReleaseNamingRegexesController extends BasePageController $meta_title = $title = 'Release Naming Regex List'; - $group = ''; - if ($request->has('group') && ! empty($request->input('group'))) { - $group = $request->input('group'); - } + $group = $this->scalarInput($request, 'group'); $regex = $regexes->getRegex($group); $this->viewData = array_merge($this->viewData, [ diff --git a/app/Http/Controllers/Admin/AdminShowsController.php b/app/Http/Controllers/Admin/AdminShowsController.php index 1437b7abb..cad93c266 100644 --- a/app/Http/Controllers/Admin/AdminShowsController.php +++ b/app/Http/Controllers/Admin/AdminShowsController.php @@ -24,7 +24,7 @@ class AdminShowsController extends BasePageController $meta_title = $title = 'TV Shows List'; - $showname = $request->input('showname', ''); + $showname = $this->scalarInput($request, 'showname'); $tvshowlist = Video::getRange($showname); return view('admin.shows.index', compact('tvshowlist', 'showname', 'title', 'meta_title')); diff --git a/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php b/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php index d82754b64..e00537262 100644 --- a/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php +++ b/app/Http/Controllers/Admin/AdminUserRoleHistoryController.php @@ -24,42 +24,51 @@ class AdminUserRoleHistoryController extends BasePageController // Get all roles for filter $roles = Role::all()->pluck('name', 'id')->toArray(); + $filters = [ + 'user_id' => $this->scalarInput($request, 'user_id'), + 'username' => $this->scalarInput($request, 'username'), + 'role_id' => $this->scalarInput($request, 'role_id'), + 'change_reason' => $this->scalarInput($request, 'change_reason'), + 'date_from' => $this->scalarInput($request, 'date_from'), + 'date_to' => $this->scalarInput($request, 'date_to'), + ]; + // Build query $query = UserRoleHistory::with(['user', 'oldRole', 'newRole', 'changedByUser']) ->orderBy('created_at', 'desc'); // Apply filters - if ($request->has('user_id') && ! empty($request->input('user_id'))) { - $query->where('user_id', $request->input('user_id')); + if ($filters['user_id'] !== '') { + $query->where('user_id', $filters['user_id']); } - if ($request->has('username') && ! empty($request->input('username'))) { - $query->whereHas('user', function ($q) use ($request) { - $q->where('username', 'like', '%'.$request->input('username').'%'); + if ($filters['username'] !== '') { + $query->whereHas('user', function ($q) use ($filters) { + $q->where('username', 'like', '%'.$filters['username'].'%'); }); } - if ($request->has('role_id') && ! empty($request->input('role_id'))) { - $query->where(function ($q) use ($request) { - $q->where('old_role_id', $request->input('role_id')) - ->orWhere('new_role_id', $request->input('role_id')); + if ($filters['role_id'] !== '') { + $query->where(function ($q) use ($filters) { + $q->where('old_role_id', $filters['role_id']) + ->orWhere('new_role_id', $filters['role_id']); }); } - if ($request->has('change_reason') && ! empty($request->input('change_reason'))) { - $query->where('change_reason', 'like', '%'.$request->input('change_reason').'%'); + if ($filters['change_reason'] !== '') { + $query->where('change_reason', 'like', '%'.$filters['change_reason'].'%'); } - if ($request->has('date_from') && ! empty($request->input('date_from'))) { - $query->where('created_at', '>=', $request->input('date_from').' 00:00:00'); + if ($filters['date_from'] !== '') { + $query->where('created_at', '>=', $filters['date_from'].' 00:00:00'); } - if ($request->has('date_to') && ! empty($request->input('date_to'))) { - $query->where('created_at', '<=', $request->input('date_to').' 23:59:59'); + if ($filters['date_to'] !== '') { + $query->where('created_at', '<=', $filters['date_to'].' 23:59:59'); } // Pagination - $page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1; + $page = $this->resolvePage($request); $perPage = config('nntmux.items_per_page', 50); $results = $query->paginate($perPage, ['*'], 'page', $page); @@ -69,14 +78,7 @@ class AdminUserRoleHistoryController extends BasePageController 'meta_title' => $meta_title, 'history' => $results, 'roles' => $roles, - 'filters' => [ - 'user_id' => $request->input('user_id', ''), - 'username' => $request->input('username', ''), - 'role_id' => $request->input('role_id', ''), - 'change_reason' => $request->input('change_reason', ''), - 'date_from' => $request->input('date_from', ''), - 'date_to' => $request->input('date_to', ''), - ], + 'filters' => $filters, ]); return view('admin.user-role-history.index', $this->viewData); diff --git a/app/Http/Controllers/Admin/DeletedUsersController.php b/app/Http/Controllers/Admin/DeletedUsersController.php index 618a9f216..b6276f484 100644 --- a/app/Http/Controllers/Admin/DeletedUsersController.php +++ b/app/Http/Controllers/Admin/DeletedUsersController.php @@ -25,14 +25,14 @@ class DeletedUsersController extends BasePageController $this->setAdminPrefs(); // Filters - $username = $request->input('username', ''); - $email = $request->input('email', ''); - $host = $request->input('host', ''); - $orderBy = $request->filled('ob') ? $request->input('ob') : 'deleted_at_desc'; - $createdFrom = $request->input('created_from', ''); - $createdTo = $request->input('created_to', ''); - $deletedFrom = $request->input('deleted_from', ''); - $deletedTo = $request->input('deleted_to', ''); + $username = $this->scalarInput($request, 'username'); + $email = $this->scalarInput($request, 'email'); + $host = $this->scalarInput($request, 'host'); + $orderBy = $this->scalarInput($request, 'ob', 'deleted_at_desc'); + $createdFrom = $this->scalarInput($request, 'created_from'); + $createdTo = $this->scalarInput($request, 'created_to'); + $deletedFrom = $this->scalarInput($request, 'deleted_from'); + $deletedTo = $this->scalarInput($request, 'deleted_to'); $deletedUsers = User::onlyTrashed() ->leftJoin('roles', 'roles.id', '=', 'users.roles_id') diff --git a/tests/Unit/UserViewRequestInputTest.php b/tests/Unit/UserViewRequestInputTest.php index 256a57fae..e46c2f8cb 100644 --- a/tests/Unit/UserViewRequestInputTest.php +++ b/tests/Unit/UserViewRequestInputTest.php @@ -4,9 +4,11 @@ namespace Tests\Unit; use App\Http\Controllers\BasePageController; use App\Http\Controllers\SearchController; +use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; use Illuminate\Http\Request; use PHPUnit\Framework\TestCase; use ReflectionClass; +use Symfony\Component\HttpFoundation\Response; class UserViewRequestInputTest extends TestCase { @@ -44,6 +46,20 @@ class UserViewRequestInputTest extends TestCase $this->assertSame(80, $controller->offset(5, 20)); } + public function test_scalar_input_normalizes_an_explicitly_empty_query_after_http_middleware(): void + { + $request = Request::create('/admin/anidb-list', 'GET', ['animetitle' => '']); + + (new ConvertEmptyStringsToNull)->handle( + $request, + static fn (Request $request): Response => new Response, + ); + + $this->assertNull($request->input('animetitle')); + $this->assertSame('', $this->controller()->scalar($request, 'animetitle')); + $this->assertSame('all', $this->controller()->scalar($request, 'animetitle', 'all')); + } + public function test_search_category_resolution_rejects_malformed_category_values(): void { $reflection = new ReflectionClass(SearchController::class); @@ -74,9 +90,9 @@ class UserViewRequestInputTest extends TestCase return $this->resolveOrderBy($request, $ordering); } - public function scalar(Request $request, string $key): string + public function scalar(Request $request, string $key, string $default = ''): string { - return $this->scalarInput($request, $key); + return $this->scalarInput($request, $key, $default); } public function integer(Request $request, string $key, int $default): int