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\Models\Traits;
7
8use App\Exceptions\InvariantException;
9use App\Models\User;
10use App\Models\UserReport;
11use App\Notifications\UserReportNotification;
12
13/**
14 * @property-read \Illuminate\Database\Eloquent\Collection<UserReport> $reportedIn
15 */
16trait Reportable
17{
18 abstract protected function newReportableExtraParams(): array;
19
20 public function reportableAdditionalInfo(): ?string
21 {
22 return null;
23 }
24
25 public function reportedIn()
26 {
27 return $this->morphMany(UserReport::class, 'reportable');
28 }
29
30 /**
31 * Creates and saves a new UserReport.
32 *
33 * @param User $reporter
34 * @param array $params
35 * @return UserReport|null The instance of UserReport saved, null if it is a duplicate.
36 */
37 public function reportBy(User $reporter, array $params = []): ?UserReport
38 {
39 $attributes = $this->newReportableExtraParams();
40 $attributes['comments'] = $params['comments'] ?? '';
41 $attributes['reporter_id'] = $reporter->getKey();
42
43 if (present($params['reason'] ?? null)) {
44 $attributes['reason'] = $params['reason'];
45 }
46
47 $existingReport = $this->reportedIn()->where([
48 'reporter_id' => $attributes['reporter_id'],
49 ])->orderBy('report_id', 'DESC')->first();
50 if ($existingReport !== null && $existingReport->isRecent()) {
51 throw new InvariantException(osu_trans('errors.user_report.recently_reported'));
52 }
53
54 $userReport = $this->reportedIn()->create($attributes);
55 $userReport->notify(new UserReportNotification($reporter));
56
57 return $userReport;
58 }
59}