| @@ -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, |