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\Traits\Validatable;
9use Carbon\Carbon;
10use DB;
11
12class TopicVote
13{
14 use Validatable;
15
16 private array $params = [];
17 private $topic;
18 private $validated = false;
19
20 public function __construct($topic)
21 {
22 $this->topic = $topic;
23 }
24
25 public function fill($params)
26 {
27 $this->params = $params;
28 $this->validated = false;
29
30 return $this;
31 }
32
33 public function isValid($revalidate = false)
34 {
35 if (!$this->validated || $revalidate) {
36 $this->validated = true;
37 $this->validationErrors()->reset();
38
39 if (!isset($this->params['option_ids']) || count($this->params['option_ids']) < 1) {
40 $this->validationErrors()->add('option_ids', '.required');
41 }
42
43 if (count($this->params['option_ids'] ?? []) > $this->topic->poll_max_options) {
44 $this->validationErrors()->add('option_ids', '.too_many');
45 }
46 }
47
48 return $this->validationErrors()->isEmpty();
49 }
50
51 public function save()
52 {
53 if (!$this->isValid()) {
54 return false;
55 }
56
57 return DB::transaction(function () {
58 $this->topic->update([
59 'poll_last_vote' => Carbon::now(),
60 ]);
61
62 $this
63 ->topic
64 ->pollVotes()
65 ->where('vote_user_id', $this->params['user_id'])
66 ->delete();
67
68 foreach (array_unique($this->params['option_ids']) as $optionId) {
69 $this
70 ->topic
71 ->pollVotes()
72 ->create([
73 'poll_option_id' => $optionId,
74 'vote_user_id' => $this->params['user_id'],
75 'vote_user_ip' => $this->params['ip'],
76 ]);
77 }
78
79 PollOption::updateTotals(['topic_id' => $this->topic->topic_id]);
80
81 return true;
82 });
83 }
84
85 public function validationErrorsTranslationPrefix(): string
86 {
87 return 'forum.topic_vote';
88 }
89}