Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
EchoHtmlEmailFormatter
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 4
72
0.00% covered (danger)
0.00%
0 / 1
 formatModel
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
20
 renderBody
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
2
 getFooter
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 renderLink
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\Notifications\Formatters;
4
5use Language;
6use MediaWiki\Html\Html;
7use MediaWiki\Parser\Sanitizer;
8use MediaWiki\SpecialPage\SpecialPage;
9
10class EchoHtmlEmailFormatter extends EchoEventFormatter {
11
12    public const PRIMARY_LINK_STYLE =
13        'cursor: pointer;' .
14        'text-align: center;' .
15        'text-decoration: none;' .
16        'padding: 6px 10px;' .
17        'border-radius: 2px;' .
18        'color: #FFF;' .
19        'background: #36C;' .
20        'font-family: Arial, Helvetica, sans-serif;' .
21        'font-weight: bold;' .
22        'font-size: 13px;';
23
24    public const SECONDARY_LINK_STYLE =
25        'text-decoration: none;' .
26        'font-size: 10px;' .
27        'font-family: Arial, Helvetica, sans-serif;' .
28        'color: #72777D;';
29
30    protected function formatModel( EchoEventPresentationModel $model ) {
31        $subject = $model->getSubjectMessage()->parse();
32
33        $intro = $model->getHeaderMessage()->parse();
34
35        $bodyMsg = $model->getBodyMessage();
36        $summary = $bodyMsg ? $bodyMsg->parse() : '';
37
38        $actions = [];
39
40        $primaryLink = $model->getPrimaryLinkWithMarkAsRead();
41        if ( $primaryLink ) {
42            $actions[] = $this->renderLink( $primaryLink, self::PRIMARY_LINK_STYLE );
43        }
44
45        foreach ( array_filter( $model->getSecondaryLinks() ) as $secondaryLink ) {
46            $actions[] = $this->renderLink( $secondaryLink, self::SECONDARY_LINK_STYLE );
47        }
48
49        $iconUrl = wfExpandUrl(
50            EchoIcon::getRasterizedUrl( $model->getIconType(), $this->language->getCode() ),
51            PROTO_CANONICAL
52        );
53
54        $body = $this->renderBody(
55            $this->language,
56            $iconUrl,
57            $summary,
58            implode( "&nbsp;&nbsp;", $actions ),
59            $intro,
60            $this->getFooter()
61        );
62
63        return [
64            'body' => $body,
65            'subject' => $subject,
66        ];
67    }
68
69    private function renderBody( Language $lang, $emailIcon, $summary, $action, $intro, $footer ) {
70        $alignStart = $lang->alignStart();
71        $langCode = $lang->getHtmlCode();
72        $langDir = $lang->getDir();
73
74        $iconImgSrc = Sanitizer::encodeAttribute( $emailIcon );
75
76        global $wgCanonicalServer;
77        // phpcs:disable Generic.Files.LineLength
78        return <<< EOF
79<html><head>
80    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
81    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
82    <style>
83        @media only screen and (max-width: 480px){
84            table[id="email-container"]{max-width:600px !important; width:100% !important;}
85        }
86    </style>
87    <base href="{$wgCanonicalServer}">
88</head><body>
89<table cellspacing="0" cellpadding="0" border="0" width="100%" align="center" lang="{$langCode}" dir="{$langDir}">
90<tr>
91    <td bgcolor="#EAECF0"><center>
92        <br /><br />
93        <table cellspacing="0" cellpadding="0" border="0" width="600" id="email-container">
94            <tr>
95                <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
96                <td bgcolor="#FFFFFF" width="10%">&nbsp;</td>
97                <td bgcolor="#FFFFFF" width="80%" style="line-height:40px;">&nbsp;</td>
98                <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
99            </tr><tr>
100                <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
101                <td bgcolor="#FFFFFF" align="center" valign="top" rowspan="2"><img src="{$iconImgSrc}" alt="" height="30" width="30"></td>
102                <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; line-height:20px; color:#72777D;">{$intro}</td>
103                <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
104            </tr><tr>
105                <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; line-height: 20px; font-weight: 600;">
106                    <table cellspacing="0" cellpadding="0" border="0">
107                        <tr>
108                            <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; padding-top: 8px; font-size:13px; font-weight: bold; color: #54595D;">
109                                {$summary}
110                            </td>
111                        </tr>
112                    </table>
113                    <table cellspacing="0" cellpadding="0" border="0">
114                        <tr>
115                            <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:14px; padding-top: 25px;">
116                                {$action}
117                            </td>
118                        </tr>
119                    </table>
120                </td>
121            </tr><tr>
122                <td bgcolor="#FFFFFF">&nbsp;</td>
123                <td bgcolor="#FFFFFF">&nbsp;</td>
124                <td bgcolor="#FFFFFF" style="line-height:40px;">&nbsp;</td>
125                <td bgcolor="#FFFFFF">&nbsp;</td>
126            </tr><tr>
127                <td>&nbsp;</td>
128                <td>&nbsp;</td>
129                <td align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:10px; line-height:13px; color:#72777D; padding:10px 20px;"><br />
130                    {$footer}
131                    <br /><br />
132                </td>
133                <td>&nbsp;</td>
134            </tr><tr>
135                <td colspan="4">&nbsp;</td>
136            </tr>
137        </table>
138        <br><br></center>
139    </td>
140</tr>
141</table>
142</body></html>
143EOF;
144        // phpcs:enable Generic.Files.LineLength
145    }
146
147    /**
148     * @return string
149     */
150    public function getFooter() {
151        global $wgEchoEmailFooterAddress;
152
153        $preferenceLink = $this->renderLink(
154            [
155                'label' => $this->msg( 'echo-email-html-footer-preference-link-text', $this->user )
156                    ->text(),
157                'url' => SpecialPage::getTitleFor( 'Preferences', false, 'mw-prefsection-echo' )
158                    ->getFullURL( '', false, PROTO_CANONICAL ),
159            ],
160            'text-decoration: none; color: #36C;'
161        );
162
163        $footer = $this->msg( 'echo-email-html-footer-with-link' )
164            ->rawParams( $preferenceLink )
165            ->params( $this->user )
166            ->parse();
167
168        if ( $wgEchoEmailFooterAddress ) {
169            $footer .= '<br />' . $wgEchoEmailFooterAddress;
170        }
171
172        return $footer;
173    }
174
175    private function renderLink( $link, $style ) {
176        return Html::element(
177            'a',
178            [
179                'href' => wfExpandUrl( $link['url'], PROTO_CANONICAL ),
180                'style' => $style,
181            ],
182            $link['label']
183        );
184    }
185}