Completed
Pull Request — master (#1038)
by René
04:22
created

MailService::sendInvitationMail()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 62
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 42
c 3
b 0
f 0
dl 0
loc 62
ccs 0
cts 50
cp 0
rs 9.248
cc 3
nc 6
nop 1
crap 12

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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