Passed
Push — master ( 56e798...72475d )
by Thomas
02:26
created

EmailUtils::stringify()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 14
c 0
b 0
f 0
nc 8
nop 1
dl 0
loc 23
rs 8.0555
1
<?php
2
3
namespace LeKoala\SparkPost;
4
5
use Pelago\Emogrifier\CssInliner;
6
use Symfony\Component\Mime\Address;
7
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
8
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
9
10
class EmailUtils
11
{
12
    /**
13
     * Inline styles using Pelago Emogrifier V7
14
     *
15
     * This is much better than the functionnality provided by SparkPost anyway
16
     *
17
     * @link https://github.com/MyIntervals/emogrifier#more-complex-example
18
     * @param string $html
19
     * @param string $css (optional) css to inline
20
     * @return string
21
     */
22
    public static function inline_styles($html, $css = '')
23
    {
24
        $domDocument = CssInliner::fromHtml($html)->inlineCss($css)->getDomDocument();
25
26
        HtmlPruner::fromDomDocument($domDocument)->removeElementsWithDisplayNone();
27
        $html = CssToAttributeConverter::fromDomDocument($domDocument)
28
            ->convertCssToVisualAttributes()->render();
29
30
        return $html;
31
    }
32
33
    /**
34
     * @param array<string|int,string|null>|string|null|bool|Address $email
35
     * @return string|null
36
     */
37
    public static function stringify($email)
38
    {
39
        if (!$email || is_bool($email)) {
40
            return null;
41
        }
42
        if ($email instanceof Address) {
43
            if ($email->getName()) {
44
                return $email->getName() . ' <' . $email->getAddress() . '>';
45
            }
46
            return $email->getAddress();
47
        }
48
        if (is_array($email)) {
49
            if (count($email) == 2) {
50
                return $email[1] . ' <' . $email[0] . '>';
51
            }
52
            foreach ($email as $k => $v) {
53
                if ($k) {
54
                    return $v . ' <' . $k . '>';
55
                }
56
                return $v;
57
            }
58
        }
59
        return $email;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $email also could return the type array<integer|string,null|string> which is incompatible with the documented return type null|string.
Loading history...
60
    }
61
62
    /**
63
     * @param array<mixed> $emails
64
     * @return string
65
     */
66
    public static function stringifyArray(array $emails)
67
    {
68
        $result = [];
69
        foreach ($emails as $email) {
70
            $result[] = self::stringify($email);
71
        }
72
        return implode(", ", $result);
73
    }
74
75
    /**
76
     * @param array<string|int,string|null>|string|null|bool $email
77
     * @return bool
78
     */
79
    public static function validate($email)
80
    {
81
        return boolval(filter_var(self::stringify($email), FILTER_VALIDATE_EMAIL));
82
    }
83
84
    /**
85
     * Convert an html email to a text email while keeping formatting and links
86
     *
87
     * @param string $content
88
     * @return string
89
     */
90
    public static function convert_html_to_text($content)
91
    {
92
        // Prevent styles to be included
93
        $content = preg_replace('/<style.*>([\s\S]*)<\/style>/i', '', $content);
94
        // Convert html entities to strip them later on
95
        $content = html_entity_decode($content);
96
        // Bold
97
        $content = str_ireplace(['<strong>', '</strong>', '<b>', '</b>'], "*", $content);
98
        // Replace links to keep them accessible
99
        $content = preg_replace('/<a(.*?)href=[\'"](.*?)[\'"](.*?)>(.*?)<\/a>/i', '$4 ($2)', $content);
100
        // Replace new lines
101
        $content = str_replace(['<br>', '<br/>', '<br />'], "\r\n", $content);
102
        // Remove html tags
103
        $content = strip_tags($content);
104
        // Avoid lots of spaces
105
        $content = preg_replace('/^[\s][\s]+(\S)/m', "\n$1", $content);
106
        // Trim content so that it's nice
107
        $content = trim($content);
108
        return $content;
109
    }
110
111
    /**
112
     * Match all words and whitespace, will be terminated by '<'
113
     *
114
     * Note: use /u to support utf8 strings
115
     *
116
     * @param string $rfc_email_string
117
     * @return string
118
     */
119
    public static function get_displayname_from_rfc_email($rfc_email_string)
120
    {
121
        $name = preg_match('/[\w\s\-\.]+/u', $rfc_email_string, $matches);
0 ignored issues
show
Unused Code introduced by
The assignment to $name is dead and can be removed.
Loading history...
122
        $matches[0] = trim($matches[0]);
123
        return $matches[0];
124
    }
125
126
    /**
127
     * Extract parts between brackets
128
     *
129
     * @param string $rfc_email_string
130
     * @return string
131
     */
132
    public static function get_email_from_rfc_email($rfc_email_string)
133
    {
134
        if (strpos($rfc_email_string, '<') === false) {
135
            return $rfc_email_string;
136
        }
137
        $mailAddress = preg_match('/(?:<)(.+)(?:>)$/', $rfc_email_string, $matches);
0 ignored issues
show
Unused Code introduced by
The assignment to $mailAddress is dead and can be removed.
Loading history...
138
        if (empty($matches)) {
139
            return $rfc_email_string;
140
        }
141
        return $matches[1];
142
    }
143
144
    /**
145
     * @deprecated
146
     * @param \SilverStripe\Control\Email\Email $Email
147
     * @return \Symfony\Component\Mime\Header\Headers
148
     */
149
    public static function getHeaders($Email)
150
    {
151
        return method_exists($Email, 'getSwiftMessage') ? $Email->getSwiftMessage()->getHeaders() : $Email->getHeaders();
152
    }
153
}
154