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;
7
8use App\Exceptions\InvariantException;
9use App\Models\Multiplayer\PlaylistItem;
10use App\Models\Solo\Score;
11use Illuminate\Database\Eloquent\Relations\BelongsTo;
12
13/**
14 * @property \App\Models\Beatmap $beatmap
15 * @property int $beatmap_id
16 * @property \App\Models\Build|null $build
17 * @property int|null $build_id
18 * @property \Carbon\Carbon|null $created_at
19 * @property int $id
20 * @property int $ruleset_id
21 * @property \App\Models\Solo\Score $score
22 * @property int $score_id
23 * @property \Carbon\Carbon|null $updated_at
24 * @property \App\Models\User $user
25 * @property int $user_id
26 */
27class ScoreToken extends Model
28{
29 public ?string $beatmapHash = null;
30
31 public function beatmap()
32 {
33 return $this->belongsTo(Beatmap::class, 'beatmap_id');
34 }
35
36 public function build()
37 {
38 return $this->belongsTo(Build::class, 'build_id');
39 }
40
41 public function playlistItem(): BelongsTo
42 {
43 return $this->belongsTo(PlaylistItem::class);
44 }
45
46 public function score()
47 {
48 return $this->belongsTo(Score::class);
49 }
50
51 public function user()
52 {
53 return $this->belongsTo(User::class, 'user_id');
54 }
55
56 public function getAttribute($key)
57 {
58 return match ($key) {
59 'beatmap_id',
60 'build_id',
61 'id',
62 'playlist_item_id',
63 'ruleset_id',
64 'score_id',
65 'user_id' => $this->getRawAttribute($key),
66
67 'created_at',
68 'updated_at' => $this->getTimeFast($key),
69
70 'created_at_json',
71 'updated_at_json' => $this->getJsonTimeFast($key),
72
73 'beatmap',
74 'build',
75 'playlistItem',
76 'score',
77 'user' => $this->getRelationValue($key),
78 };
79 }
80
81 public function setBeatmapHashAttribute(?string $value): void
82 {
83 $this->beatmapHash = $value;
84 }
85
86 public function assertValid(): void
87 {
88 $beatmap = $this->beatmap;
89 if ($this->beatmapHash !== $beatmap->checksum) {
90 throw new InvariantException(osu_trans('score_tokens.create.beatmap_hash_invalid'));
91 }
92
93 $rulesetId = $this->ruleset_id;
94 if ($rulesetId === null) {
95 throw new InvariantException('missing ruleset_id');
96 }
97 if (Beatmap::modeStr($rulesetId) === null || !$beatmap->canBeConvertedTo($rulesetId)) {
98 throw new InvariantException('invalid ruleset_id');
99 }
100 }
101
102 public function save(array $options = []): bool
103 {
104 if (!$this->exists) {
105 $this->assertValid();
106 }
107
108 return parent::save($options);
109 }
110}