PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.5.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.5.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 3.0.62 3.0.70 3.0.71 3.0.72 3.1.0 All 34 releases
double-opt-in / compatibility / cf7 / CF7Frontend.class.php

CF7Frontend.class.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.5.0, at compatibility/cf7/CF7Frontend.class.php

361 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace forge12\contactform7\CF7DoubleOptIn {
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 use forge12\plugins\ContactForm7;
9 use Forge12\Shared\LoggerInterface;
10
11 /**
12 * Class Frontend
13 * Responsible to handle the frontend of the Double OptIn
14 *
15 * @package forge12\contactform7\CF7DoubleOptIn
16 *
17 * @deprecated 4.0.0 Use \Forge12\DoubleOptIn\Integration\CF7Integration instead.
18 * This class is maintained for backward compatibility only.
19 * @see \Forge12\DoubleOptIn\Integration\CF7Integration
20 */
21 class CF7Frontend extends OptInFrontend {
22 protected $OptIn = null;
23
24 /**
25 * Admin constructor.
26 */
27 public function __construct( LoggerInterface $logger ) {
28 parent::__construct( $logger, 'cf7' );
29
30 $this->get_logger()->debug( 'CF7 integration constructor called', [
31 'plugin' => 'double-opt-in',
32 'class' => __CLASS__,
33 'method' => __METHOD__,
34 ] );
35
36 add_action( 'wpcf7_before_send_mail', [ $this, 'onSubmit' ], 5, 3 );
37 $this->get_logger()->debug( 'Action wpcf7_before_send_mail registered', [
38 'plugin' => 'double-opt-in',
39 ] );
40 }
41
42
43 /**
44 * Get the recipient email address
45 *
46 * @param string $recipient The recipient email address
47 * @param array $formParameter The form parameter array
48 * @param array $postParameter The post parameter array
49 *
50 * @return string The sanitized recipient email address
51 */
52 public function getRecipient( string $recipient, array $formParameter, array $postParameter ): string {
53 $this->get_logger()->debug( 'getRecipient called', [
54 'plugin' => 'double-opt-in',
55 'class' => __CLASS__,
56 'method' => __METHOD__,
57 'formParameter' => $formParameter,
58 ] );
59
60 // Ensure the recipient has been defined in the settings
61 if ( ! isset( $formParameter['recipient'] ) ) {
62 $this->get_logger()->warning( 'Recipient not defined in form parameters, returning fallback', [
63 'plugin' => 'double-opt-in',
64 'recipient' => $recipient,
65 ] );
66
67 return $recipient;
68 }
69
70 $recipient = $formParameter['recipient'];
71
72 $recipient = str_replace( [ '[', ']' ], '', $recipient );
73
74 // Get the Recipient from the post parameter
75 if ( isset( $postParameter[ $recipient ] ) ) {
76 $recipient = sanitize_email( $_POST[ $recipient ] ); // phpcs:ignore WordPress.Security.NonceVerification
77 $this->get_logger()->debug( 'Recipient resolved from post parameter', [
78 'plugin' => 'double-opt-in',
79 'recipient' => $recipient,
80 ] );
81 } else {
82 $this->get_logger()->warning( 'Recipient not found in postParameter, using fallback', [
83 'plugin' => 'double-opt-in',
84 'recipient' => $recipient,
85 ] );
86 }
87
88 return $recipient;
89 }
90
91
92 /**
93 * Add File after submission and confirming opt in.
94 *
95 * @param $form
96 * @param $abort
97 * @param $submission
98 *
99 * @return void
100 */
101 public function attachExtraAttachments( $form, $abort, $submission ) {
102 $this->get_logger()->debug( 'attachExtraAttachments called', [
103 'plugin' => 'double-opt-in',
104 'class' => __CLASS__,
105 'method' => __METHOD__,
106 ] );
107
108 if ( $this->OptIn !== null && $this->OptIn->get_files() !== null ) {
109 $fileWrapper = maybe_unserialize( $this->OptIn->get_files() );
110
111 if ( is_array( $fileWrapper ) ) {
112 foreach ( $fileWrapper as $file ) {
113 $submission->add_extra_attachments( $file );
114
115 $this->get_logger()->debug( 'Extra attachment added', [
116 'plugin' => 'double-opt-in',
117 'file' => $file,
118 ] );
119 }
120 } else {
121 $this->get_logger()->warning( 'File wrapper is not an array, skipping attachments', [
122 'plugin' => 'double-opt-in',
123 ] );
124 }
125 } else {
126 $this->get_logger()->debug( 'No OptIn files found, skipping attachments', [
127 'plugin' => 'double-opt-in',
128 ] );
129 }
130 }
131
132
133 /**
134 * Send the default email for the given OptIn. (Original Mail after Opt-In Confirmation)
135 *
136 * @param OptIn $OptIn The OptIn object containing the email content and form ID.
137 *
138 * @return void
139 */
140 public function sendDefaultMail( OptIn $OptIn ): void {
141 $this->get_logger()->debug( 'sendDefaultMail called', [
142 'plugin' => 'double-opt-in',
143 'class' => __CLASS__,
144 'method' => __METHOD__,
145 'optin_id' => $OptIn->get_id(),
146 'form_id' => $OptIn->get_cf_form_id(),
147 ] );
148
149 if ( ! function_exists( 'wpcf7' ) ) {
150 $this->get_logger()->warning( 'wpcf7 function not available, aborting sendDefaultMail', [
151 'plugin' => 'double-opt-in',
152 ] );
153
154 return;
155 }
156
157 $this->OptIn = $OptIn;
158
159 $data = maybe_unserialize( $OptIn->get_content() );
160 $_POST = SanitizeHelper::sanitize_array( $data );
161
162 $ContactForm = \WPCF7_ContactForm::get_instance( $OptIn->get_cf_form_id() );
163 if ( ! $ContactForm ) {
164 $this->get_logger()->warning( 'Contact form not found, aborting sendDefaultMail', [
165 'plugin' => 'double-opt-in',
166 'form_id' => $OptIn->get_cf_form_id(),
167 'optin_id' => $OptIn->get_id(),
168 ] );
169
170 return;
171 }
172
173 add_action( 'wpcf7_before_send_mail', [ $this, 'attachExtraAttachments' ], 10, 3 );
174 $this->get_logger()->debug( 'Hook wpcf7_before_send_mail registered for attachments', [
175 'plugin' => 'double-opt-in',
176 ] );
177
178 // Disable CF7 validation and spam checks for confirmation mail resend.
179 // CF7 re-runs all form validations (required fields, quiz, acceptance checkboxes)
180 // when creating a WPCF7_Submission instance, which fails in a GET request context.
181 $clearValidation = function( $result ) {
182 return new \WPCF7_Validation();
183 };
184 add_filter( 'wpcf7_validate', $clearValidation, 999 );
185 add_filter( 'wpcf7_spam', '__return_false', 0 );
186 add_filter( 'wpcf7_skip_spam_check', '__return_true', 0 );
187
188 $submission = \WPCF7_Submission::get_instance( $ContactForm );
189
190 // Re-enable validation and spam checks
191 remove_filter( 'wpcf7_validate', $clearValidation, 999 );
192 remove_filter( 'wpcf7_spam', '__return_false', 0 );
193 remove_filter( 'wpcf7_skip_spam_check', '__return_true', 0 );
194
195 if ( $submission ) {
196 $this->get_logger()->info( 'WPCF7 submission prepared for sendDefaultMail', [
197 'plugin' => 'double-opt-in',
198 'form_id' => $OptIn->get_cf_form_id(),
199 'optin_id' => $OptIn->get_id(),
200 ] );
201 } else {
202 $this->get_logger()->warning( 'Failed to prepare WPCF7 submission', [
203 'plugin' => 'double-opt-in',
204 'form_id' => $OptIn->get_cf_form_id(),
205 'optin_id' => $OptIn->get_id(),
206 ] );
207 }
208 }
209
210
211 /**
212 * On Form Submit add the double optin if enabled
213 *
214 * @param $form \WPCF7_ContactForm
215 * @param bool
216 * @param $submission \WPCF7_Submission
217 */
218 public function onSubmit( $form, &$abort, $submission ) {
219 $this->get_logger()->debug( 'onSubmit called', [
220 'plugin' => 'double-opt-in',
221 'class' => __CLASS__,
222 'method' => __METHOD__,
223 'form_id' => $form->id(),
224 ] );
225
226 $parameter = CF7DoubleOptIn::getInstance()->getParameter( $form->id() );
227
228 if ( $this->isOptinEnabled( $form->id() ) ) {
229 $this->get_logger()->debug( 'Opt-in enabled, processing', [
230 'plugin' => 'double-opt-in',
231 'form_id' => $form->id(),
232 ] );
233
234 // Remove Contact Form 7 DB hook to ensure the optin mail is not saved
235 remove_action( 'wpcf7_before_send_mail', 'cfdb7_before_send_mail' );
236
237 if ( apply_filters( 'f12_cf7_doubleoptin_skip_option', false, $form->id(), $submission->get_posted_data(), $this->type ) ) {
238 $this->get_logger()->info( 'Opt-in skipped by filter', [
239 'plugin' => 'double-opt-in',
240 'form_id' => $form->id(),
241 ] );
242
243 return;
244 }
245
246 $OptIn = $this->maybeCreateOptIn(
247 $form->id(),
248 $form->form_html(),
249 $submission->get_posted_data(),
250 $submission->uploaded_files()
251 );
252
253 if ( ! $OptIn ) {
254 $this->get_logger()->warning( 'OptIn object could not be created', [
255 'plugin' => 'double-opt-in',
256 'form_id' => $form->id(),
257 ] );
258
259 return;
260 }
261
262 $parameter['formUrl'] = $submission->get_meta( 'url' );
263
264 /**
265 * Filter to render custom email templates.
266 *
267 * Allows replacing the email body with content from custom templates.
268 *
269 * @since 4.0.0
270 *
271 * @param string $body The email body content.
272 * @param string $template The template key (e.g., 'blank', 'custom_123').
273 * @param array $parameter The form parameters.
274 * @param OptIn $OptIn The OptIn object.
275 */
276 $body = apply_filters( 'f12_cf7_doubleoptin_template_body', $parameter['body'], $parameter['template'], $parameter, $OptIn );
277
278 $body = $this->addPlaceholders( $body, $OptIn, $parameter );
279 $body = apply_filters( 'f12_cf7_doubleoptin_body', $body );
280
281 $OptIn->set_mail_optin( $body );
282 $OptIn->save();
283
284 $args = apply_filters( 'f12-cf7-doubleoptin-cf7-args', [
285 'subject' => $parameter['subject'],
286 'body' => $body,
287 'sender' => $parameter['sender'],
288 'sender_name' => $parameter['sender_name'],
289 'recipient' => $parameter['recipient'],
290 'use_html' => true,
291 'additional_headers' => '',
292 ] );
293
294 if ( ! empty( $parameter['sender_name'] ) ) {
295 $args['additional_headers'] .= 'From: ' . $args['sender_name'] . ' <' . $args['sender'] . '>';
296 }
297
298 \WPCF7_Mail::send( $args, 'mail' );
299 $this->get_logger()->info( 'OptIn mail sent', [
300 'plugin' => 'double-opt-in',
301 'form_id' => $form->id(),
302 'recipient' => $args['recipient'],
303 'subject' => $args['subject'],
304 ] );
305
306 $telemetry = new Telemetry( $this->get_logger() );
307 $telemetry->increment( 'total_optins' );
308 $telemetry->increment( 'cf7_optins' );
309
310 add_filter( 'wpcf7_skip_mail', '__return_true' );
311 do_action( 'f12_cf7_doubleoptin_sent', $form, $form->id() );
312
313 } elseif ( isset( $_GET['optin'] ) ) {
314 $hash = sanitize_text_field( $_GET['optin'] );
315 $OptIn = OptIn::get_by_hash( $hash );
316
317 if ( $OptIn === null ) {
318 $this->get_logger()->warning( 'OptIn not found for hash', [
319 'plugin' => 'double-opt-in',
320 'hash' => $hash,
321 ] );
322
323 return;
324 }
325
326 $files = maybe_unserialize( $OptIn->get_files() );
327
328 if ( empty( $files ) ) {
329 $this->get_logger()->debug( 'No files found for OptIn', [
330 'plugin' => 'double-opt-in',
331 'optinId' => $OptIn->get_id(),
332 ] );
333
334 return;
335 }
336
337 foreach ( $files as $file ) {
338 if ( empty( $file ) ) {
339 continue;
340 }
341
342 if ( apply_filters( 'f12_cf7_doubleoptin_files_mail_1', true, $OptIn ) ) {
343 $submission->add_extra_attachments( $file );
344 $this->get_logger()->debug( 'Attachment added to mail_1', [
345 'plugin' => 'double-opt-in',
346 'file' => $file,
347 ] );
348 }
349
350 if ( apply_filters( 'f12_cf7_doubleoptin_files_mail_2', true, $OptIn ) ) {
351 $submission->add_extra_attachments( $file, 'mail_2' );
352 $this->get_logger()->debug( 'Attachment added to mail_2', [
353 'plugin' => 'double-opt-in',
354 'file' => $file,
355 ] );
356 }
357 }
358 }
359 }
360 }
361 }