repository = $repository; } public function register( EventDispatcherInterface $dispatcher ): void { $dispatcher->addListener( OptInCreatedEvent::class, array( $this, 'onCreated' ) ); add_action( 'wp_mail_failed', array( $this, 'onMailFailed' ) ); add_action( 'f12_cf7_doubleoptin_sent', array( $this, 'onSent' ), 99, 0 ); add_action( self::RESULT_ACTION, array( $this, 'record' ), 10, 3 ); } public function onCreated( OptInCreatedEvent $event ): void { $this->currentId = $event->getOptInId(); $this->currentRecipient = self::normalise( $event->getEmail() ); $this->recorded = false; } /** * @param mixed $error A WP_Error from wp_mail(). */ public function onMailFailed( $error ): void { if ( $this->currentId <= 0 || $this->recorded || ! is_object( $error ) || ! method_exists( $error, 'get_error_message' ) ) { return; } $data = method_exists( $error, 'get_error_data' ) ? $error->get_error_data() : array(); $to = is_array( $data ) && isset( $data['to'] ) ? (array) $data['to'] : array(); $recipients = array_map( array( self::class, 'normalise' ), $to ); if ( ! in_array( $this->currentRecipient, $recipients, true ) ) { // Another mail of the same request (a notification, a reminder). return; } $this->record( $this->currentId, false, (string) $error->get_error_message() ); } public function onSent(): void { if ( $this->currentId <= 0 || $this->recorded ) { return; } $this->record( $this->currentId, true ); } /** * Store an outcome. Also the handler of `f12_doi_optin_mail_result`. * * @param mixed $optInId Opt-in ID. * @param mixed $sent Whether wp_mail() accepted the mail. * @param mixed $error Error text for a failure. */ public function record( $optInId, $sent, $error = '' ): void { $optInId = (int) $optInId; if ( $optInId <= 0 ) { return; } // First outcome of the current opt-in wins: wp_mail_failed carries // the mail server's own message and fires before the integration // reports its (generic) result. if ( $optInId === $this->currentId && $this->recorded ) { return; } $this->repository->mark( $optInId, $sent ? OptInMailStatusRepository::SENT : OptInMailStatusRepository::FAILED, $sent ? '' : ( (string) $error !== '' ? (string) $error : __( 'The mail could not be handed to the mail server.', 'double-opt-in' ) ) ); if ( $optInId === $this->currentId ) { $this->recorded = true; } } /** * Lower-case address out of "Name " or "a@b.c". * * @param mixed $address */ public static function normalise( $address ): string { $address = (string) $address; if ( preg_match( '/<([^>]+)>/', $address, $m ) ) { $address = $m[1]; } return strtolower( trim( $address ) ); } }