Completed
Push — 3.0 ( edb87a...82b7ad )
by Jeroen
128:20 queued 66:19
created

EmailService::transport()   B

Complexity

Conditions 6
Paths 11

Size

Total Lines 73
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 6.2373

Importance

Changes 0
Metric Value
cc 6
eloc 36
nc 11
nop 1
dl 0
loc 73
ccs 26
cts 32
cp 0.8125
crap 6.2373
rs 8.7217
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
namespace Elgg;
4
5
use Psr\Log\LoggerInterface;
6
use RuntimeException;
7
use Zend\Mail\Header\ContentType;
8
use Zend\Mail\Message as MailMessage;
9
use Zend\Mail\Transport\TransportInterface;
10
use Zend\Mime\Mime;
11
use Zend\Mime\Message as MimeMessage;
12
use Zend\Mime\Part;
13
use Zend\Mime\Exception\InvalidArgumentException;
14
15
/**
16
 * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
17
 *
18
 * Use the elgg_* versions instead.
19
 *
20
 * @access private
21
 * @since  3.0
22
 */
23
class EmailService {
24
25
	use Loggable;
26
27
	/**
28
	 * @var Config
29
	 */
30
	private $config;
31
32
	/**
33
	 * @var PluginHooksService
34
	 */
35
	private $hooks;
36
37
	/**
38
	 * @var TransportInterface
39
	 */
40
	private $mailer;
41
42
	/**
43
	 * Constructor
44
	 *
45
	 * @param Config             $config Config
46
	 * @param PluginHooksService $hooks  Hook registration service
47
	 * @param TransportInterface $mailer Mailer
48
	 * @param LoggerInterface    $logger Logger
49
	 */
50 5
	public function __construct(Config $config, PluginHooksService $hooks, TransportInterface $mailer, LoggerInterface $logger) {
51 5
		$this->config = $config;
52 5
		$this->hooks = $hooks;
53 5
		$this->mailer = $mailer;
54 5
		$this->logger = $logger;
55 5
	}
56
57
	/**
58
	 * Sends an email
59
	 *
60
	 * @param Email $email Email
61
	 *
62
	 * @return bool
63
	 * @throws RuntimeException
64
	 */
65 5
	public function send(Email $email) {
66 5
		$email = $this->hooks->trigger('prepare', 'system:email', null, $email);
67 5
		if (!$email instanceof Email) {
68
			$msg = "'prepare','system:email' hook handlers should return an instance of " . Email::class;
69
			throw new RuntimeException($msg);
70
		}
71
72
		$hook_params = [
73 5
			'email' => $email,
74
		];
75
76 5
		$is_valid = $email->getFrom() && $email->getTo();
77 5
		if (!$this->hooks->trigger('validate', 'system:email', $hook_params, $is_valid)) {
78
			return false;
79
		}
80
81 5
		return $this->transport($email);
82
	}
83
84
	/**
85
	 * Transports an email
86
	 *
87
	 * @param Email $email Email
88
	 *
89
	 * @return bool
90
	 * @throws RuntimeException
91
	 */
92 5
	public function transport(Email $email) {
93
94
		$hook_params = [
95 5
			'email' => $email,
96
		];
97
98 5
		if ($this->hooks->trigger('transport', 'system:email', $hook_params, false)) {
99 1
			return true;
100
		}
101
102
		// create the e-mail message
103 4
		$message = new MailMessage();
104 4
		$message->setEncoding('UTF-8');
105 4
		$message->setSender($email->getFrom());
106 4
		$message->addFrom($email->getFrom());
107 4
		$message->addTo($email->getTo());
108
		
109
		// set headers
110
		$headers = [
111 4
			"MIME-Version" => "1.0",
112
			"Content-Transfer-Encoding" => "8bit",
113
		];
114 4
		$headers = array_merge($headers, $email->getHeaders());
115
116 4
		foreach ($headers as $name => $value) {
117
			// See #11018
118
			// Create a headerline as a concatenated string "name: value"
119
			// This is done to force correct class detection for each header type,
120
			// which influences the output of the header in the message
121 4
			$message->getHeaders()->addHeaderLine("{$name}: {$value}");
122
		}
123
		
124
		// add the body to the message
125
		try {
126 4
			$body = $this->buildMessageBody($email);
127
		} catch (InvalidArgumentException $e) {
128
			$this->logger->error($e->getMessage());
129
			
130
			return false;
131
		}
132
		
133
		
134 4
		$message->setBody($body);
135
		
136
		// set Subject
137 4
		$subject = elgg_strip_tags($email->getSubject());
138 4
		$subject = html_entity_decode($subject, ENT_QUOTES, 'UTF-8');
139
		// Sanitise subject by stripping line endings
140 4
		$subject = preg_replace("/(\r\n|\r|\n)/", " ", $subject);
141 4
		$subject = trim($subject);
142
		
143 4
		$message->setSubject($subject);
144
145
		// allow others to modify the $message content
146
		// eg. add html body, add attachments
147 4
		$message = $this->hooks->trigger('zend:message', 'system:email', $hook_params, $message);
148
149
		// fix content type header
150
		// @see https://github.com/Elgg/Elgg/issues/12555
151 4
		$ct = $message->getHeaders()->get('Content-Type');
152 4
		if ($ct instanceof ContentType) {
153 4
			$ct->addParameter('format', 'flowed');
154
		}
155
		
156
		try {
157 4
			$this->mailer->send($message);
158
		} catch (RuntimeException $e) {
159
			$this->logger->error($e->getMessage());
160
161
			return false;
162
		}
163
164 4
		return true;
165
	}
166
	
167
	/**
168
	 * Build the body part of the e-mail message
169
	 *
170
	 * @param Email $email Email
171
	 *
172
	 * @return \Zend\Mime\Message
173
	 * @throws \Zend\Mime\Exception\InvalidArgumentException
174
	 */
175 4
	protected function buildMessageBody(Email $email) {
176
		// create body
177 4
		$body = new MimeMessage();
178
		
179
		// add plain text part
180 4
		$plain_text = elgg_strip_tags($email->getBody());
181 4
		$plain_text = html_entity_decode($plain_text, ENT_QUOTES, 'UTF-8');
182 4
		$plain_text = wordwrap($plain_text);
183
		
184 4
		$plain_text_part = new Part($plain_text);
185 4
		$plain_text_part->setId('plaintext');
186 4
		$plain_text_part->setType(Mime::TYPE_TEXT);
187 4
		$plain_text_part->setCharset('UTF-8');
188
		
189 4
		$body->addPart($plain_text_part);
190
		
191
		// process attachments
192 4
		$attachments = $email->getAttachments();
193 4
		foreach ($attachments as $attachement) {
194
			$body->addPart($attachement);
195
		}
196
		
197 4
		return $body;
198
	}
199
200
}
201