Passed
Push — master ( ece31d...41b8a6 )
by Paul
10:20 queued 04:17
created

Email::logMailError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
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 ('plaintext' == $format) {
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) {
76
            return;
77
        }
78 1
        add_action('wp_mail_failed', [$this, 'logMailError']);
79 1
        $sent = wp_mail(
80 1
            $this->to,
81 1
            $this->subject,
82 1
            $this->message,
83 1
            $this->headers,
84 1
            $this->attachments
85
        );
86 1
        remove_action('wp_mail_failed', [$this, 'logMailError']);
87 1
        $this->reset();
88 1
        return $sent;
89
    }
90
91
    /**
92
     * @return void
93
     * @action phpmailer_init
94
     */
95 1
    public function buildPlainTextMessage(PHPMailer $phpmailer)
96
    {
97 1
        if (empty($this->email)) {
98
            return;
99
        }
100 1
        if ('text/plain' === $phpmailer->ContentType || !empty($phpmailer->AltBody)) {
101
            return;
102
        }
103 1
        $message = $this->stripHtmlTags($phpmailer->Body);
104 1
        $phpmailer->AltBody = apply_filters('site-reviews/email/message', $message, 'text', $this);
105 1
    }
106
107
    /**
108
     * @return array
109
     */
110 1
    protected function buildHeaders()
111
    {
112
        $allowed = [
113 1
            'bcc', 'cc', 'from', 'reply-to',
114
        ];
115 1
        $headers = array_intersect_key($this->email, array_flip($allowed));
116 1
        $headers = array_filter($headers);
117 1
        foreach ($headers as $key => $value) {
118 1
            unset($headers[$key]);
119 1
            $headers[] = $key.': '.$value;
120
        }
121 1
        $headers[] = 'Content-Type: text/html';
122 1
        return apply_filters('site-reviews/email/headers', $headers, $this);
123
    }
124
125
    /**
126
     * @return string
127
     */
128 1
    protected function buildHtmlMessage()
129
    {
130 1
        $template = trim(glsr(OptionManager::class)->get('settings.general.notification_message'));
131 1
        if (!empty($template)) {
132 1
            $message = glsr(Template::class)->interpolate($template, $this->email['template-tags'], $this->email['template']);
133
        } elseif ($this->email['template']) {
134
            $message = glsr(Template::class)->build('templates/'.$this->email['template'], [
135
                'context' => $this->email['template-tags'],
136
            ]);
137
        }
138 1
        if (!isset($message)) {
139
            $message = $this->email['message'];
140
        }
141 1
        $message = $this->email['before'].$message.$this->email['after'];
142 1
        $message = strip_shortcodes($message);
143 1
        $message = wptexturize($message);
144 1
        $message = wpautop($message);
145 1
        $message = str_replace('&lt;&gt; ', '', $message);
146 1
        $message = str_replace(']]>', ']]&gt;', $message);
147 1
        $message = glsr(Template::class)->build('partials/email/index', [
148 1
            'context' => ['message' => $message],
149
        ]);
150 1
        return apply_filters('site-reviews/email/message', stripslashes($message), 'html', $this);
151
    }
152
153
    /**
154
     * @param \WP_Error $error
155
     * @return void
156
     */
157
    protected function logMailError($error)
158
    {
159
        glsr_log()->error('Email was not sent (wp_mail failed)')
160
            ->debug($this)
161
            ->debug($error);
162
    }
163
164
    /**
165
     * @return void
166
     */
167 1
    protected function normalize(array $email = [])
168
    {
169 1
        $email = shortcode_atts(glsr(EmailDefaults::class)->defaults(), $email);
170 1
        if (empty($email['reply-to'])) {
171 1
            $email['reply-to'] = $email['from'];
172
        }
173 1
        $this->email = apply_filters('site-reviews/email/compose', $email, $this);
174 1
    }
175
176
    /**
177
     * @return void
178
     */
179 1
    protected function reset()
180
    {
181 1
        $this->attachments = [];
182 1
        $this->email = [];
183 1
        $this->headers = [];
184 1
        $this->message = null;
185 1
        $this->subject = null;
186 1
        $this->to = null;
187 1
    }
188
189
    /**
190
     * @return string
191
     */
192 1
    protected function stripHtmlTags($string)
193
    {
194
        // remove invisible elements
195 1
        $string = preg_replace('@<(embed|head|noembed|noscript|object|script|style)[^>]*?>.*?</\\1>@siu', '', $string);
196
        // replace certain elements with a line-break
197 1
        $string = preg_replace('@</(div|h[1-9]|p|pre|tr)@iu', "\r\n\$0", $string);
198
        // replace other elements with a space
199 1
        $string = preg_replace('@</(td|th)@iu', ' $0', $string);
200
        // add a placeholder for plain-text bullets to list elements
201 1
        $string = preg_replace('@<(li)[^>]*?>@siu', '$0-o-^-o-', $string);
202
        // strip all remaining HTML tags
203 1
        $string = wp_strip_all_tags($string);
204 1
        $string = wp_specialchars_decode($string, ENT_QUOTES);
205 1
        $string = preg_replace('/\v(?:[\v\h]+){2,}/', "\r\n\r\n", $string);
206 1
        $string = str_replace('-o-^-o-', ' - ', $string);
207 1
        return html_entity_decode($string, ENT_QUOTES, 'UTF-8');
208
    }
209
}
210