Passed
Pull Request — master (#1281)
by René
03:47
created

PollService::listForAdmin()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 11
ccs 0
cts 6
cp 0
rs 10
cc 3
nc 3
nop 0
crap 12
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\EmptyTitleException;
28
use OCA\Polls\Exceptions\InvalidAccessException;
29
use OCA\Polls\Exceptions\InvalidShowResultsException;
30
use OCA\Polls\Exceptions\InvalidPollTypeException;
31
use OCA\Polls\Exceptions\NotAuthorizedException;
32
33
34
use OCA\Polls\Db\Log;
35
use OCA\Polls\Db\PollMapper;
36
use OCA\Polls\Db\Poll;
37
use OCA\Polls\Db\VoteMapper;
38
use OCA\Polls\Db\Vote;
39
use OCA\Polls\Model\Acl;
40
41
class PollService {
42
43
	/** @var string */
44
	private $userId;
45
46
	/** @var PollMapper */
47
	private $pollMapper;
48
49
	/** @var Poll */
50
	private $poll;
51
52
	/** @var VoteMapper */
53
	private $voteMapper;
54
55
	/** @var Vote */
56
	private $vote;
57
58
	/** @var LogService */
59
	private $logService;
60
61
	/** @var NotificationService */
62
	private $notificationService;
63
64
	/** @var MailService */
65
	private $mailService;
66
67
	/** @var Acl */
68
	private $acl;
69
70
	public function __construct(
71
		string $UserId,
72
		PollMapper $pollMapper,
73
		Poll $poll,
74
		VoteMapper $voteMapper,
75
		Vote $vote,
76
		LogService $logService,
77
		NotificationService $notificationService,
78
		MailService $mailService,
79
		Acl $acl
80
	) {
81
		$this->pollMapper = $pollMapper;
82
		$this->userId = $UserId;
83
		$this->poll = $poll;
84
		$this->voteMapper = $voteMapper;
85
		$this->vote = $vote;
86
		$this->logService = $logService;
87
		$this->notificationService = $notificationService;
88
		$this->mailService = $mailService;
89
		$this->acl = $acl;
90
	}
91
92
	/**
93
	 * Get list of polls
94
	 */
95
	public function list(): array {
96
		$pollList = [];
97
		try {
98
			$polls = $this->pollMapper->findForMe(\OC::$server->getUserSession()->getUser()->getUID());
99
100
			foreach ($polls as $poll) {
101
				try {
102
					$this->acl->setPoll($poll)->requestView();
103
					// TODO: Not the elegant way. Improvement neccessary
104
					$pollList[] = (object) array_merge(
105
						(array) json_decode(json_encode($poll)),
106
						(array) json_decode(json_encode($this->acl))
107
						);
108
				} catch (NotAuthorizedException $e) {
109
					continue;
110
				}
111
			}
112
		} catch (DoesNotExistException $e) {
113
			// silent catch
114
		}
115
		return $pollList;
116
	}
117
118
	/**
119
	 *   * Get list of polls
120
	 *
121
	 * @return Poll[]
122
	 */
123
	public function listForAdmin(): array {
124
		$pollList = [];
125
		$userId = \OC::$server->getUserSession()->getUser()->getUID();
126
		if (\OC::$server->getGroupManager()->isAdmin($userId)) {
127
			try {
128
				$pollList = $this->pollMapper->findForAdmin($userId);
129
			} catch (DoesNotExistException $e) {
130
				// silent catch
131
			}
132
		}
133
		return $pollList;
134
	}
135
136
	/**
137
	 * 	 * Update poll configuration
138
	 *
139
	 * @return Poll
140
	 */
141
	public function takeover(int $pollId): Poll {
142
		$this->poll = $this->pollMapper->find($pollId);
143
		$originalOwner = $this->poll->getOwner();
144
		$this->poll->setOwner(\OC::$server->getUserSession()->getUser()->getUID());
145
146
		$this->pollMapper->update($this->poll);
147
		$this->logService->setLog($this->poll->getId(), Log::MSG_ID_OWNERCHANGE);
148
149
		// send notification to the original owner
150
		$this->notificationService->createNotification([
151
			'msgId' => 'takeOverPoll',
152
			'objectType' => 'poll',
153
			'objectValue' => $this->poll->getId(),
154
			'recipient' => $originalOwner,
155
			'actor' => $this->userId
156
		]);
157
158
		return $this->poll;
159
	}
160
161
	/**
162
	 * 	 * get poll configuration
163
	 *
164
	 * @return Poll
165
	 */
166
	public function get(int $pollId): Poll {
167
		$this->poll = $this->pollMapper->find($pollId);
168
		$this->acl->setPoll($this->poll)->requestView();
169
		return $this->poll;
170
	}
171
172
	/**
173
	 * Add poll
174
	 */
175
	public function add(string $type, string $title) {
176
		if (!\OC::$server->getUserSession()->isLoggedIn()) {
177
			throw new NotAuthorizedException;
178
		}
179
180
		// Validate valuess
181
		if (!in_array($type, $this->getValidPollType())) {
182
			throw new InvalidPollTypeException('Invalid poll type');
183
		}
184
185
		if (!$title) {
186
			throw new EmptyTitleException('Title must not be empty');
187
		}
188
189
		$this->poll = new Poll();
190
		$this->poll->setType($type);
191
		$this->poll->setCreated(time());
192
		$this->poll->setOwner(\OC::$server->getUserSession()->getUser()->getUID());
193
		$this->poll->setTitle($title);
194
		$this->poll->setDescription('');
195
		$this->poll->setAccess(Poll::ACCESS_HIDDEN);
196
		$this->poll->setExpire(0);
197
		$this->poll->setAnonymous(0);
198
		$this->poll->setFullAnonymous(0);
199
		$this->poll->setAllowMaybe(0);
200
		$this->poll->setVoteLimit(0);
201
		$this->poll->setSettings('');
202
		$this->poll->setOptions('');
203
		$this->poll->setShowResults(Poll::SHOW_RESULTS_ALWAYS);
204
		$this->poll->setDeleted(0);
205
		$this->poll->setAdminAccess(0);
206
		$this->poll->setImportant(0);
207
		$this->poll = $this->pollMapper->insert($this->poll);
208
209
		$this->logService->setLog($this->poll->getId(), Log::MSG_ID_ADDPOLL);
210
211
		return $this->poll;
212
	}
213
214
	/**
215
	 * 	 * Update poll configuration
216
	 *
217
	 * @return Poll
218
	 */
219
	public function update(int $pollId, array $poll): Poll {
220
		$this->poll = $this->pollMapper->find($pollId);
221
		$this->acl->setPoll($this->poll)->requestEdit();
222
223
		// Validate valuess
224
		if (isset($poll['showResults']) && !in_array($poll['showResults'], $this->getValidShowResults())) {
225
			throw new InvalidShowResultsException('Invalid value for prop showResults');
226
		}
227
		if (isset($poll['access']) && !in_array($poll['access'], $this->getValidAccess())) {
228
			throw new InvalidAccessException('Invalid value for prop access ' . $poll['access']);
229
		}
230
231
		if (isset($poll['title']) && !$poll['title']) {
232
			throw new EmptyTitleException('Title must not be empty');
233
		}
234
		$this->poll->deserializeArray($poll);
235
236
		$this->pollMapper->update($this->poll);
237
		$this->logService->setLog($this->poll->getId(), Log::MSG_ID_UPDATEPOLL);
238
239
		return $this->poll;
240
	}
241
242
243
	/**
244
	 * 	 * Switch deleted status (move to deleted polls)
245
	 *
246
	 * @return Poll
247
	 */
248
	public function switchDeleted(int $pollId): Poll {
249
		$this->poll = $this->pollMapper->find($pollId);
250
		$this->acl->setPoll($this->poll)->requestDelete();
251
252
		if ($this->poll->getDeleted()) {
253
			$this->poll->setDeleted(0);
254
		} else {
255
			$this->poll->setDeleted(time());
256
		}
257
258
		$this->poll = $this->pollMapper->update($this->poll);
259
		$this->logService->setLog($this->poll->getId(), Log::MSG_ID_DELETEPOLL);
260
261
		if ($this->userId !== $this->poll->getOwner()) {
262
			// send notification to the original owner
263
			$this->notificationService->createNotification([
264
				'msgId' => 'softDeletePollByOther',
265
				'objectType' => 'poll',
266
				'objectValue' => $this->poll->getId(),
267
				'recipient' => $this->poll->getOwner(),
268
				'actor' => $this->userId,
269
				'pollTitle' => $this->poll->getTitle()
270
			]);
271
		}
272
273
		return $this->poll;
274
	}
275
276
	/**
277
	 * 	 * Delete poll
278
	 *
279
	 * @return Poll
280
	 */
281
	public function delete(int $pollId): Poll {
282
		$this->poll = $this->pollMapper->find($pollId);
283
		$this->acl->setPoll($this->poll)->requestDelete();
284
285
		$this->pollMapper->delete($this->poll);
286
287
		if ($this->userId !== $this->poll->getOwner()) {
288
			// send notification to the original owner
289
			$this->notificationService->createNotification([
290
				'msgId' => 'deletePollByOther',
291
				'objectType' => 'poll',
292
				'objectValue' => $this->poll->getId(),
293
				'recipient' => $this->poll->getOwner(),
294
				'actor' => $this->userId,
295
				'pollTitle' => $this->poll->getTitle()
296
			]);
297
		}
298
		return $this->poll;
299
	}
300
301
	/**
302
	 * 	 * Clone poll
303
	 *
304
	 * @return Poll
305
	 */
306
	public function clone(int $pollId): Poll {
307
		$origin = $this->pollMapper->find($pollId);
308
		$this->acl->setPoll($origin)->requestView();
309
310
		$this->poll = new Poll();
311
		$this->poll->setCreated(time());
312
		$this->poll->setOwner(\OC::$server->getUserSession()->getUser()->getUID());
313
		$this->poll->setTitle('Clone of ' . $origin->getTitle());
314
		$this->poll->setDeleted(0);
315
		$this->poll->setAccess(Poll::ACCESS_HIDDEN);
316
317
		$this->poll->setType($origin->getType());
318
		$this->poll->setDescription($origin->getDescription());
319
		$this->poll->setExpire($origin->getExpire());
320
		$this->poll->setAnonymous($origin->getAnonymous());
321
		$this->poll->setFullAnonymous($origin->getFullAnonymous());
322
		$this->poll->setAllowMaybe($origin->getAllowMaybe());
323
		$this->poll->setVoteLimit($origin->getVoteLimit());
324
		$this->poll->setSettings($origin->getSettings());
325
		$this->poll->setOptions($origin->getOptions());
326
		$this->poll->setShowResults($origin->getShowResults());
327
		$this->poll->setAdminAccess($origin->getAdminAccess());
328
		$this->poll->setImportant($origin->getImportant());
329
330
		return $this->pollMapper->insert($this->poll);
331
	}
332
333
	/**
334
	 * 	 * Collect email addresses from particitipants
335
	 *
336
	 * @return string[]
337
	 *
338
	 * @psalm-return array<int, string>
339
	 */
340
	public function getParticipantsEmailAddresses(int $pollId): array {
341
		$this->poll = $this->pollMapper->find($pollId);
342
		$this->acl->setPoll($this->poll)->requestEdit();
343
344
		$votes = $this->voteMapper->findParticipantsByPoll($pollId);
345
		$list = [];
346
		foreach ($votes as $vote) {
347
			$list[] = $vote->getDisplayName() . ' <' . $this->mailService->resolveEmailAddress($pollId, $vote->getUserId()) . '>';
348
		}
349
		return array_unique($list);
350
	}
351
352
	/**
353
	 * 	 * Get valid values for configuration options
354
	 *
355
	 * @return array
356
	 *
357
	 * @psalm-return array{pollType: mixed, access: mixed, showResults: mixed}
358
	 */
359
	public function getValidEnum(): array {
360
		return [
361
			'pollType' => $this->getValidPollType(),
362
			'access' => $this->getValidAccess(),
363
			'showResults' => $this->getValidShowResults()
364
		];
365
	}
366
367
	/**
368
	 * 	 * Get valid values for pollType
369
	 *
370
	 * @return string[]
371
	 *
372
	 * @psalm-return array{0: string, 1: string}
373
	 */
374
	private function getValidPollType(): array {
375
		return [Poll::TYPE_DATE, Poll::TYPE_TEXT];
376
	}
377
378
	/**
379
	 * 	 * Get valid values for access
380
	 *
381
	 * @return string[]
382
	 *
383
	 * @psalm-return array{0: string, 1: string}
384
	 */
385
	private function getValidAccess(): array {
386
		return [Poll::ACCESS_HIDDEN, Poll::ACCESS_PUBLIC];
387
	}
388
389
	/**
390
	 * 	 * Get valid values for showResult
391
	 *
392
	 * @return string[]
393
	 *
394
	 * @psalm-return array{0: string, 1: string, 2: string}
395
	 */
396
	private function getValidShowResults(): array {
397
		return [Poll::SHOW_RESULTS_ALWAYS, Poll::SHOW_RESULTS_CLOSED, Poll::SHOW_RESULTS_NEVER];
398
	}
399
}
400