Passed
Pull Request — master (#1340)
by René
08:20 queued 04:06
created

VoteService::set()   A

Complexity

Conditions 5
Paths 17

Size

Total Lines 33
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
eloc 23
c 0
b 0
f 0
dl 0
loc 33
ccs 0
cts 7
cp 0
rs 9.2408
cc 5
nc 17
nop 3
crap 30
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
4
 *
5
 * @author René Gieling <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU Affero General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU Affero General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Polls\Service;
25
26
use OCP\AppFramework\Db\DoesNotExistException;
27
use OCA\Polls\Exceptions\NotAuthorizedException;
28
use OCA\Polls\Exceptions\VoteLimitExceededException;
29
30
use OCA\Polls\Db\Log;
31
use OCA\Polls\Db\OptionMapper;
32
use OCA\Polls\Db\VoteMapper;
33
use OCA\Polls\Db\PollMapper;
34
use OCA\Polls\Db\Vote;
35
use OCA\Polls\Model\Acl;
36
37
class VoteService {
38
39
	/** @var VoteMapper */
40
	private $voteMapper;
41
42
	/** @var PollMapper */
43
	private $pollMapper;
44
45
	/** @var Vote */
46
	private $vote;
47
48
	/** @var OptionMapper */
49
	private $optionMapper;
50
51
	/** @var AnonymizeService */
52
	private $anonymizer;
53
54
	/** @var LogService */
55
	private $logService;
56
57
	/** @var Acl */
58
	private $acl;
59
60
	public function __construct(
61
		VoteMapper $voteMapper,
62
		PollMapper $pollMapper,
63
		Vote $vote,
64
		OptionMapper $optionMapper,
65
		AnonymizeService $anonymizer,
66
		LogService $logService,
67
		Acl $acl
68
	) {
69
		$this->voteMapper = $voteMapper;
70
		$this->pollMapper = $pollMapper;
71
		$this->vote = $vote;
72
		$this->optionMapper = $optionMapper;
73
		$this->anonymizer = $anonymizer;
74
		$this->logService = $logService;
75
		$this->acl = $acl;
76
	}
77
78
	/**
79
	 * Read all votes of a poll based on the poll id and return list as array
80
	 */
81
	public function list(?int $pollId = 0, string $token = ''): array {
82
		if ($token) {
83
			$this->acl->setToken($token);
84
		} else {
85
			$this->acl->setPollId($pollId)->request(Acl::PERMISSION_VIEW);
86
		}
87
88
		try {
89
			if (!$this->acl->isAllowed(Acl::PERMISSION_SEE_RESULTS)) {
90
				return $this->voteMapper->findByPollAndUser($this->acl->getpollId(), $this->acl->getUserId());
91
			} elseif (!$this->acl->isAllowed(Acl::PERMISSION_SEE_USERNAMES)) {
92
				$this->anonymizer->set($this->acl->getpollId(), $this->acl->getUserId());
93
				return $this->anonymizer->getVotes();
94
			} else {
95
				return $this->voteMapper->findByPoll($this->acl->getpollId());
96
			}
97
		} catch (DoesNotExistException $e) {
98
			return [];
99
		}
100
	}
101
102
	private function checkLimits(int $optionId, string $userId):void {
103
		$option = $this->optionMapper->find($optionId);
104
		$poll = $this->pollMapper->find($option->getPollId());
105
106
		// check, if the optionlimit is reached or exceeded, if one is set
107
		if ($poll->getOptionLimit() > 0) {
108
			if ($poll->getOptionLimit() <= count($this->voteMapper->getYesVotesByOption($option->getPollId(), $option->getPollOptionText()))) {
109
				throw new VoteLimitExceededException;
110
			}
111
		}
112
113
		// check if the votelimit for the user is reached or exceeded, if one is set
114
		if ($poll->getVoteLimit() > 0) {
115
			$pollOptionTexts = [];
116
			$validVotes = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $validVotes is dead and can be removed.
Loading history...
117
			$votecount = 0;
118
119
			$options = $this->optionMapper->findByPoll($option->getPollId());
120
			$votes = $this->voteMapper->getYesVotesByParticipant($option->getPollId(), $userId);
121
122
			// Only count votes, which match to an actual existing option.
123
			// Explanation: If an option is deleted, the corresponding votes are not deleted.
124
125
			// create an array of pollOptionTexts
126
			foreach ($options as $element) {
127
				$pollOptionTexts[] = $element->getPollOptionText();
128
			}
129
130
			// only count relevant votes for the limit
131
			foreach ($votes as $vote) {
132
				if (in_array($vote->getVoteOptionText(), $pollOptionTexts)) {
133
					$votecount++;
134
				}
135
			}
136
			if ($poll->getVoteLimit() <= $votecount) {
137
				throw new VoteLimitExceededException;
138
			}
139
		}
140
	}
141
142
	/**
143
	 * Set vote
144
	 */
145
	public function set(int $optionId, string $setTo, string $token = ''): Vote {
146
		$option = $this->optionMapper->find($optionId);
147
148
		if ($token) {
149
			$this->acl->setToken($token)->request(Acl::PERMISSION_VOTE);
150
			if (intval($option->getPollId()) !== $this->acl->getPollId()) {
151
				throw new NotAuthorizedException;
152
			}
153
		} else {
154
			$this->acl->setPollId($option->getPollId())->request(Acl::PERMISSION_VOTE);
155
		}
156
157
		if ($setTo === 'yes') {
158
			$this->checkLimits($optionId, $this->acl->getUserId());
159
		}
160
161
		try {
162
			$this->vote = $this->voteMapper->findSingleVote($this->acl->getPollId(), $option->getPollOptionText(), $this->acl->getUserId());
163
			$this->vote->setVoteAnswer($setTo);
164
			$this->voteMapper->update($this->vote);
165
		} catch (DoesNotExistException $e) {
166
			// Vote does not exist, insert as new Vote
167
			$this->vote = new Vote();
168
169
			$this->vote->setPollId($this->acl->getPollId());
170
			$this->vote->setUserId($this->acl->getUserId());
171
			$this->vote->setVoteOptionText($option->getPollOptionText());
172
			$this->vote->setVoteOptionId($option->getId());
173
			$this->vote->setVoteAnswer($setTo);
174
			$this->voteMapper->insert($this->vote);
175
		}
176
		$this->logService->setLog($this->acl->getPollId(), Log::MSG_ID_SETVOTE, $this->vote->getUserId());
177
		return $this->vote;
178
	}
179
180
	/**
181
	 * Remove user from poll
182
	 */
183
	public function delete(int $pollId, string $userId): string {
184
		$this->acl->setPollId($pollId)->request(Acl::PERMISSION_EDIT);
185
		$this->voteMapper->deleteByPollAndUser($pollId, $userId);
186
		return $userId;
187
	}
188
}
189