PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.9.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.9.0
5.9.0 5.8.0 5.8.1 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 All 42 releases
← All changes | src/FormSettings/FormSettingsService.php +66 -0 5.1.6 → 5.9.0 View file →
@@ -8,9 +8,12 @@
8 8
9 9 namespace Forge12\DoubleOptIn\FormSettings;
10 10
11 11 use Forge12\DoubleOptIn\EmailTemplates\EmailTemplateRepository;
12 +use Forge12\DoubleOptIn\Health\StaleConsentFieldCheck;
12 13 use Forge12\DoubleOptIn\Integration\FormIntegrationRegistry;
14 +use Forge12\DoubleOptIn\Integration\FieldTextProviderInterface;
15 +use Forge12\DoubleOptIn\Integration\SubmittedContent;
13 16 use Forge12\Shared\LoggerInterface;
14 17
15 18 if ( ! defined( 'ABSPATH' ) ) {
16 19 exit;
@@ -143,8 +146,14 @@
143 146 'enabled' => $settings->enabled,
144 147 )
145 148 );
146 149
150 + // The acceptance-field health check caches its scan for hours.
151 + // Someone who just saved these settings very likely did so to fix
152 + // what that check reported, and a stale "still broken" would be a
153 + // bad answer.
154 + StaleConsentFieldCheck::flush();
155 +
147 156 return true;
148 157 }
149 158
150 159 /**
@@ -330,8 +339,65 @@
330 339 $fieldsList[] = array(
331 340 'name' => (string) $name,
332 341 'label' => $label,
333 342 );
343 + }
344 +
345 + // The wording next to each field, where the integration knows it,
346 + // so the consent tab can compare it with the stored consent text.
347 + $texts = $integrationInstance instanceof FieldTextProviderInterface ? $integrationInstance->getFieldTexts( $formId ) : array();
348 + /**
349 + * Visible text per field name (e.g. the label of a consent checkbox).
350 + *
351 + * @since 5.9.0
352 + *
353 + * @param array<string, string> $texts Field name => plain text.
354 + * @param int|string $formId The form ID.
355 + * @param string $integration The integration identifier.
356 + */
357 + $texts = apply_filters( 'f12_doi_form_field_texts', $texts, $formId, $integrationInstance->getIdentifier() );
358 + if ( is_array( $texts ) ) {
359 + foreach ( $fieldsList as &$entry ) {
360 + $text = $texts[ $entry['name'] ] ?? '';
361 + if ( is_string( $text ) && trim( $text ) !== '' ) {
362 + $entry['text'] = trim( $text );
363 + }
364 + }
365 + unset( $entry );
366 + }
367 +
368 + // Reconcile the stored consent field with the form's real field
369 + // names. Settings written before 5.3.2 went through
370 + // sanitize_key(), which lowercased them — so an Elementor
371 + // checkbox with the id `Datenschutz` sits in post_meta as
372 + // `datenschutz`, matches nothing, and the settings page warns
373 + // that the field does not exist. Forever: re-picking it from
374 + // the dropdown lowercased it again (customer report 2026-08-27).
375 + //
376 + // The validator no longer mangles new saves; this repairs the
377 + // installations that already have a mangled one. Doing it on
378 + // read means an untouched site recovers the moment the page is
379 + // opened, and the corrected spelling is what the next save
380 + // persists.
381 + //
382 + // A name that matches NOTHING is left exactly as it is — the
383 + // field really was removed from the form, and the red banner
384 + // saying so is the correct answer.
385 + $storedConsentField = (string) ( $settingsArray['consentField'] ?? '' );
386 + if ( $storedConsentField !== '' ) {
387 + $canonical = SubmittedContent::matchFieldName( $storedConsentField, array_keys( $fields ) );
388 + if ( $canonical !== '' && $canonical !== $storedConsentField ) {
389 + $this->logger->info(
390 + 'Repaired a consent field name that only differed in case',
391 + array(
392 + 'plugin' => 'double-opt-in',
393 + 'form_id' => $formId,
394 + 'stored' => $storedConsentField,
395 + 'form' => $canonical,
396 + )
397 + );
398 + $settingsArray['consentField'] = $canonical;
399 + }
334 400 }
335 401
336 402 return array(
337 403 'id' => $formId,