Completed
Push — master ( d19024...c7c8b5 )
by Thomas
12:42
created

MailNotifications::sendInternalShareMail()   C

Complexity

Conditions 8
Paths 50

Size

Total Lines 68
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 45
nc 50
nop 3
dl 0
loc 68
rs 6.5974
c 0
b 0
f 0

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
 * @author Björn Schießle <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Lukas Reschke <[email protected]>
6
 * @author Morris Jobke <[email protected]>
7
 * @author Robin McCorkell <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 * @author scolebrook <[email protected]>
10
 * @author Thomas Müller <[email protected]>
11
 * @author Vincent Petry <[email protected]>
12
 *
13
 * @copyright Copyright (c) 2018, ownCloud GmbH
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
30
namespace OC\Share;
31
32
use DateTime;
33
use OCP\IL10N;
34
use OCP\IURLGenerator;
35
use OCP\IUser;
36
use OCP\Mail\IMailer;
37
use OCP\ILogger;
38
use OCP\Defaults;
39
use OCP\Util;
40
use OC\Share\Filters\MailNotificationFilter;
41
42
/**
43
 * Class MailNotifications
44
 *
45
 * @package OC\Share
46
 */
47
class MailNotifications {
48
49
	/** @var IUser sender userId */
50
	private $user;
51
	/** @var string sender email address */
52
	private $replyTo;
53
	/** @var string */
54
	private $senderDisplayName;
55
	/** @var IL10N */
56
	private $l;
57
	/** @var IMailer */
58
	private $mailer;
59
	/** @var Defaults */
60
	private $defaults;
61
	/** @var ILogger */
62
	private $logger;
63
	/** @var IURLGenerator */
64
	private $urlGenerator;
65
66
	/**
67
	 * @param IUser $user
68
	 * @param IL10N $l10n
69
	 * @param IMailer $mailer
70
	 * @param ILogger $logger
71
	 * @param Defaults $defaults
72
	 * @param IURLGenerator $urlGenerator
73
	 */
74
	public function __construct(IUser $user,
75
								IL10N $l10n,
76
								IMailer $mailer,
77
								ILogger $logger,
78
								Defaults $defaults,
79
								IURLGenerator $urlGenerator) {
80
		$this->l = $l10n;
81
		$this->user = $user;
82
		$this->mailer = $mailer;
83
		$this->logger = $logger;
84
		$this->defaults = $defaults;
85
		$this->urlGenerator = $urlGenerator;
86
87
		$this->replyTo = $this->user->getEMailAddress();
88
		$this->senderDisplayName = $this->user->getDisplayName();
89
	}
90
91
	/**
92
	 * split a list of comma or semicolon separated email addresses
93
	 *
94
	 * @param string $mailsstring email addresses
95
	 * @return array list of individual addresses
96
	 */
97
	private function _mailStringToArray($mailsstring) {
98
		$sanatised  = str_replace([', ', '; ', ',', ';', ' '], ',', $mailsstring);
99
		$mail_array = explode(',', $sanatised);
100
101
		return $mail_array;
102
	}
103
104
	/**
105
	 * inform users if a file was shared with them
106
	 *
107
	 * @param IUser[] $recipientList list of recipients
108
	 * @param string $itemSource shared item source
109
	 * @param string $itemType shared item type
110
	 * @return array list of user to whom the mail send operation failed
111
	 */
112
	public function sendInternalShareMail($recipientList, $itemSource, $itemType) {
113
		$noMail = [];
114
115
		foreach ($recipientList as $recipient) {
116
			$recipientDisplayName = $recipient->getDisplayName();
117
			$to = $recipient->getEMailAddress();
118
119
			if ($to === null || $to === '') {
120
				$noMail[] = $recipientDisplayName;
121
				continue;
122
			}
123
124
			$items = $this->getItemSharedWithUser($itemSource, $itemType, $recipient);
125
			$filename = trim($items[0]['file_target'], '/');
126
			$expiration = null;
127
			if (isset($items[0]['expiration'])) {
128
				try {
129
					$date = new DateTime($items[0]['expiration']);
130
					$expiration = $date->getTimestamp();
131
				} catch (\Exception $e) {
132
					$this->logger->error("Couldn't read date: ".$e->getMessage(), ['app' => 'sharing']);
133
				}
134
			}
135
136
			$link = $this->urlGenerator->linkToRouteAbsolute(
137
				'files.viewcontroller.showFile',
138
				['fileId' => $items[0]['item_source']]
139
			);
140
141
			$filter = new MailNotificationFilter([
142
				'link' => $link,
143
				'file' => $filename,
144
			]);
145
146
			$filename = $filter->getFile();
147
			$link = $filter->getLink();
148
149
			$subject = (string) $this->l->t('%s shared »%s« with you', [$this->senderDisplayName, $filename]);
150
			list($htmlBody, $textBody) = $this->createMailBody($filename, $link, $expiration, null, 'internal');
151
152
			// send it out now
153
			try {
154
				$message = $this->mailer->createMessage();
155
				$message->setSubject($subject);
156
				$message->setTo([$to => $recipientDisplayName]);
157
				$message->setHtmlBody($htmlBody);
0 ignored issues
show
Bug introduced by
It seems like $htmlBody defined by $this->createMailBody($f...tion, null, 'internal') on line 150 can also be of type boolean; however, OC\Mail\Message::setHtmlBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
158
				$message->setPlainBody($textBody);
0 ignored issues
show
Bug introduced by
It seems like $textBody defined by $this->createMailBody($f...tion, null, 'internal') on line 150 can also be of type boolean; however, OC\Mail\Message::setPlainBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
159
				$message->setFrom([
160
					Util::getDefaultEmailAddress('sharing-noreply') =>
161
						(string)$this->l->t('%s via %s', [
162
							$this->senderDisplayName,
163
							$this->defaults->getName()
164
						]),
165
					]);
166
				if(!is_null($this->replyTo)) {
167
					$message->setReplyTo([$this->replyTo]);
168
				}
169
170
				$this->mailer->send($message);
171
			} catch (\Exception $e) {
172
				$this->logger->error("Can't send mail to inform the user about an internal share: ".$e->getMessage(), ['app' => 'sharing']);
173
				$noMail[] = $recipientDisplayName;
174
			}
175
		}
176
177
		return $noMail;
178
179
	}
180
181
	public function sendLinkShareMail($recipient, $filename, $link, $expiration, $personalNote = null) {
182
		$subject = (string)$this->l->t('%s shared »%s« with you', [$this->senderDisplayName, $filename]);
183
		list($htmlBody, $textBody) = $this->createMailBody($filename, $link, $expiration, $personalNote);
184
185
		return $this->sendLinkShareMailFromBody($recipient, $subject, $htmlBody, $textBody);
186
	}
187
188
	/**
189
	 * inform recipient about public link share
190
	 *
191
	 * @param string $recipient recipient email address
192
	 * @param string $filename the shared file
0 ignored issues
show
Bug introduced by
There is no parameter named $filename. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
193
	 * @param string $link the public link
0 ignored issues
show
Bug introduced by
There is no parameter named $link. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
194
	 * @param array $options allows ['cc'] and ['bcc'] recipients
195
	 * @param int $expiration expiration date (timestamp)
0 ignored issues
show
Bug introduced by
There is no parameter named $expiration. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
196
	 * @return string[] $result of failed recipients
197
	 */
198
	public function sendLinkShareMailFromBody($recipient, $subject, $htmlBody, $textBody, $options = array()) {
199
200
		$recipients    = $this->_mailStringToArray($recipient);
201
		$ccRecipients  = (isset($options['cc']) && $options['cc'] !== '') ? $this->_mailStringToArray($options['cc']) : null;
202
		$bccRecipients = (isset($options['bcc']) && $options['bcc'] !== '') ? $this->_mailStringToArray($options['bcc']) : null;
203
204
		try {
205
			$message = $this->mailer->createMessage();
206
			$message->setSubject($subject);
207
			$message->setTo($recipients);
208
			if ($htmlBody !== null) {
209
				$message->setHtmlBody($htmlBody);
210
			}
211
			if ($bccRecipients !== null) {
212
				$message->setBcc($bccRecipients);
213
			}
214
			if ($ccRecipients !== null) {
215
				$message->setCc($ccRecipients);
216
			}
217
			$message->setPlainBody($textBody);
218
			$message->setFrom([
219
				Util::getDefaultEmailAddress('sharing-noreply') =>
220
					(string)$this->l->t('%s via %s', [
221
						$this->senderDisplayName,
222
						$this->defaults->getName()
223
					]),
224
			]);
225
			if(!is_null($this->replyTo)) {
226
				$message->setReplyTo([$this->replyTo]);
227
			}
228
229
			return $this->mailer->send($message);
230
		} catch (\Exception $e) {
231
			$this->logger->error("Can't send mail with public link to $recipient: ".$e->getMessage(), ['app' => 'sharing']);
232
			return [$recipient];
233
		}
234
	}
235
236
	/**
237
	 * create mail body for plain text and html mail
238
	 *
239
	 * @param string $filename the shared file
240
	 * @param string $link link to the shared file
241
	 * @param int $expiration expiration date (timestamp)
242
	 * @param string $personalNote optional personal note
243
	 * @param string $prefix prefix of mail template files
244
	 * @return array an array of the html mail body and the plain text mail body
245
	 */
246
	public function createMailBody($filename, $link, $expiration, $personalNote = null, $prefix = '') {
247
		$formattedDate = $expiration ? $this->l->l('date', $expiration) : null;
248
249
		$html = new \OC_Template('core', $prefix . 'mail', '');
250
		$html->assign('link', $link);
251
		$html->assign('user_displayname', $this->senderDisplayName);
252
		$html->assign('filename', $filename);
253
		$html->assign('expiration',  $formattedDate);
254
		if ($personalNote !== null && $personalNote !== '') {
255
			$html->assign('personal_note', $personalNote);
256
		}
257
		$htmlMail = $html->fetchPage();
258
259
		$plainText = new \OC_Template('core', $prefix . 'altmail', '');
260
		$plainText->assign('link', $link);
261
		$plainText->assign('user_displayname', $this->senderDisplayName);
262
		$plainText->assign('filename', $filename);
263
		$plainText->assign('expiration', $formattedDate);
264
		if ($personalNote !== null && $personalNote !== '') {
265
			$plainText->assign('personal_note', $personalNote);
266
		}
267
		$plainTextMail = $plainText->fetchPage();
268
269
		return [$htmlMail, $plainTextMail];
270
	}
271
272
	/**
273
	 * @param string $itemSource
274
	 * @param string $itemType
275
	 * @param IUser $recipient
276
	 * @return array
277
	 */
278
	protected function getItemSharedWithUser($itemSource, $itemType, $recipient) {
279
		return Share::getItemSharedWithUser($itemType, $itemSource, $recipient->getUID());
280
	}
281
282
}
283