Completed
Push — master ( cf3397...88c060 )
by René
24s queued 11s
created

VoteService::delete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
nc 1
nop 2
crap 2
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
			$votecount = 0;
117
118
			$options = $this->optionMapper->findByPoll($option->getPollId());
119
			$votes = $this->voteMapper->getYesVotesByParticipant($option->getPollId(), $userId);
120
121
			// Only count votes, which match to an actual existing option.
122
			// Explanation: If an option is deleted, the corresponding votes are not deleted.
123
124
			// create an array of pollOptionTexts
125
			foreach ($options as $element) {
126
				$pollOptionTexts[] = $element->getPollOptionText();
127
			}
128
129
			// only count relevant votes for the limit
130
			foreach ($votes as $vote) {
131
				if (in_array($vote->getVoteOptionText(), $pollOptionTexts)) {
132
					$votecount++;
133
				}
134
			}
135
			if ($poll->getVoteLimit() <= $votecount) {
136
				throw new VoteLimitExceededException;
137
			}
138
		}
139
	}
140
141
	/**
142
	 * Set vote
143
	 */
144
	public function set(int $optionId, string $setTo, string $token = ''): Vote {
145
		$option = $this->optionMapper->find($optionId);
146
147
		if ($token) {
148
			$this->acl->setToken($token)->request(Acl::PERMISSION_VOTE);
149
			if (intval($option->getPollId()) !== $this->acl->getPollId()) {
150
				throw new NotAuthorizedException;
151
			}
152
		} else {
153
			$this->acl->setPollId($option->getPollId())->request(Acl::PERMISSION_VOTE);
154
		}
155
156
		if ($setTo === 'yes') {
157
			$this->checkLimits($optionId, $this->acl->getUserId());
158
		}
159
160
		try {
161
			$this->vote = $this->voteMapper->findSingleVote($this->acl->getPollId(), $option->getPollOptionText(), $this->acl->getUserId());
162
			$this->vote->setVoteAnswer($setTo);
163
			$this->voteMapper->update($this->vote);
164
		} catch (DoesNotExistException $e) {
165
			// Vote does not exist, insert as new Vote
166
			$this->vote = new Vote();
167
168
			$this->vote->setPollId($this->acl->getPollId());
169
			$this->vote->setUserId($this->acl->getUserId());
170
			$this->vote->setVoteOptionText($option->getPollOptionText());
171
			$this->vote->setVoteOptionId($option->getId());
172
			$this->vote->setVoteAnswer($setTo);
173
			$this->voteMapper->insert($this->vote);
174
		}
175
		$this->logService->setLog($this->acl->getPollId(), Log::MSG_ID_SETVOTE, $this->vote->getUserId());
176
		return $this->vote;
177
	}
178
179
	/**
180
	 * Remove user from poll
181
	 */
182
	public function delete(int $pollId, string $userId): string {
183
		$this->acl->setPollId($pollId)->request(Acl::PERMISSION_EDIT);
184
		$this->voteMapper->deleteByPollAndUser($pollId, $userId);
185
		return $userId;
186
	}
187
}
188