JezK
Edit File: RestNewsletter.php
<?php /** * REST endpoint for the Newsletter Section block. * * Route: POST bpsc/v1/newsletter-subscribe * Accepts: { email, form_id, hp } * Reads mail settings from a transient keyed bpsc_newsletter_{form_id} * and sends a notification to the configured recipient via wp_mail(). */ // ABS PATH guard. if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'BPSCRestNewsletter' ) ) { class BPSCRestNewsletter { public function __construct() { add_action( 'rest_api_init', [ $this, 'register_routes' ] ); } /** * Register the REST route. */ public function register_routes() { register_rest_route( 'bpsc/v1', '/newsletter-subscribe', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'handle_subscribe' ], 'permission_callback' => '__return_true', 'args' => [ 'email' => [ 'type' => 'string', 'required' => true, 'sanitize_callback' => function ( $val ) { return sanitize_email( wp_unslash( $val ) ); }, ], 'form_id' => [ 'type' => 'string', 'required' => true, 'sanitize_callback' => function ( $val ) { return sanitize_text_field( wp_unslash( $val ) ); }, ], 'hp' => [ 'type' => 'string', 'default' => '', 'sanitize_callback' => function ( $val ) { return sanitize_text_field( wp_unslash( $val ) ); }, ], ], ] ); } /** * Handle a newsletter subscription request. * * @param WP_REST_Request $request Full request object. * @return WP_REST_Response|WP_Error */ public function handle_subscribe( WP_REST_Request $request ) { // --- Honeypot check --- $hp = $request->get_param( 'hp' ); if ( '' !== $hp ) { // Silent success — do not reveal the bot was detected. return rest_ensure_response( [ 'success' => true ] ); } // --- Email validation --- $email = $request->get_param( 'email' ); if ( ! is_email( $email ) ) { return new WP_Error( 'invalid_email', __( 'Please enter a valid email address.', 'section-collection' ), [ 'status' => 400 ] ); } // --- Load mail settings from transient --- $form_id = $request->get_param( 'form_id' ); $settings = get_transient( 'bpsc_newsletter_' . $form_id ); if ( false === $settings || ! is_array( $settings ) ) { return new WP_Error( 'form_expired', __( 'This form has expired. Please refresh the page.', 'section-collection' ), [ 'status' => 400 ] ); } // --- Resolve recipient --- $recipient = isset( $settings['recipient'] ) ? trim( $settings['recipient'] ) : ''; if ( empty( $recipient ) || ! is_email( $recipient ) ) { $recipient = get_option( 'admin_email' ); } // --- Build message --- $subject = isset( $settings['subject'] ) ? sanitize_text_field( $settings['subject'] ) : __( 'New newsletter subscriber', 'section-collection' ); $body_template = isset( $settings['body'] ) ? $settings['body'] : '{email} is subscribing to the newsletter.'; $body = str_replace( '{email}', $email, $body_template ); // --- Optional From Name via filters --- $from_name = isset( $settings['fromName'] ) ? sanitize_text_field( $settings['fromName'] ) : ''; $headers = []; if ( ! empty( $from_name ) ) { $from_email = ''; $from_filter = function ( $email ) use ( &$from_email ) { $from_email = $email; return $email; }; add_filter( 'wp_mail_from', $from_filter, 99 ); // Run once to capture the default from address. $from_email = apply_filters( 'wp_mail_from', get_option( 'admin_email' ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- core WordPress filter, read intentionally to capture the default from-address. remove_filter( 'wp_mail_from', $from_filter, 99 ); $from_name_filter = function () use ( $from_name ) { return $from_name; }; add_filter( 'wp_mail_from_name', $from_name_filter, 99 ); wp_mail( $recipient, $subject, $body, $headers ); remove_filter( 'wp_mail_from_name', $from_name_filter, 99 ); } else { wp_mail( $recipient, $subject, $body, $headers ); } // --- Build success message --- $success_message = isset( $settings['successMessage'] ) && '' !== $settings['successMessage'] ? $settings['successMessage'] : __( "Thanks! Check your inbox.", 'section-collection' ); return rest_ensure_response( [ 'success' => true, 'message' => $success_message, ] ); } } new BPSCRestNewsletter(); }