PollService::listForAdmin()   A
last analyzed

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