Passed
Push — master ( 6b8ca8...3384db )
by Paul
04:57
created

Email::send()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 10
cts 10
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 2
nop 0
crap 4
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Database\OptionManager;
6
use GeminiLabs\SiteReviews\Modules\Html\Template;
7
8
class Email
9
{
10
	/**
11
	 * @var array
12
	 */
13
	protected $attachments;
14
15
	/**
16
	 * @var array
17
	 */
18
	protected $headers;
19
20
	/**
21
	 * @var string
22
	 */
23
	protected $message;
24
25
	/**
26
	 * @var string
27
	 */
28
	protected $subject;
29
30
	/**
31
	 * @var string
32
	 */
33
	protected $to;
34
35
	/**
36
	 * @return Email
37
	 */
38 1
	public function compose( array $email )
39
	{
40 1
		$email = $this->normalize( $email );
41 1
		$this->attachments = $email['attachments'];
42 1
		$this->headers = $this->buildHeaders( $email );
43 1
		$this->message = $this->buildHtmlMessage( $email );
44 1
		$this->subject = $email['subject'];
45 1
		$this->to = $email['to'];
46 1
		add_action( 'phpmailer_init', [ $this, 'buildPlainTextMessage'] );
47 1
		return $this;
48
	}
49
50
	/**
51
	 * @return string|null
52
	 */
53
	public function read( $plaintext = false )
54
	{
55
		if( !!$plaintext ) {
56
			$message = $this->stripHtmlTags( $this->message );
57
			return apply_filters( 'site-reviews/email/message', $message, 'text', $this );
58
		}
59
		return $this->message;
60
	}
61
62
	/**
63
	 * @return void|bool
64
	 */
65 1
	public function send()
66
	{
67 1
		if( !$this->message || !$this->subject || !$this->to )return;
68 1
		$sent = wp_mail(
69 1
			$this->to,
70 1
			$this->subject,
71 1
			$this->message,
72 1
			$this->headers,
73 1
			$this->attachments
74
		);
75 1
		$this->reset();
76 1
		return $sent;
77
	}
78
79
	/**
80
	 * @return void
81
	 *
82
	 * @action phpmailer_init
83
	 */
84 1
	public function buildPlainTextMessage( $phpmailer )
85
	{
86 1
		if( $phpmailer->ContentType === 'text/plain' || !empty( $phpmailer->AltBody ))return;
87 1
		$message = $this->stripHtmlTags( $phpmailer->Body );
88 1
		$phpmailer->AltBody = apply_filters( 'site-reviews/email/message', $message, 'text', $this );
89 1
	}
90
91
	/**
92
	 * @return array
93
	 */
94 1
	protected function buildHeaders( $email )
95
	{
96
		$allowed = [
97 1
			'bcc',
98
			'cc',
99
			'from',
100
			'reply-to',
101
		];
102 1
		$headers = array_intersect_key( $email, array_flip( $allowed ));
103 1
		$headers = array_filter( $headers );
104 1
		foreach( $headers as $key => $value ) {
105 1
			unset( $headers[ $key ] );
106 1
			$headers[] = "{$key}: {$value}";
107
		}
108 1
		$headers[] = 'Content-Type: text/html';
109 1
		return apply_filters( 'site-reviews/email/headers', $headers, $this );
110
	}
111
112
	/**
113
	 * @return string
114
	 */
115 1
	protected function buildHtmlMessage( $email )
116
	{
117 1
		$template = trim( glsr( OptionManager::class )->get( 'settings.general.notification_message' ));
118 1
		if( !empty( $template )) {
119 1
			$message = glsr( Template::class )->interpolate( $template, $email['template-tags'] );
120
		}
121
		else if( $email['template'] ) {
122
			$message = glsr( Template::class )->build( 'templates/'.$email['template'], [
123
				'context' => $email['template-tags'],
124
			]);
125
		}
126 1
		if( !isset( $message )) {
127
			$message = $email['message'];
128
		}
129 1
		$message = $email['before'].$message.$email['after'];
130 1
		$message = strip_shortcodes( $message );
131 1
		$message = wptexturize( $message );
132 1
		$message = wpautop( $message );
133 1
		$message = str_replace( '&lt;&gt; ', '', $message );
134 1
		$message = str_replace( ']]>', ']]&gt;', $message );
135 1
		$message = glsr( Template::class )->build( 'email/index', [
136 1
			'context' => ['message' => $message],
137
		]);
138 1
		return apply_filters( 'site-reviews/email/message', stripslashes( $message ), 'html', $this );
139
	}
140
141
	/**
142
	 * @return array
143
	 */
144 1
	protected function normalize( $email )
145
	{
146 1
		$fromName  = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
0 ignored issues
show
Bug introduced by
It seems like get_option('blogname') can also be of type false; however, parameter $string of wp_specialchars_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

146
		$fromName  = wp_specialchars_decode( /** @scrutinizer ignore-type */ get_option( 'blogname' ), ENT_QUOTES );
Loading history...
147 1
		$fromEmail = get_option( 'admin_email' );
148
		$defaults = [
149 1
			'after' => '',
150
			'attachments' => [],
151 1
			'bcc' => '',
152 1
			'before' => '',
153 1
			'cc' => '',
154 1
			'from' => $fromName.'<'.$fromEmail.'>',
0 ignored issues
show
Bug introduced by
Are you sure $fromEmail of type mixed|false can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

154
			'from' => $fromName.'<'./** @scrutinizer ignore-type */ $fromEmail.'>',
Loading history...
155 1
			'message' => '',
156 1
			'reply-to' => '',
157 1
			'subject' => '',
158 1
			'template' => '',
159
			'template-tags' => [],
160 1
			'to' => '',
161
		];
162 1
		$email = shortcode_atts( $defaults, $email );
163 1
		if( empty( $email['reply-to'] )) {
164 1
			$email['reply-to'] = $email['from'];
165
		}
166 1
		return apply_filters( 'site-reviews/email/compose', $email, $this );
167
	}
168
169
	/**
170
	 * @return void
171
	 */
172 1
	protected function reset()
173
	{
174 1
		$this->attachments = [];
175 1
		$this->headers = [];
176 1
		$this->message = null;
177 1
		$this->subject = null;
178 1
		$this->to = null;
179 1
	}
180
181
	/**
182
	 * @return string
183
	 */
184 1
	protected function stripHtmlTags( $string )
185
	{
186
		// remove invisible elements
187 1
		$string = preg_replace( '@<(embed|head|noembed|noscript|object|script|style)[^>]*?>.*?</\\1>@siu', '', $string );
188
		// replace certain elements with a line-break
189 1
		$string = preg_replace( '@</(div|h[1-9]|p|pre|tr)@iu', "\r\n\$0", $string );
190
		// replace other elements with a space
191 1
		$string = preg_replace( '@</(td|th)@iu', " \$0", $string );
192
		// add a placeholder for plain-text bullets to list elements
193 1
		$string = preg_replace( '@<(li)[^>]*?>@siu', "\$0-o-^-o-", $string );
194
		// strip all remaining HTML tags
195 1
		$string = wp_strip_all_tags( $string );
196 1
		$string = wp_specialchars_decode( $string, ENT_QUOTES );
197 1
		$string = preg_replace( '/\v(?:[\v\h]+){2,}/', "\r\n\r\n", $string );
198 1
		$string = str_replace( '-o-^-o-', ' - ', $string );
199 1
		return html_entity_decode( $string, ENT_QUOTES, 'UTF-8' );
200
	}
201
}
202