Passed
Pull Request — master (#1128)
by René
04:52
created

MailService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 26
ccs 0
cts 21
cp 0
rs 9.8666
cc 1
nc 1
nop 12
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 Exception;
27
28
use OCP\IUser;
29
use OCP\IUserManager;
30
use OCP\IGroupManager;
31
use OCP\IConfig;
32
use OCP\IURLGenerator;
33
use OCP\IL10N;
34
use OCP\L10N\IFactory;
35
use OCP\Mail\IMailer;
36
use OCP\Mail\IEMailTemplate;
37
38
use OCA\Polls\Db\SubscriptionMapper;
39
use OCA\Polls\Db\PollMapper;
40
use OCA\Polls\Db\ShareMapper;
41
use OCA\Polls\Db\Share;
42
use OCA\Polls\Db\LogMapper;
43
44
class MailService {
45
46
	/** @var IUserManager */
47
	private $userManager;
48
49
	/** @var IGroupManager */
50
	private $groupManager;
51
52
	/** @var IConfig */
53
	private $config;
54
55
	/** @var IURLGenerator */
56
	private $urlGenerator;
57
58
	/** @var IL10N */
59
	private $trans;
60
61
	/** @var IFactory */
62
	private $transFactory;
63
64
	/** @var IMailer */
65
	private $mailer;
66
67
	/** @var SubscriptionMapper */
68
	private $subscriptionMapper;
69
70
	/** @var ShareMapper */
71
	private $shareMapper;
72
73
	/** @var PollMapper */
74
	private $pollMapper;
75
76
	/** @var LogMapper */
77
	private $logMapper;
78
79
	/** @var ContactsService */
80
	private $contactsService;
81
82
	/**
83
	 * MailService constructor.
84
	 * @param IUserManager $userManager
85
	 * @param IGroupManager $groupManager
86
	 * @param IConfig $config
87
	 * @param IURLGenerator $urlGenerator
88
	 * @param IL10N $trans
89
	 * @param IFactory $transFactory
90
	 * @param IMailer $mailer
91
	 * @param SubscriptionMapper $subscriptionMapper
92
	 * @param ShareMapper $shareMapper
93
	 * @param PollMapper $pollMapper
94
	 * @param LogMapper $logMapper
95
	 * @param ContactsService $contactsService
96
	 */
97
98
	public function __construct(
99
		IUserManager $userManager,
100
		IGroupManager $groupManager,
101
		IConfig $config,
102
		IURLGenerator $urlGenerator,
103
		IL10N $trans,
104
		IFactory $transFactory,
105
		IMailer $mailer,
106
		ShareMapper $shareMapper,
107
		SubscriptionMapper $subscriptionMapper,
108
		PollMapper $pollMapper,
109
		LogMapper $logMapper,
110
		ContactsService $contactsService
111
	) {
112
		$this->config = $config;
113
		$this->userManager = $userManager;
114
		$this->groupManager = $groupManager;
115
		$this->urlGenerator = $urlGenerator;
116
		$this->trans = $trans;
117
		$this->transFactory = $transFactory;
118
		$this->mailer = $mailer;
119
		$this->shareMapper = $shareMapper;
120
		$this->subscriptionMapper = $subscriptionMapper;
121
		$this->pollMapper = $pollMapper;
122
		$this->logMapper = $logMapper;
123
		$this->contactsService = $contactsService;
124
	}
125
126
127
	/**
128
	 * sendMail - Send eMail and evaluate recipient's mail address
129
	 * and displayname if $userId is a site user
130
	 * @param IEmailTemplate $emailTemplate
131
	 * @param String $userId
132
	 * @param String $emailAddress, ignored, when $userId is set
133
	 * @param String $displayName, ignored, when $userId is set
134
	 * @return String
135
	 */
136
137
	private function sendMail($emailTemplate, $userId = '', $emailAddress = '', $displayName = '') {
138
		if ($this->userManager->get($userId) instanceof IUser) {
139
			$emailAddress = \OC::$server->getConfig()->getUserValue($userId, 'settings', 'email');
140
			$displayName = $this->userManager->get($userId)->getDisplayName();
141
		}
142
143
		if (!$emailAddress || !filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
144
			throw new Exception('Invalid email address (' . $emailAddress . ')');
145
		}
146
147
		try {
148
			$message = $this->mailer->createMessage();
149
			$message->setTo([$emailAddress => $displayName]);
150
			$message->useTemplate($emailTemplate);
151
			$this->mailer->send($message);
152
153
			return null;
154
		} catch (\Exception $e) {
155
			\OC::$server->getLogger()->logException($e, ['app' => 'polls']);
156
			throw $e;
157
		}
158
	}
159
160
161
	/**
162
	 * @param integer $pollId
163
	 * @param string $userId
164
	 * @return string
165
	 */
166
	public function resolveEmailAddress($pollId, $userId) {
167
		if ($this->userManager->get($userId) instanceof IUser) {
168
			return \OC::$server->getConfig()->getUserValue($userId, 'settings', 'email');
169
		}
170
171
		// if $userId is no site user, eval via shares
172
		try {
173
			$share = $this->shareMapper->findByPollAndUser($pollId, $userId);
174
			if ($share->getUserEmail()) {
175
				return $share->getUserEmail();
176
			}
177
		} catch (\Exception $e) {
178
			// catch silently
179
		}
180
		return $userId;
181
	}
182
183
184
	/**
185
	 * @param Share $share
186
	 * @param String $defaultLang
187
	 * @param String $skipUser
188
	 * @return Array $recipients
189
	 */
190
	private function getRecipientsByShare($share, $defaultLang = 'en', $skipUser = null) {
191
		$recipients = [];
192
193
		$tokenLink = $this->urlGenerator->getAbsoluteURL(
194
			$this->urlGenerator->linkToRoute(
195
				'polls.page.vote_publicpublic',
196
				['token' => $share->getToken()]
197
			)
198
		);
199
200
		$internalLink = $this->urlGenerator->getAbsoluteURL(
201
			$this->urlGenerator->linkToRoute(
202
				'polls.page.indexvote',
203
				['id' => $share->getPollId()]
204
			)
205
		);
206
207
		if ($share->getType() === Share::TYPE_USER) {
208
			$user = new User(User::TYPE_USER, $share->getUserId());
0 ignored issues
show
Bug introduced by
The type OCA\Polls\Service\User 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...
209
			$recipients[] = [
210
				'userId' => $user->getUserId(),
211
				'eMailAddress' => $user->getEmailAddress(),
212
				'displayName' => $user->getDisplayName(),
213
				'language' => $user->getLanguage(),
214
				'link' => $internalLink,
215
			];
216
		} elseif ($share->getType() === Share::TYPE_EMAIL) {
217
			$user = new User(User::TYPE_EMAIL, $share->getUserId());
218
			$recipients[] = [
219
				'userId' => $user->getUserId(),
220
				'eMailAddress' => $user->getEmailAddress(),
221
				'displayName' => $user->getDisplayName(),
222
				'language' => $defaultLang,
223
				'link' => $tokenLink,
224
			];
225
		} elseif ($share->getType() === Share::TYPE_CONTACT) {
226
			$contacts = $this->contactsService->getContacts($share->getUserId(), ['FN', 'UID']);
227
			if (count($contacts)) {
228
				$user = $contacts[0];
229
230
				$recipients[] = [
231
					'userId' => $user->getUserId(),
232
					'eMailAddress' => $user->getEmailAddress(),
233
					'displayName' => $user->getDisplayname(),
234
					'language' => $defaultLang,
235
					'link' => $tokenLink,
236
				];
237
			} else {
238
				return;
239
			}
240
		} elseif ($share->getType() === Share::TYPE_EXTERNAL) {
241
			$recipients[] = [
242
				'userId' => $share->getUserId(),
243
				'eMailAddress' => $share->getUserEmail(),
244
				'displayName' => $share->getUserId(),
245
				'language' => $defaultLang,
246
				'link' => $tokenLink,
247
			];
248
		} elseif ($share->getType() === Share::TYPE_GROUP) {
249
			$groupMembers = array_keys($this->groupManager->displayNamesInGroup($share->getUserId()));
250
251
			foreach ($groupMembers as $user) {
252
				if ($skipUser === $user || !$this->userManager->get($user)->isEnabled()) {
253
					continue;
254
				}
255
				$user = new User(User::TYPE_USER, $user->getUserId());
256
257
				$recipients[] = [
258
					'userId' => $user->getUserId(),
259
					'eMailAddress' => $user->getEmailAddress(),
260
					'displayName' => $user->getDisplayName(),
261
					'language' => $user->getLanguage(),
262
					'link' => $internalLink,
263
				];
264
			}
265
		}
266
		return $recipients;
267
	}
268
269
	/**
270
	 * @param string $token
271
	 */
272
	public function sendInvitationMail($token) {
273
		$share = $this->shareMapper->findByToken($token);
274
		$poll = $this->pollMapper->find($share->getPollId());
275
		$owner = $this->userManager->get($poll->getOwner());
276
		$sentMails = [];
277
		$abortedMails = [];
278
279
		$recipients = $this->getRecipientsByShare(
280
			$this->shareMapper->findByToken($token),
281
			$this->config->getUserValue($poll->getOwner(), 'core', 'lang'),
282
			$poll->getOwner()
283
		);
284
285
		foreach ($recipients as $recipient) {
286
			$trans = $this->transFactory->get('polls', $recipient['language']);
287
288
289
			$emailTemplate = $this->mailer->createEMailTemplate('polls.Invitation', [
290
				'owner' => $owner->getDisplayName(),
291
				'title' => $poll->getTitle(),
292
				'link' => $recipient['link']
293
			]);
294
295
			$emailTemplate->setSubject($trans->t('Poll invitation "%s"', $poll->getTitle()));
296
			$emailTemplate->addHeader();
297
			$emailTemplate->addHeading($trans->t('Poll invitation "%s"', $poll->getTitle()), false);
298
299
			$emailTemplate->addBodyText(str_replace(
300
				['{owner}', '{title}'],
301
				[$owner->getDisplayName(), $poll->getTitle()],
302
				$trans->t('{owner} invited you to take part in the poll "{title}"')
303
			));
304
305
			$emailTemplate->addBodyText($poll->getDescription());
306
307
			$emailTemplate->addBodyButton(
308
				htmlspecialchars($trans->t('Go to poll')),
309
				$recipient['link']
310
			);
311
312
			$emailTemplate->addBodyText($trans->t('This link gives you personal access to the poll named above. Press the button above or copy the following link and add it in your browser\'s location bar: '));
313
			$emailTemplate->addBodyText($recipient['link']);
314
315
			$emailTemplate->addFooter($trans->t('This email is sent to you, because you are invited to vote in this poll by the poll owner. At least your name or your email address is recorded in this poll. If you want to get removed from this poll, contact the site administrator or the initiator of this poll, where the mail is sent from.'));
316
317
			try {
318
				$this->sendMail(
319
					$emailTemplate,
320
					$recipient['userId'],
321
					$recipient['eMailAddress'],
322
					$recipient['displayName']
323
				);
324
				$share->setInvitationSent(time());
325
				$this->shareMapper->update($share);
326
				$sentMails[] = $recipient;
327
			} catch (Exception $e) {
328
				$abortedMails[] = $recipient;
329
				\OC::$server->getLogger()->alert('Error sending Mail to ' . json_encode($recipient));
330
			}
331
		}
332
		return ['sentMails' => $sentMails, 'abortedMails' => $abortedMails];
333
	}
334
335
	public function sendNotifications() {
336
		$subscriptions = [];
337
		$log = $this->logMapper->findUnprocessedPolls();
338
339
		foreach ($log as $logItem) {
340
			$subscriptions = array_merge($subscriptions, $this->subscriptionMapper->findAllByPoll($logItem->getPollId()));
341
		}
342
343
		$log = $this->logMapper->findUnprocessed();
344
345
		foreach ($subscriptions as $subscription) {
346
			$poll = $this->pollMapper->find($subscription->getPollId());
347
			$emailAddress = '';
348
			$displayName = '';
349
350
			if ($this->userManager->get($subscription->getUserId()) instanceof IUser) {
351
				$lang = $this->config->getUserValue($subscription->getUserId(), 'core', 'lang');
352
			} else {
353
				try {
354
					$emailAddress = $this->shareMapper->findByPollAndUser($subscription->getPollId(), $subscription->getUserId())->getUserEmail();
355
					$displayName = $subscription->getUserId();
356
					$lang = $this->config->getUserValue($poll->getOwner(), 'core', 'lang');
357
				} catch (\Exception $e) {
358
					continue;
359
				}
360
			}
361
362
			$trans = $this->transFactory->get('polls', $lang);
363
364
			$url = $this->urlGenerator->getAbsoluteURL(
365
				$this->urlGenerator->linkToRoute(
366
					'polls.page.indexvote',
367
					['id' => $subscription->getPollId()]
368
				)
369
			);
370
371
			$emailTemplate = $this->mailer->createEMailTemplate('polls.Invitation', [
372
				'title' => $poll->getTitle(),
373
				'link' => $url
374
			]);
375
			$emailTemplate->setSubject($trans->t('Polls App - New Activity'));
376
			$emailTemplate->addHeader();
377
			$emailTemplate->addHeading($trans->t('Polls App - New Activity'), false);
378
			$emailTemplate->addBodyText(str_replace(
379
				['{title}'],
380
				[$poll->getTitle()],
381
				$trans->t('"{title}" had recent activity: ')
382
			));
383
384
			foreach ($log as $logItem) {
385
				if ($logItem->getPollId() === $subscription->getPollId()) {
386
					if ($poll->getAnonymous() || $poll->getShowResults() !== "always") {
387
						$displayUser = $trans->t('A user');
388
					} elseif ($this->userManager->get($logItem->getUserId()) instanceof IUser) {
389
						$displayUser = $this->userManager->get($logItem->getUserId())->getDisplayName();
390
					} else {
391
						$displayUser = $logItem->getUserId();
392
					}
393
394
					if ($logItem->getMessage()) {
395
						$emailTemplate->addBodyText($logItem->getMessage());
396
					} elseif ($logItem->getMessageId() === Log::MSG_ID_SETVOTE) {
397
						$emailTemplate->addBodyText($trans->t(
398
							'- %s voted.',
399
							[$displayUser]
400
						));
401
					} elseif ($logItem->getMessageId() === Log::MSG_ID_UPDATEPOLL) {
402
						$emailTemplate->addBodyText($trans->t(
403
							'- %s updated the poll configuration. Please check your votes.',
404
							[$displayUser]
405
						));
406
					} elseif ($logItem->getMessageId() === Log::MSG_ID_DELETEPOLL) {
407
						$emailTemplate->addBodyText($trans->t(
408
							'- %s deleted the poll.',
409
							[$displayUser]
410
						));
411
					} elseif ($logItem->getMessageId() === Log::MSG_ID_RESTOREPOLL) {
412
						$emailTemplate->addBodyText($trans->t(
413
							'- %s restored the poll.',
414
							[$displayUser]
415
						));
416
					} elseif ($logItem->getMessageId() === Log::MSG_ID_EXPIREPOLL) {
417
						$emailTemplate->addBodyText($trans->t(
418
							'- The poll expired.',
419
							[$displayUser]
420
						));
421
					} elseif ($logItem->getMessageId() === Log::MSG_ID_ADDOPTION) {
422
						$emailTemplate->addBodyText($trans->t(
423
							'- %s added a vote option.',
424
							[$displayUser]
425
						));
426
					} elseif ($logItem->getMessageId() === Log::MSG_ID_DELETEOPTION) {
427
						$emailTemplate->addBodyText($trans->t(
428
							'- %s removed a vote option.',
429
							[$displayUser]
430
						));
431
					} else {
432
						$emailTemplate->addBodyText(
433
							$logItem->getMessageId() . " (" . $displayUser . ")"
434
						);
435
					}
436
				}
437
438
				$logItem->setProcessed(time());
439
				$this->logMapper->update($logItem);
440
			}
441
442
			$emailTemplate->addBodyButton(
443
				htmlspecialchars($trans->t('Go to poll')),
444
				$url,
445
				/** @scrutinizer ignore-type */ false
446
			);
447
			$emailTemplate->addFooter($trans->t('This email is sent to you, because you subscribed to notifications of this poll. To opt out, visit the poll and remove your subscription.'));
448
449
			try {
450
				$this->sendMail($emailTemplate, $subscription->getUserId(), $emailAddress, $displayName);
451
			} catch (Exception $e) {
452
				\OC::$server->getLogger()->alert('Error sending Mail to ' . $subscription->getUserId());
453
			}
454
		}
455
	}
456
}
457