PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.6.3
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.6.3
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 3.0.62 All 38 releases
← All changes | src/Integration/AbstractFormIntegration.php +73 -0 5.6.1 → 5.6.3 View file →
@@ -487,8 +487,81 @@
487 487 return null;
488 488 }
489 489
490 490 /**
491 + * The consent gate, asked at the form plugin's own validation stage.
492 + *
493 + * For integrations whose submit hook runs after the form plugin has
494 + * already accepted the submission (WPForms `wpforms_process_complete`,
495 + * Gravity Forms `gform_after_submission`). By then the form has been
496 + * replaced by its confirmation, and a refused consent could only be
497 + * reported in a toast over an empty page (5.6.2 click test). Asked from
498 + * `wpforms_process` / `gform_validation` instead, the form plugin marks
499 + * the checkbox like a missed required field and keeps the input.
500 + *
501 + * Only a refusal that would stand is returned: DOI on for the form, not
502 + * skipped by `f12_cf7_doubleoptin_skip_option`, verdict NOT_GIVEN, gate
503 + * enforced. Everything else — a stale field name, the gate switched off
504 + * by filter — is left to createOptIn(), which logs it as before.
505 + *
506 + * @param FormDataInterface $formData The submission, normalized the same
507 + * way the submit hook will normalize it.
508 + * @param mixed $rawFields What the skip filter receives in the
509 + * submit hook of this integration.
510 + *
511 + * @return OptInError|null The refusal, or null to let the form through.
512 + *
513 + * @since 5.6.2
514 + */
515 + public function refusedConsentBeforeSubmit( FormDataInterface $formData, $rawFields = array() ): ?OptInError {
516 + $formId = $formData->getFormId();
517 +
518 + if ( ! $this->isOptInEnabled( $formId ) ) {
519 + return null;
520 + }
521 +
522 + if ( apply_filters( 'f12_cf7_doubleoptin_skip_option', false, $formId, $rawFields, $this->getIdentifier() ) ) {
523 + return null;
524 + }
525 +
526 + $consentField = (string) ( $this->getFormParameter( $formId )['consent_field'] ?? '' );
527 + if ( $consentField === '' ) {
528 + return null;
529 + }
530 +
531 + $verdict = ConsentGate::evaluate(
532 + $consentField,
533 + $formData->getFields(),
534 + $this->getKnownFieldNames( $formId )
535 + );
536 +
537 + if ( $verdict !== ConsentGate::NOT_GIVEN || ! ConsentGate::isEnforced( $formId, $this->getIdentifier() ) ) {
538 + return null;
539 + }
540 +
541 + $this->getLogger()->info(
542 + 'Consent acceptance not given, rejecting submission at validation',
543 + array(
544 + 'plugin' => 'double-opt-in',
545 + 'form_id' => $formId,
546 + 'integration' => $this->getIdentifier(),
547 + 'consent_field' => $consentField,
548 + )
549 + );
550 +
551 + /** This action is documented in createOptIn(). */
552 + do_action( 'f12_cf7_doubleoptin_consent_not_given', $formId, $consentField );
553 +
554 + return OptInError::fromCode(
555 + OptInError::CONSENT_NOT_GIVEN,
556 + array(
557 + 'form_id' => $formId,
558 + 'consent_field' => $consentField,
559 + )
560 + );
561 + }
562 +
563 + /**
491 564 * Validate the consent-acceptance gate (GDPR Art. 7).
492 565 *
493 566 * The decision itself lives in {@see ConsentGate} — this method only
494 567 * turns it into the return value `createOptIn()` expects and writes