| @@ -9,11 +9,8 @@ | ||
| 9 | 9 | namespace Forge12\DoubleOptIn\Integration; |
| 10 | 10 | |
| 11 | 11 | use Forge12\DoubleOptIn\Container\Container; |
| 12 | 12 | use Forge12\DoubleOptIn\EmailTemplates\PlaceholderMapper; |
| 13 | -use Forge12\DoubleOptIn\FollowUp\FollowUpAttempt; | |
| 14 | -use Forge12\DoubleOptIn\FollowUp\FollowUpCoordinator; | |
| 15 | -use Forge12\DoubleOptIn\FollowUp\FollowUpResult; | |
| 16 | 13 | use forge12\contactform7\CF7DoubleOptIn\Category; |
| 17 | 14 | use forge12\contactform7\CF7DoubleOptIn\CF7DoubleOptIn; |
| 18 | 15 | use forge12\contactform7\CF7DoubleOptIn\HTMLSelect; |
| 19 | 16 | use forge12\contactform7\CF7DoubleOptIn\OptIn; |
| @@ -87,9 +84,9 @@ | ||
| 87 | 84 | |
| 88 | 85 | // Confirmation mail hooks |
| 89 | 86 | add_action( 'f12_cf7_doubleoptin_before_send_default_mail', array( $this, 'beforeSendDefaultMail' ) ); |
| 90 | 87 | add_action( 'f12_cf7_doubleoptin_after_send_default_mail', array( $this, 'afterSendDefaultMail' ) ); |
| 91 | - add_action( 'f12_cf7_doubleoptin_trigger_default_mail', array( $this, 'onTriggerDefaultMail' ) ); | |
| 88 | + add_action( 'f12_cf7_doubleoptin_trigger_default_mail', array( $this, 'sendConfirmationMail' ) ); | |
| 92 | 89 | |
| 93 | 90 | // File hand-off + pending-cleanup. CF7 attaches files to the |
| 94 | 91 | // confirmation mail in attachExtraAttachments (hooked on |
| 95 | 92 | // wpcf7_before_send_mail during sendConfirmationMail). Cleanup |
| @@ -248,10 +245,10 @@ | ||
| 248 | 245 | ) |
| 249 | 246 | ); |
| 250 | 247 | |
| 251 | 248 | if ( ! $this->isOptInEnabled( $formId ) ) { |
| 252 | - // Our own post-confirmation replay: attach the stored files. | |
| 253 | - if ( self::isReplaying() ) { | |
| 249 | + // Handle file attachments for confirmation | |
| 250 | + if ( isset( $_GET['optin'] ) ) { | |
| 254 | 251 | $this->attachStoredFiles( $submission ); |
| 255 | 252 | } |
| 256 | 253 | return; |
| 257 | 254 | } |
| @@ -364,51 +361,9 @@ | ||
| 364 | 361 | /** |
| 365 | 362 | * {@inheritdoc} |
| 366 | 363 | */ |
| 367 | 364 | public function sendConfirmationMail( OptIn $optIn ): void { |
| 368 | - self::runAsReplay( | |
| 369 | - function () use ( $optIn ) { | |
| 370 | - $this->replaySubmission( $optIn ); | |
| 371 | - } | |
| 372 | - ); | |
| 373 | - } | |
| 374 | - | |
| 375 | - /** | |
| 376 | - * Listener on the global `f12_cf7_doubleoptin_trigger_default_mail`. | |
| 377 | - * That action fires for every integration's opt-in; this used to run | |
| 378 | - * the CF7 submission for Elementor opt-ins too, overwriting $_POST. | |
| 379 | - * Managed opt-ins go through the follow-up coordinator, so a second | |
| 380 | - * trigger never sends twice. | |
| 381 | - * | |
| 382 | - * @param OptIn $optIn The confirmed opt-in. | |
| 383 | - * | |
| 384 | - * @since 5.6.0 | |
| 385 | - */ | |
| 386 | - public function onTriggerDefaultMail( OptIn $optIn ): void { | |
| 387 | - if ( ! $optIn->isType( $this->getIdentifier() ) ) { | |
| 388 | - return; | |
| 389 | - } | |
| 390 | - | |
| 391 | - $coordinator = FollowUpCoordinator::instance(); | |
| 392 | - if ( $coordinator !== null && $coordinator->plan( $optIn, true ) ) { | |
| 393 | - $coordinator->run( $optIn, FollowUpAttempt::TRIGGER_LEGACY ); | |
| 394 | - return; | |
| 395 | - } | |
| 396 | - | |
| 397 | - $this->sendConfirmationMail( $optIn ); | |
| 398 | - } | |
| 399 | - | |
| 400 | - /** | |
| 401 | - * Re-run the stored submission through CF7 and report what CF7 says. | |
| 402 | - * | |
| 403 | - * Must run inside {@see runAsReplay()} so our own | |
| 404 | - * `wpcf7_before_send_mail` listener processes it as the confirmed | |
| 405 | - * submission (attachments) instead of creating a new opt-in. | |
| 406 | - * | |
| 407 | - * @since 5.6.0 | |
| 408 | - */ | |
| 409 | - public function replaySubmission( OptIn $optIn ): FollowUpResult { | |
| 410 | - if ( ! $this->isAvailable() || ! class_exists( '\\WPCF7_ContactForm' ) || ! class_exists( '\\WPCF7_Submission' ) ) { | |
| 365 | + if ( ! $this->isAvailable() ) { | |
| 411 | 366 | $this->getLogger()->warning( |
| 412 | 367 | 'CF7 not available for confirmation mail', |
| 413 | 368 | array( |
| 414 | 369 | 'plugin' => 'double-opt-in', |
| @@ -413,11 +368,18 @@ | ||
| 413 | 368 | array( |
| 414 | 369 | 'plugin' => 'double-opt-in', |
| 415 | 370 | ) |
| 416 | 371 | ); |
| 417 | - return FollowUpResult::failedRetryable( 'integration_unavailable' ); | |
| 372 | + return; | |
| 418 | 373 | } |
| 419 | 374 | |
| 375 | + $this->currentOptIn = $optIn; | |
| 376 | + | |
| 377 | + // Restore POST data | |
| 378 | + $data = maybe_unserialize( $optIn->get_content() ); | |
| 379 | + $_POST = SanitizeHelper::sanitize_array( $data ); | |
| 380 | + | |
| 381 | + // Get CF7 form | |
| 420 | 382 | $contactForm = \WPCF7_ContactForm::get_instance( $optIn->get_cf_form_id() ); |
| 421 | 383 | if ( ! $contactForm ) { |
| 422 | 384 | $this->getLogger()->warning( |
| 423 | 385 | 'CF7 form not found for confirmation mail', |
| @@ -425,52 +387,31 @@ | ||
| 425 | 387 | 'plugin' => 'double-opt-in', |
| 426 | 388 | 'form_id' => $optIn->get_cf_form_id(), |
| 427 | 389 | ) |
| 428 | 390 | ); |
| 429 | - return FollowUpResult::failedPermanent( 'form_missing' ); | |
| 391 | + return; | |
| 430 | 392 | } |
| 431 | 393 | |
| 432 | - $data = maybe_unserialize( $optIn->get_content() ); | |
| 433 | - if ( ! is_array( $data ) ) { | |
| 434 | - return FollowUpResult::failedPermanent( 'payload_missing' ); | |
| 435 | - } | |
| 394 | + // Add attachment hook | |
| 395 | + add_action( 'wpcf7_before_send_mail', array( $this, 'attachExtraAttachments' ), 10, 3 ); | |
| 436 | 396 | |
| 437 | - $previousPost = $_POST; | |
| 438 | - $previousOptIn = $this->currentOptIn; | |
| 439 | - $this->currentOptIn = $optIn; | |
| 440 | - $status = ''; | |
| 397 | + // Disable validation and spam checks before creating submission | |
| 398 | + $this->beforeSendConfirmationMail(); | |
| 441 | 399 | |
| 442 | - try { | |
| 443 | - $_POST = SanitizeHelper::sanitize_array( $data ); | |
| 400 | + // Create submission and send mail | |
| 401 | + $submission = \WPCF7_Submission::get_instance( $contactForm ); | |
| 444 | 402 | |
| 445 | - // Disable validation and spam checks before creating submission | |
| 446 | - $this->beforeSendConfirmationMail(); | |
| 403 | + // Re-enable validation and spam checks | |
| 404 | + $this->afterSendConfirmationMail(); | |
| 447 | 405 | |
| 448 | - // Create submission and send mail. Attachments are added by | |
| 449 | - // onSubmit() → attachStoredFiles() while isReplaying(). | |
| 450 | - $submission = \WPCF7_Submission::get_instance( $contactForm ); | |
| 451 | - | |
| 452 | - if ( is_object( $submission ) && method_exists( $submission, 'get_status' ) ) { | |
| 453 | - $status = (string) $submission->get_status(); | |
| 454 | - } | |
| 455 | - } finally { | |
| 456 | - // Re-enable validation and spam checks, restore request state. | |
| 457 | - $this->afterSendConfirmationMail(); | |
| 458 | - $_POST = $previousPost; | |
| 459 | - $this->currentOptIn = $previousOptIn; | |
| 460 | - } | |
| 461 | - | |
| 462 | 406 | $this->getLogger()->info( |
| 463 | 407 | 'Confirmation mail triggered via CF7', |
| 464 | 408 | array( |
| 465 | - 'plugin' => 'double-opt-in', | |
| 466 | - 'form_id' => $optIn->get_cf_form_id(), | |
| 467 | - 'optin_id' => $optIn->get_id(), | |
| 468 | - 'cf7_status' => $status, | |
| 409 | + 'plugin' => 'double-opt-in', | |
| 410 | + 'form_id' => $optIn->get_cf_form_id(), | |
| 411 | + 'optin_id' => $optIn->get_id(), | |
| 469 | 412 | ) |
| 470 | 413 | ); |
| 471 | - | |
| 472 | - return CF7FollowUpAdapter::mapStatus( $status ); | |
| 473 | 414 | } |
| 474 | 415 | |
| 475 | 416 | /** |
| 476 | 417 | * Handle opt-in confirmation from URL. |
| @@ -531,11 +472,10 @@ | ||
| 531 | 472 | * |
| 532 | 473 | * @return void |
| 533 | 474 | */ |
| 534 | 475 | private function attachStoredFiles( $submission ): void { |
| 535 | - // The opt-in being replayed — not the one named in the URL, which | |
| 536 | - // a cron or admin retry does not have (and a visitor controls). | |
| 537 | - $optIn = $this->currentOptIn; | |
| 476 | + $hash = sanitize_text_field( $_GET['optin'] ); | |
| 477 | + $optIn = OptIn::get_by_hash( $hash ); | |
| 538 | 478 | |
| 539 | 479 | if ( ! $optIn ) { |
| 540 | 480 | return; |
| 541 | 481 | } |
| @@ -597,16 +537,8 @@ | ||
| 597 | 537 | * |
| 598 | 538 | * @since 4.3.0 |
| 599 | 539 | */ |
| 600 | 540 | public function cleanupPendingAfterMail( OptIn $optIn ): void { |
| 601 | - // Managed opt-ins: CF7FollowUpAdapter::onSettled() cleans up only | |
| 602 | - // once the mail was actually handed over. This hook fires after | |
| 603 | - // the attempt regardless of its outcome. | |
| 604 | - $coordinator = FollowUpCoordinator::instance(); | |
| 605 | - if ( $coordinator !== null && $coordinator->adapterFor( $optIn ) !== null ) { | |
| 606 | - return; | |
| 607 | - } | |
| 608 | - | |
| 609 | 541 | // Template-method's $hash arg is unused inside processFilesOnConfirm; |
| 610 | 542 | // passing an empty string keeps the contract tight. |
| 611 | 543 | $this->processFilesOnConfirm( '', $optIn ); |
| 612 | 544 | } |