PollService::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 22
ccs 0
cts 17
cp 0
rs 9.9332
cc 1
nc 1
nop 10
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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