Completed
Pull Request — master (#429)
by René
04:19
created

PageController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 17
nc 1
nop 17
dl 0
loc 36
rs 9.7
c 0
b 0
f 0
ccs 18
cts 18
cp 1
crap 1

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 Vinzenz Rosenkranz <[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\Controller;
25
26
use OCA\Polls\Db\Comment;
27
use OCA\Polls\Db\CommentMapper;
28
use OCA\Polls\Db\Event;
29
use OCA\Polls\Db\EventMapper;
30
use OCA\Polls\Db\Notification;
31
use OCA\Polls\Db\NotificationMapper;
32
use OCA\Polls\Db\Options;
33
use OCA\Polls\Db\OptionsMapper;
34
use OCA\Polls\Db\Votes;
35
use OCA\Polls\Db\VotesMapper;
36
use OCP\AppFramework\Controller;
37
use OCP\AppFramework\Db\DoesNotExistException;
38
use OCP\AppFramework\Http\ContentSecurityPolicy;
39
use OCP\AppFramework\Http\JSONResponse;
40
use OCP\AppFramework\Http\RedirectResponse;
41
use OCP\AppFramework\Http\TemplateResponse;
42
use OCP\IAvatarManager;
43
use OCP\IConfig;
44
use OCP\IGroupManager;
45
use OCP\IL10N;
46
use OCP\ILogger;
47
use OCP\IRequest;
48
use OCP\IURLGenerator;
49
use OCP\IUser;
50
use OCP\IUserManager;
51
use OCP\L10N\IFactory;
52
use OCP\Mail\IMailer;
53
use OCP\Security\ISecureRandom;
54
use OCP\User; //To do: replace according to API
55
use OCP\Util;
56
57
class PageController extends Controller {
58
59
	private $userId;
60
	private $config;
61
	private $commentMapper;
62
	private $eventMapper;
63
	private $notificationMapper;
64
	private $optionsMapper;
65
	private $votesMapper;
66
	private $urlGenerator;
67
	private $userMgr;
68
	private $avatarManager;
69
	private $logger;
70
	private $trans;
71
	private $transFactory;
72
	private $groupManager;
73
	private $mailer;
74
75
	/**
76
	 * PageController constructor.
77
	 * @param string $appName
78
	 * @param IRequest $request
79
	 * @param IConfig $config
80
	 * @param IUserManager $userMgr
81
	 * @param IGroupManager $groupManager
82
	 * @param IAvatarManager $avatarManager
83
	 * @param ILogger $logger
84
	 * @param IL10N $trans
85
	 * @param IFactory $transFactory
86
	 * @param IURLGenerator $urlGenerator
87
	 * @param string $userId
88
	 * @param CommentMapper $commentMapper
89
	 * @param OptionsMapper $optionsMapper
90
	 * @param EventMapper $eventMapper
91
	 * @param NotificationMapper $notificationMapper
92
	 * @param VotesMapper $VotesMapper
93
	 * @param IMailer $mailer
94
	 */
95 1
	public function __construct(
96
		$appName,
97
		IRequest $request,
98
		IConfig $config,
99
		IUserManager $userMgr,
100
		IGroupManager $groupManager,
101
		IAvatarManager $avatarManager,
102
		ILogger $logger,
103
		IL10N $trans,
104
		IFactory $transFactory,
105
		IURLGenerator $urlGenerator,
106
		$userId,
107
		CommentMapper $commentMapper,
108
		OptionsMapper $optionsMapper,
109
		EventMapper $eventMapper,
110
		NotificationMapper $notificationMapper,
111
		VotesMapper $VotesMapper,
112
		IMailer $mailer
113
	) {
114 1
		parent::__construct($appName, $request);
115 1
		$this->request = $request;
116 1
		$this->config = $config;
117 1
		$this->userMgr = $userMgr;
118 1
		$this->groupManager = $groupManager;
119 1
		$this->avatarManager = $avatarManager;
120 1
		$this->logger = $logger;
121 1
		$this->trans = $trans;
122 1
		$this->transFactory = $transFactory;
123 1
		$this->urlGenerator = $urlGenerator;
124 1
		$this->userId = $userId;
125 1
		$this->commentMapper = $commentMapper;
126 1
		$this->optionsMapper = $optionsMapper;
127 1
		$this->eventMapper = $eventMapper;
128 1
		$this->notificationMapper = $notificationMapper;
129 1
		$this->votesMapper = $VotesMapper;
130 1
		$this->mailer = $mailer;
131 1
	}
132
133
	/**
134
	 * @NoAdminRequired
135
	 * @NoCSRFRequired
136
	 */
137 1
	public function index() {
138 1
		$polls = $this->eventMapper->findAllForUserWithInfo($this->userId);
139 1
		$comments = $this->commentMapper->findDistinctByUser($this->userId);
140 1
		$votes = $this->votesMapper->findDistinctByUser($this->userId);
141 1
		$response = new TemplateResponse('polls', 'main.tmpl', [
142 1
			'polls' => $polls,
143 1
			'comments' => $comments,
144 1
			'votes' => $votes,
145 1
			'userId' => $this->userId,
146 1
			'userMgr' => $this->userMgr,
147 1
			'urlGenerator' => $this->urlGenerator
148
		]);
149 1
		$csp = new ContentSecurityPolicy();
150 1
		$response->setContentSecurityPolicy($csp);
151 1
		return $response;
152
	}
153
154
	/**
155
	 * @param int $pollId
156
	 * @param string $from
157
	 */
158
	private function sendNotifications($pollId, $from) {
159
		$poll = $this->eventMapper->find($pollId);
160
		$notifications = $this->notificationMapper->findAllByPoll($pollId);
161
		foreach ($notifications as $notification) {
162
			if ($from === $notification->getUserId()) {
163
				continue;
164
			}
165
			$recUser = $this->userMgr->get($notification->getUserId());
166
			if (!$recUser instanceof IUser) {
167
				continue;
168
			}
169
			$email = \OC::$server->getConfig()->getUserValue($notification->getUserId(), 'settings', 'email');
170
			if ($email === null || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
171
				continue;
172
			}
173
			$url = $this->urlGenerator->getAbsoluteURL(
174
				$this->urlGenerator->linkToRoute('polls.page.goto_poll',
175
					array('hash' => $poll->getHash()))
176
			);
177
178
			$sendUser = $this->userMgr->get($from);
179
			$sender = $from;
180
			if ($sendUser instanceof IUser) {
181
				$sender = $sendUser->getDisplayName();
182
			}
183
184
			$lang = $this->config->getUserValue($notification->getUserId(), 'core', 'lang');
185
			$trans = $this->transFactory->get('polls', $lang);
186
			$emailTemplate = $this->mailer->createEMailTemplate('polls.Notification', [
187
				'user' => $sender,
188
				'title' => $poll->getTitle(),
189
				'link' => $url,
190
			]);
191
			$emailTemplate->setSubject($trans->t('Polls App - New Activity'));
0 ignored issues
show
Bug introduced by
The method setSubject() does not exist on OCP\Mail\IEMailTemplate. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

191
			$emailTemplate->/** @scrutinizer ignore-call */ 
192
                   setSubject($trans->t('Polls App - New Activity'));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
192
			$emailTemplate->addHeader();
193
			$emailTemplate->addHeading($trans->t('Polls App - New Activity'), false);
194
195
			$emailTemplate->addBodyText(str_replace(
196
				['{user}', '{title}'],
197
				[$sender, $poll->getTitle()],
198
				$trans->t('{user} participated in the poll "{title}"')
199
			));
200
201
			$emailTemplate->addBodyButton(
202
				htmlspecialchars($trans->t('Go to poll')),
203
				$url,
204
				false
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $plainText of OCP\Mail\IEMailTemplate::addBodyButton(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

204
				/** @scrutinizer ignore-type */ false
Loading history...
205
			);
206
207
			$emailTemplate->addFooter();
208
			try {
209
				$message = $this->mailer->createMessage();
210
				$message->setTo([$email => $recUser->getDisplayName()]);
211
				$message->useTemplate($emailTemplate);
212
				$this->mailer->send($message);
213
			} catch (\Exception $e) {
214
				$this->logger->logException($e, ['app' => 'polls']);
215
			}
216
		}
217
	}
218
219
	/**
220
	 * @NoAdminRequired
221
	 * @NoCSRFRequired
222
	 * @PublicPage
223
	 * @param string $hash
224
	 * @return TemplateResponse
225
	 */
226
	public function gotoPoll($hash) {
227
		try {
228
			$poll = $this->eventMapper->findByHash($hash);
229
		} catch (DoesNotExistException $e) {
230
			return new TemplateResponse('polls', 'no.acc.tmpl', []);
231
		}
232
		$options = $this->optionsMapper->findByPoll($poll->getId());
233
		$votes = $this->votesMapper->findByPoll($poll->getId());
234
		$participants = $this->votesMapper->findParticipantsByPoll($poll->getId());
235
		$comments = $this->commentMapper->findByPoll($poll->getId());
236
237
		try {
238
			$notification = $this->notificationMapper->findByUserAndPoll($poll->getId(), $this->userId);
239
		} catch (DoesNotExistException $e) {
240
			$notification = null;
241
		}
242
		if ($this->hasUserAccess($poll)) {
243
			return new TemplateResponse('polls', 'goto.tmpl', [
244
				'poll' => $poll,
245
				'options' => $options,
246
				'comments' => $comments,
247
				'votes' => $votes,
248
				'participant' => $participants,
249
				'notification' => $notification,
250
				'userId' => $this->userId,
251
				'userMgr' => $this->userMgr,
252
				'urlGenerator' => $this->urlGenerator,
253
				'avatarManager' => $this->avatarManager
254
			]);
255
		} else {
256
			User::checkLoggedIn();
257
			return new TemplateResponse('polls', 'no.acc.tmpl', []);
258
		}
259
	}
260
261
	/**
262
	 * @NoAdminRequired
263
	 * @NoCSRFRequired
264
	 * @param int $pollId
265
	 * @return TemplateResponse|RedirectResponse
266
	 */
267
	public function deletePoll($pollId) {
268
		$pollToDelete = $this->eventMapper->find($pollId);
269
		if ($this->userId !== $pollToDelete->getOwner() && !$this->groupManager->isAdmin($this->userId)) {
270
			return new TemplateResponse('polls', 'no.delete.tmpl');
271
		}
272
		$poll = new Event();
273
		$poll->setId($pollId);
274
		$this->commentMapper->deleteByPoll($pollId);
275
		$this->votesMapper->deleteByPoll($pollId);
276
		$this->optionsMapper->deleteByPoll($pollId);
277
		$this->eventMapper->delete($poll);
278
		$url = $this->urlGenerator->linkToRoute('polls.page.index');
279
		return new RedirectResponse($url);
280
	}
281
282
	/**
283
	 * @NoAdminRequired
284
	 * @NoCSRFRequired
285
	 * @param string $hash
286
	 * @return TemplateResponse
287
	 */
288
	public function editPoll($hash) {
289
		return new TemplateResponse('polls', 'create.tmpl', [
290
			'urlGenerator' => $this->urlGenerator,
291
 			'hash' => $hash
292
		]);
293
	}
294
295
	/**
296
	 * @NoAdminRequired
297
	 * @NoCSRFRequired
298
	 */
299
	public function createPoll() {
300
		return new TemplateResponse('polls', 'create.tmpl',
301
			['urlGenerator' => $this->urlGenerator]);
302
	}
303
304
	/**
305
	 * @NoAdminRequired
306
	 * @NoCSRFRequired
307
	 * @PublicPage
308
	 * @param int $pollId
309
	 * @param string $userId
310
	 * @param string $answers
311
	 * @param string $options
312
	 * @param bool $receiveNotifications
313
	 * @param bool $changed
314
	 * @return RedirectResponse
315
	 */
316
	public function insertVote($pollId, $userId, $answers, $options, $receiveNotifications, $changed) {
317
		if ($this->userId !== null) {
318
			if ($receiveNotifications) {
319
				try {
320
					//check if user already set notification for this poll
321
					$this->notificationMapper->findByUserAndPoll($pollId, $userId);
322
				} catch (DoesNotExistException $e) {
323
					//insert if not exist
324
					$not = new Notification();
325
					$not->setUserId($userId);
326
					$not->setPollId($pollId);
327
					$this->notificationMapper->insert($not);
328
				}
329
			} else {
330
				try {
331
					//delete if entry is in db
332
					$not = $this->notificationMapper->findByUserAndPoll($pollId, $userId);
333
					$this->notificationMapper->delete($not);
334
				} catch (DoesNotExistException $e) {
335
					//doesn't exist in db, nothing to do
336
				}
337
			}
338
		}
339
		$poll = $this->eventMapper->find($pollId);
340
341
		if ($changed) {
342
			$options = json_decode($options);
343
			$answers = json_decode($answers);
344
			$count_options = count($options);
345
			$this->votesMapper->deleteByPollAndUser($pollId, $userId);
346
347
			for ($i = 0; $i < $count_options; $i++) {
348
				$vote = new Votes();
349
				$vote->setPollId($pollId);
350
				$vote->setUserId($userId);
351
				$vote->setVoteOptionText(htmlspecialchars($options[$i]));
352
				$vote->setVoteAnswer($answers[$i]);
353
				$this->votesMapper->insert($vote);
354
355
			}
356
			$this->sendNotifications($pollId, $userId);
357
		}
358
		$hash = $poll->getHash();
359
		$url = $this->urlGenerator->linkToRoute('polls.page.goto_poll', ['hash' => $hash]);
360
		return new RedirectResponse($url);
361
	}
362
363
	/**
364
	 * @NoAdminRequired
365
	 * @NoCSRFRequired
366
	 * @PublicPage
367
	 * @param int $pollId
368
	 * @param string $userId
369
	 * @param string $commentBox
370
	 * @return JSONResponse
371
	 */
372
	public function insertComment($pollId, $userId, $commentBox) {
373
		$comment = new Comment();
374
		$comment->setPollId($pollId);
375
		$comment->setUserId($userId);
376
		$comment->setComment($commentBox);
377
		$comment->setDt(date('Y-m-d H:i:s'));
378
		$this->commentMapper->insert($comment);
379
		$this->sendNotifications($pollId, $userId);
380
		$timeStamp = time();
381
		$displayName = $userId;
382
		$user = $this->userMgr->get($userId);
383
		if ($user !== null) {
384
			$displayName = $user->getDisplayName();
385
		}
386
		return new JSONResponse(array(
387
			'userId' => $userId,
388
			'displayName' => $displayName,
389
			'timeStamp' => $timeStamp * 100,
390
			'date' => date('Y-m-d H:i:s', $timeStamp),
391
			'relativeNow' => $this->trans->t('just now'),
392
			'comment' => $commentBox
393
		));
394
	}
395
396
	/**
397
	 * @NoAdminRequired
398
	 * @NoCSRFRequired
399
	 * @param string $searchTerm
400
	 * @param string $groups
401
	 * @param string $users
402
	 * @return array
403
	 */
404
	public function search($searchTerm, $groups, $users) {
405
		return array_merge($this->searchForGroups($searchTerm, $groups), $this->searchForUsers($searchTerm, $users));
406
	}
407
408
	/**
409
	 * @NoAdminRequired
410
	 * @NoCSRFRequired
411
	 * @param string $searchTerm
412
	 * @param string $groups
413
	 * @return array
414
	 */
415
	public function searchForGroups($searchTerm, $groups) {
416
		$selectedGroups = json_decode($groups);
417
		$groups = $this->groupManager->search($searchTerm);
418
		$gids = array();
419
		$sgids = array();
420
		foreach ($selectedGroups as $sg) {
421
			$sgids[] = str_replace('group_', '', $sg);
422
		}
423
		foreach ($groups as $g) {
424
			$gids[] = $g->getGID();
425
		}
426
		$diffGids = array_diff($gids, $sgids);
427
		$gids = array();
428
		foreach ($diffGids as $g) {
429
			$gids[] = ['gid' => $g, 'isGroup' => true];
430
		}
431
		return $gids;
432
	}
433
434
	/**
435
	 * @NoAdminRequired
436
	 * @NoCSRFRequired
437
	 * @param string $searchTerm
438
	 * @param string $users
439
	 * @return array
440
	 */
441
	public function searchForUsers($searchTerm, $users) {
442
		$selectedUsers = json_decode($users);
443
		Util::writeLog('polls', print_r($selectedUsers, true), Util::ERROR);
444
		$userNames = $this->userMgr->searchDisplayName($searchTerm);
445
		$users = array();
446
		$sUsers = array();
447
		foreach ($selectedUsers as $su) {
448
			$sUsers[] = str_replace('user_', '', $su);
449
		}
450
		foreach ($userNames as $u) {
451
			$allreadyAdded = false;
452
			foreach ($sUsers as &$su) {
453
				if ($su === $u->getUID()) {
454
					unset($su);
455
					$allreadyAdded = true;
456
					break;
457
				}
458
			}
459
			if (!$allreadyAdded) {
460
				$users[] = array('uid' => $u->getUID(), 'displayName' => $u->getDisplayName(), 'isGroup' => false);
461
			} else {
462
				continue;
463
			}
464
		}
465
		return $users;
466
	}
467
468
	/**
469
	 * @NoAdminRequired
470
	 * @NoCSRFRequired
471
	 * @param string $username
472
	 * @return string
473
	 */
474
	public function getDisplayName($username) {
475
		return $this->userMgr->get($username)->getDisplayName();
476
	}
477
478
	/**
479
	 * @return \OCP\IGroup[]
480
	 */
481
	private function getGroups() {
482
		if (class_exists('\OC_Group')) {
483
			// Nextcloud <= 11, ownCloud
484
			return \OC_Group::getUserGroups($this->userId);
0 ignored issues
show
Bug introduced by
The type OC_Group was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
485
		}
486
		// Nextcloud >= 12
487
		$groups = $this->groupManager->getUserGroups(\OC::$server->getUserSession()->getUser());
488
		return array_map(function($group) {
489
			return $group->getGID();
490
		}, $groups);
491
	}
492
493
	/**
494
	 * Check if user has access to this poll
495
	 *
496
	 * @param Event $poll
497
	 * @return bool
498
	 */
499
	private function hasUserAccess($poll) {
500
		$access = $poll->getAccess();
501
		$owner = $poll->getOwner();
502
		if ($access === 'public' || $access === 'hidden') {
503
			return true;
504
		}
505
		if ($this->userId === null) {
506
			return false;
507
		}
508
		if ($access === 'registered') {
509
			return true;
510
		}
511
		if ($owner === $this->userId) {
512
			return true;
513
		}
514
		Util::writeLog('polls', $this->userId, Util::ERROR);
515
		$userGroups = $this->getGroups();
516
		$arr = explode(';', $access);
517
		foreach ($arr as $item) {
518
			if (strpos($item, 'group_') === 0) {
519
				$grp = substr($item, 6);
520
				foreach ($userGroups as $userGroup) {
521
					if ($userGroup === $grp) {
522
						return true;
523
					}
524
				}
525
			} else {
526
				if (strpos($item, 'user_') === 0) {
527
					$usr = substr($item, 5);
528
					if ($usr === $this->userId) {
529
						return true;
530
					}
531
				}
532
			}
533
		}
534
		return false;
535
	}
536
	/**
537
	 * Check if user is owner of this poll
538
	 *
539
	 * @param Event $poll
540
	 * @return bool
541
	 */
542
543
	private function userIsOwner($poll) {
544
		$owner = $poll->getOwner();
545
546
		if ($owner === $this->userId) {
547
			return true;
548
		}
549
		Util::writeLog('polls', $this->userId, Util::ERROR);
550
		return false;
551
	}
552
}
553