1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Http\Controllers\Admin;
7
8use App\Models\Contest;
9use App\Models\ContestJudgeVote;
10use App\Models\DeletedUser;
11use App\Models\UserContestEntry;
12use ZipStream\ZipStream;
13
14class ContestsController extends Controller
15{
16 public function index()
17 {
18 return ext_view('admin.contests.index', [
19 'contests' => Contest::orderBy('id', 'desc')->get(),
20 ]);
21 }
22
23 public function show($id)
24 {
25 $contest = Contest::with('judges')
26 ->withCount('entries')
27 ->findOrFail($id);
28
29 $entries = UserContestEntry::withTrashed()
30 ->where('contest_id', $id)
31 ->with('user')
32 ->get();
33
34 if ($contest->isJudged()) {
35 $judgeVoteCounts = ContestJudgeVote::whereIn('contest_entry_id', $contest->entries()->pluck('id'))
36 ->groupBy('user_id')
37 ->selectRaw('COUNT(*) as judge_votes_count, user_id')
38 ->get();
39 }
40
41 return ext_view('admin.contests.show', [
42 'contest' => $contest,
43 'entries' => json_collection($entries, 'UserContestEntry', ['user']),
44 'judgeVoteCounts' => $judgeVoteCounts ??= null,
45 ]);
46 }
47
48 public function gimmeZip($id)
49 {
50 // doesn't actually work in octane
51 set_time_limit(300);
52
53 Contest::findOrFail($id);
54 $entries = UserContestEntry::where('contest_id', $id)->with('user')->get();
55
56 $zipOutput = "contest-{$id}.zip";
57
58 return response()->streamDownload(function () use ($entries) {
59 $zip = new ZipStream();
60
61 $deletedUser = new DeletedUser();
62 foreach ($entries as $entry) {
63 $targetDir = ($entry->user ?? $deletedUser)->username." ({$entry->user_id})";
64 $filename = sanitize_filename($entry->original_filename);
65 $zip->addFile("$targetDir/{$filename}", $entry->file()->get());
66 }
67
68 $zip->finish();
69 }, $zipOutput, ['content-type' => 'application/zip']);
70 }
71}