Passed
Push — hotfix/fix-counts ( b4ff8e...673622 )
by Paul
04:39
created

Email::buildHeaders()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
nc 2
nop 0
dl 0
loc 13
ccs 9
cts 9
cp 1
crap 2
rs 9.9666
c 1
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Database\OptionManager;
6
use GeminiLabs\SiteReviews\Defaults\EmailDefaults;
7
use GeminiLabs\SiteReviews\Modules\Html\Template;
8
use PHPMailer;
9
10
class Email
11
{
12
	/**
13
	 * @var array
14
	 */
15
	public $attachments;
16
17
	/**
18
	 * @var array
19
	 */
20
	public $email;
21
22
	/**
23
	 * @var array
24
	 */
25
	public $headers;
26
27
	/**
28
	 * @var string
29
	 */
30
	public $message;
31
32
	/**
33
	 * @var string
34
	 */
35
	public $subject;
36
37
	/**
38
	 * @var string|array
39
	 */
40
	public $to;
41
42
	/**
43
	 * @return Email
44
	 */
45 1
	public function compose( array $email )
46
	{
47 1
		$this->normalize( $email );
48 1
		$this->attachments = $this->email['attachments'];
49 1
		$this->headers = $this->buildHeaders();
50 1
		$this->message = $this->buildHtmlMessage();
51 1
		$this->subject = $this->email['subject'];
52 1
		$this->to = $this->email['to'];
53 1
		add_action( 'phpmailer_init', [$this, 'buildPlainTextMessage'] );
54 1
		return $this;
55
	}
56
57
	/**
58
	 * @param string $format
59
	 * @return string|null
60
	 */
61
	public function read( $format = '' )
62
	{
63
		if( $format == 'plaintext' ) {
64
			$message = $this->stripHtmlTags( $this->message );
65
			return apply_filters( 'site-reviews/email/message', $message, 'text', $this );
66
		}
67
		return $this->message;
68
	}
69
70
	/**
71
	 * @return void|bool
72
	 */
73 1
	public function send()
74
	{
75 1
		if( !$this->message || !$this->subject || !$this->to )return;
76 1
		add_action( 'wp_mail_failed', [$this, 'logMailError']);
77 1
		$sent = wp_mail(
78 1
			$this->to,
79 1
			$this->subject,
80 1
			$this->message,
81 1
			$this->headers,
82 1
			$this->attachments
83
		);
84 1
		remove_action( 'wp_mail_failed', [$this, 'logMailError']);
85 1
		$this->reset();
86 1
		return $sent;
87
	}
88
89
	/**
90
	 * @return void
91
	 * @action phpmailer_init
92
	 */
93 1
	public function buildPlainTextMessage( PHPMailer $phpmailer )
94
	{
95 1
		if( empty( $this->email ))return;
96 1
		if( $phpmailer->ContentType === 'text/plain' || !empty( $phpmailer->AltBody ))return;
97 1
		$message = $this->stripHtmlTags( $phpmailer->Body );
98 1
		$phpmailer->AltBody = apply_filters( 'site-reviews/email/message', $message, 'text', $this );
99 1
	}
100
101
	/**
102
	 * @return array
103
	 */
104 1
	protected function buildHeaders()
105
	{
106
		$allowed = [
107 1
			'bcc', 'cc', 'from', 'reply-to',
108
		];
109 1
		$headers = array_intersect_key( $this->email, array_flip( $allowed ));
110 1
		$headers = array_filter( $headers );
111 1
		foreach( $headers as $key => $value ) {
112 1
			unset( $headers[$key] );
113 1
			$headers[] = $key.': '.$value;
114
		}
115 1
		$headers[] = 'Content-Type: text/html';
116 1
		return apply_filters( 'site-reviews/email/headers', $headers, $this );
117
	}
118
119
	/**
120
	 * @return string
121
	 */
122 1
	protected function buildHtmlMessage()
123
	{
124 1
		$template = trim( glsr( OptionManager::class )->get( 'settings.general.notification_message' ));
125 1
		if( !empty( $template )) {
126 1
			$message = glsr( Template::class )->interpolate( $template, $this->email['template-tags'], $this->email['template'] );
127
		}
128
		else if( $this->email['template'] ) {
129
			$message = glsr( Template::class )->build( 'templates/'.$this->email['template'], [
130
				'context' => $this->email['template-tags'],
131
			]);
132
		}
133 1
		if( !isset( $message )) {
134
			$message = $this->email['message'];
135
		}
136 1
		$message = $this->email['before'].$message.$this->email['after'];
137 1
		$message = strip_shortcodes( $message );
138 1
		$message = wptexturize( $message );
139 1
		$message = wpautop( $message );
140 1
		$message = str_replace( '&lt;&gt; ', '', $message );
141 1
		$message = str_replace( ']]>', ']]&gt;', $message );
142 1
		$message = glsr( Template::class )->build( 'partials/email/index', [
143 1
			'context' => ['message' => $message],
144
		]);
145 1
		return apply_filters( 'site-reviews/email/message', stripslashes( $message ), 'html', $this );
146
	}
147
148
	/**
149
	 * @param \WP_Error $error
150
	 * @return void
151
	 */
152
	protected function logMailError( $error )
153
	{
154
		glsr_log()->error( 'Email was not sent (wp_mail failed)' )
155
			->debug( $this )
156
			->debug( $error );
157
	}
158
159
	/**
160
	 * @return void
161
	 */
162 1
	protected function normalize( array $email = [] )
163
	{
164 1
		$email = shortcode_atts( glsr( EmailDefaults::class )->defaults(), $email );
165 1
		if( empty( $email['reply-to'] )) {
166 1
			$email['reply-to'] = $email['from'];
167
		}
168 1
		$this->email = apply_filters( 'site-reviews/email/compose', $email, $this );
169 1
	}
170
171
	/**
172
	 * @return void
173
	 */
174 1
	protected function reset()
175
	{
176 1
		$this->attachments = [];
177 1
		$this->email = [];
178 1
		$this->headers = [];
179 1
		$this->message = null;
180 1
		$this->subject = null;
181 1
		$this->to = null;
182 1
	}
183
184
	/**
185
	 * @return string
186
	 */
187 1
	protected function stripHtmlTags( $string )
188
	{
189
		// remove invisible elements
190 1
		$string = preg_replace( '@<(embed|head|noembed|noscript|object|script|style)[^>]*?>.*?</\\1>@siu', '', $string );
191
		// replace certain elements with a line-break
192 1
		$string = preg_replace( '@</(div|h[1-9]|p|pre|tr)@iu', "\r\n\$0", $string );
193
		// replace other elements with a space
194 1
		$string = preg_replace( '@</(td|th)@iu', " \$0", $string );
195
		// add a placeholder for plain-text bullets to list elements
196 1
		$string = preg_replace( '@<(li)[^>]*?>@siu', "\$0-o-^-o-", $string );
197
		// strip all remaining HTML tags
198 1
		$string = wp_strip_all_tags( $string );
199 1
		$string = wp_specialchars_decode( $string, ENT_QUOTES );
200 1
		$string = preg_replace( '/\v(?:[\v\h]+){2,}/', "\r\n\r\n", $string );
201 1
		$string = str_replace( '-o-^-o-', ' - ', $string );
202 1
		return html_entity_decode( $string, ENT_QUOTES, 'UTF-8' );
203
	}
204
}
205