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\Forum;
7
8use App\Models\User;
9use App\Traits\Validatable;
10use DB;
11
12/**
13 * @property \Carbon\Carbon $date
14 * @property int $star_id
15 * @property Topic $topic
16 * @property int $topic_id
17 * @property mixed $type
18 * @property User $user
19 * @property int $user_id
20 */
21class FeatureVote extends Model
22{
23 use Validatable;
24
25 public $timestamps = false;
26
27 protected $casts = ['date' => 'datetime'];
28 protected $table = 'phpbb_topics_stars';
29 protected $primaryKey = 'star_id';
30
31 const COST = 1;
32
33 public function topic()
34 {
35 return $this->belongsTo(Topic::class, 'topic_id');
36 }
37
38 public function user()
39 {
40 return $this->belongsTo(User::class, 'user_id');
41 }
42
43 public function voteIncrement()
44 {
45 switch ($this->type) {
46 case 'supporter':
47 return 2;
48 case 'user':
49 return 1;
50 }
51 }
52
53 public function setType()
54 {
55 if ($this->user !== null && $this->user->osu_subscriber) {
56 $this->type = 'supporter';
57 } else {
58 $this->type = 'user';
59 }
60 }
61
62 public function validateTopic()
63 {
64 if ($this->topic === null) {
65 $this->validationErrors()->add('topic_id', 'required');
66
67 return;
68 }
69
70 if (!$this->topic->isFeatureTopic()) {
71 $this->validationErrors()->add('topic_id', '.not_feature_topic');
72 }
73 }
74
75 public function validateUser()
76 {
77 if ($this->user === null) {
78 $this->validationErrors()->add('user_id', 'required');
79
80 return;
81 }
82
83 if ($this->user->osu_featurevotes < static::COST) {
84 $this->validationErrors()->add('user_id', '.not_enough_feature_votes');
85 }
86 }
87
88 public function isValid()
89 {
90 $this->validationErrors()->reset();
91 $this->validateUser();
92 $this->validateTopic();
93
94 return $this->validationErrors()->isEmpty();
95 }
96
97 public static function createNew($params)
98 {
99 $star = new static($params);
100 $star->setType();
101
102 if ($star->isValid()) {
103 DB::transaction(function () use ($star) {
104 // So the strings can be used with interpolation
105 // instead of concatenation or sprintf.
106 $cost = (string) static::COST;
107 $increment = (string) $star->voteIncrement();
108
109 // phpcs:ignore
110 return
111 $star->user->update([
112 'osu_featurevotes' => DB::raw("osu_featurevotes - ({$cost})"),
113 ]) &&
114
115 $star->topic->update([
116 'osu_starpriority' => DB::raw("osu_starpriority + ({$increment})"),
117 ]) &&
118
119 $star->saveOrFail();
120 });
121 }
122
123 return $star;
124 }
125
126 public function validationErrorsTranslationPrefix(): string
127 {
128 return 'forum.feature_vote';
129 }
130}