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
6declare(strict_types=1);
7
8namespace App\Libraries\BeatmapsetDiscussion\Traits;
9
10use App\Jobs\Notifications\BeatmapsetDiscussionQualifiedProblem;
11use App\Models\BeatmapDiscussion;
12use App\Models\User;
13
14trait HandlesProblem
15{
16 private bool $hasPriorOpenProblems = false;
17 private bool $isNew = false;
18 private ?BeatmapDiscussion $problemDiscussion = null;
19 private User $user;
20
21 private function handleProblemDiscussion(): void
22 {
23 if ($this->problemDiscussion === null) {
24 return;
25 }
26
27 $beatmapset = $this->problemDiscussion->beatmapset;
28
29 if ($this->shouldDisqualifyOrResetNominations()) {
30 $beatmapset->disqualifyOrResetNominations($this->user, $this->problemDiscussion);
31
32 return;
33 }
34
35 if ($beatmapset->isQualified() && !$this->hasPriorOpenProblems && !$this->problemDiscussion->resolved) {
36 (new BeatmapsetDiscussionQualifiedProblem(
37 $this->problemDiscussion->startingPost,
38 $this->user
39 ))->dispatch();
40 }
41 }
42
43 /**
44 * This should be called _before_ any updates to the problem discussion are saved.
45 *
46 * @param BeatmapDiscussion $discussion The discussion flagging the problem.
47 * @param bool $isNew Whether the discussion should be considered a new discussion or reply.
48 */
49 private function maybeSetProblemDiscussion(BeatmapDiscussion $discussion, bool $isNew = true)
50 {
51 if ($discussion->isProblem() && $this->problemDiscussion === null) {
52 $this->hasPriorOpenProblems = $discussion->beatmapset->beatmapDiscussions()->openProblems()->exists();
53 $this->problemDiscussion = $discussion;
54 $this->isNew = $isNew;
55 }
56 }
57
58 private function shouldDisqualifyOrResetNominations(): bool
59 {
60 // disqualify or reset nominations requires a new discussion.
61 if ($this->problemDiscussion !== null && $this->isNew) {
62 $beatmapset = $this->problemDiscussion->beatmapset;
63 if ($beatmapset->isQualified()) {
64 return priv_check_user($this->user, 'BeatmapsetDisqualify', $beatmapset)->can();
65 } elseif ($beatmapset->isPending()) {
66 return $beatmapset->hasNominations()
67 && priv_check_user($this->user, 'BeatmapsetResetNominations', $beatmapset)->can();
68 }
69 }
70
71 return false;
72 }
73}