PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.7.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.7.0
5.7.0 5.6.2 5.6.3 5.6.1 5.6.0 5.5.0 5.4.0 5.3.2 5.3.1 5.1.6 5.1.5 trunk 2.1.5 2.11 2.12 2.13 2.15 3.0.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.51 3.0.60 3.0.61 All 39 releases
double-opt-in / src / Setup / SetupMailComposer.php

SetupMailComposer.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.7.0, at src/Setup/SetupMailComposer.php

219 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The confirmation email the setup wizard writes into a form.
4 *
5 * The designs under mails/ are English only and speak of a newsletter, which
6 * is wrong for a contact form and wrong for every German site. This builds the
7 * mail from the free editor blocks instead, with neutral, translatable text,
8 * and renders it with the same generator that renders saved templates.
9 *
10 * Only blocks from BlockRegistry::FREE_BLOCKS are used.
11 *
12 * @package Forge12\DoubleOptIn\Setup
13 * @since 5.7.0
14 */
15
16 declare( strict_types=1 );
17
18 namespace Forge12\DoubleOptIn\Setup;
19
20 use Forge12\DoubleOptIn\EmailTemplates\EmailHtmlGenerator;
21
22 if ( ! defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 class SetupMailComposer {
27
28 public const DESIGNS = array( 'light', 'dark', 'accent', 'plain' );
29
30 public const DEFAULT_DESIGN = 'light';
31
32 private const LINK = '[doubleoptinlink]';
33
34 /**
35 * Colours per design: page background, card, text, muted text, button, button text.
36 *
37 * @var array<string, array<string, string>>
38 */
39 private const PALETTES = array(
40 'light' => array(
41 'page' => '#f3f4f6',
42 'card' => '#ffffff',
43 'text' => '#1f2937',
44 'muted' => '#6b7280',
45 'button' => '#2271b1',
46 'buttonText' => '#ffffff',
47 ),
48 'dark' => array(
49 'page' => '#0f1216',
50 'card' => '#1c2128',
51 'text' => '#e5e7eb',
52 'muted' => '#9ca3af',
53 'button' => '#3b82f6',
54 'buttonText' => '#ffffff',
55 ),
56 'accent' => array(
57 'page' => '#fdf6dd',
58 'card' => '#ffffff',
59 'text' => '#1f2937',
60 'muted' => '#6b7280',
61 'button' => '#f5c518',
62 'buttonText' => '#1f2937',
63 ),
64 'plain' => array(
65 'page' => '#ffffff',
66 'card' => '#ffffff',
67 'text' => '#1f2937',
68 'muted' => '#6b7280',
69 'button' => '#2271b1',
70 'buttonText' => '#ffffff',
71 ),
72 );
73
74 /** @var string */
75 private $siteName;
76
77 public function __construct( ?string $siteName = null ) {
78 $this->siteName = $siteName ?? wp_specialchars_decode( (string) get_bloginfo( 'name' ), ENT_QUOTES );
79 }
80
81 public static function isDesign( string $design ): bool {
82 return in_array( $design, self::DESIGNS, true );
83 }
84
85 public function subject(): string {
86 return sprintf(
87 /* translators: %s: site name */
88 __( 'Please confirm your email address for %s', 'double-opt-in' ),
89 $this->siteName
90 );
91 }
92
93 /**
94 * Rendered HTML body, ready for the form's `body` setting.
95 */
96 public function body( string $design ): string {
97 $design = self::isDesign( $design ) ? $design : self::DEFAULT_DESIGN;
98 $colors = self::PALETTES[ $design ];
99
100 return ( new EmailHtmlGenerator() )->generate(
101 $this->blocks( $design ),
102 array(
103 'backgroundColor' => $colors['page'],
104 'primaryColor' => $colors['button'],
105 'textColor' => $colors['text'],
106 'linkColor' => $colors['button'],
107 'contentWidth' => '600',
108 )
109 );
110 }
111
112 /**
113 * The block tree of a design.
114 *
115 * @return array<int, array<string, mixed>>
116 */
117 public function blocks( string $design ): array {
118 $design = self::isDesign( $design ) ? $design : self::DEFAULT_DESIGN;
119 $colors = self::PALETTES[ $design ];
120 $site = esc_html( $this->siteName );
121 $link = '<a href="' . self::LINK . '" style="color:' . $colors['button'] . ';word-break:break-all;">' . self::LINK . '</a>';
122
123 $children = array(
124 $this->block(
125 'heading',
126 array(
127 'level' => 1,
128 'text' => __( 'Please confirm your email address', 'double-opt-in' ),
129 'color' => $colors['text'],
130 )
131 ),
132 $this->block(
133 'text',
134 array(
135 'content' => sprintf(
136 /* translators: %s: site name */
137 __( 'Hello,<br><br>this email address was just entered on %s. To make sure it was really you, please confirm it with one click.', 'double-opt-in' ),
138 $site
139 ),
140 'color' => $colors['text'],
141 )
142 ),
143 );
144
145 if ( $design === 'plain' ) {
146 $children[] = $this->block(
147 'text',
148 array(
149 'content' => $link,
150 'color' => $colors['text'],
151 )
152 );
153 } else {
154 $children[] = $this->block( 'spacer', array( 'height' => 8 ) );
155 $children[] = $this->block(
156 'button',
157 array(
158 'text' => __( 'Confirm email address', 'double-opt-in' ),
159 'url' => self::LINK,
160 'align' => 'center',
161 'backgroundColor' => $colors['button'],
162 'textColor' => $colors['buttonText'],
163 'borderRadius' => 6,
164 )
165 );
166 $children[] = $this->block( 'spacer', array( 'height' => 8 ) );
167 $children[] = $this->block(
168 'text',
169 array(
170 'content' => __( 'If the button does not work, copy this link into your browser:', 'double-opt-in' ) . '<br>' . $link,
171 'color' => $colors['muted'],
172 'fontSize' => '13px',
173 )
174 );
175 }
176
177 $children[] = $this->block( 'divider', array( 'color' => $colors['page'] === $colors['card'] ? '#e5e7eb' : $colors['page'] ) );
178 $children[] = $this->block(
179 'text',
180 array(
181 'content' => __( 'If you did not request this, simply ignore this email. Nothing happens without your confirmation.', 'double-opt-in' )
182 . '<br><br>'
183 . sprintf(
184 /* translators: %s: site name */
185 __( 'Kind regards,<br>%s', 'double-opt-in' ),
186 $site
187 ),
188 'color' => $colors['muted'],
189 'fontSize' => '14px',
190 )
191 );
192
193 return array(
194 $this->block(
195 'email-wrapper',
196 array(
197 'backgroundColor' => $colors['card'],
198 'padding' => $design === 'plain' ? '8px' : '32px',
199 ),
200 $children
201 ),
202 );
203 }
204
205 /**
206 * @param array<string, mixed> $attributes
207 * @param array<int, array<string, mixed>> $children
208 *
209 * @return array<string, mixed>
210 */
211 private function block( string $type, array $attributes, array $children = array() ): array {
212 return array(
213 'type' => $type,
214 'attributes' => $attributes,
215 'children' => $children,
216 );
217 }
218 }
219