'Booking submitted', 'booking_confirmed' => 'Booking confirmed', 'booking_cancelled' => 'Booking cancelled', 'booking_rescheduled' => 'Booking rescheduled', 'booking_completed' => 'Booking completed', 'booking_reminder' => 'Booking reminder', 'no_show_marked' => 'No-show marked', 'review_request' => 'Review request', ]; public const RECIPIENTS = [ 'customer' => 'Customer', 'admin' => 'Admin (from Settings)', 'staff' => 'Staff (from Settings)', 'custom' => 'Custom email', ]; public static function render(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only display filter; saves are nonce+capability checked in maybe_save(). $edit_id = isset( $_GET['edit'] ) ? absint( wp_unslash( $_GET['edit'] ) ) : 0; $new = isset( $_GET['new'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only display filter. if ( $edit_id || $new ) { $rule = $edit_id ? Email_Automation_Repository::find( $edit_id ) : null; $services = Service_Repository::all(); $variables = Email_Template_Renderer::VARIABLE_KEYS; include BOOKINGISTIC_DIR . 'templates/admin/email-automation-edit.php'; return; } $rules = Email_Automation_Repository::all(); include BOOKINGISTIC_DIR . 'templates/admin/email-automations-list.php'; } public static function maybe_save(): void { // Action dispatcher peek: each branch verifies its own nonce below. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verified below before any processing. $action = sanitize_key( wp_unslash( $_POST['bookingistic_admin_action'] ?? '' ) ); if ( $action === 'save_email_automation' ) { \Bookingistic\Core\Capabilities::verify( \Bookingistic\Core\Capabilities::MANAGE_EMAILS ); check_admin_referer( 'bookingistic_admin_email_automation' ); $payload = [ 'name' => sanitize_text_field( wp_unslash( $_POST['name'] ?? '' ) ), 'trigger_event' => sanitize_key( wp_unslash( $_POST['trigger_event'] ?? '' ) ), 'recipient_type' => sanitize_key( wp_unslash( $_POST['recipient_type'] ?? 'customer' ) ), 'recipient_custom' => sanitize_email( wp_unslash( $_POST['recipient_custom'] ?? '' ) ), 'delay_amount' => absint( wp_unslash( $_POST['delay_amount'] ?? 0 ) ), 'delay_unit' => sanitize_key( wp_unslash( $_POST['delay_unit'] ?? 'minutes' ) ), 'subject' => sanitize_text_field( wp_unslash( $_POST['subject'] ?? '' ) ), 'body' => wp_kses_post( wp_unslash( $_POST['body'] ?? '' ) ), 'service_id' => absint( wp_unslash( $_POST['service_id'] ?? 0 ) ), 'status' => sanitize_key( wp_unslash( $_POST['status'] ?? 'active' ) ), ]; $id = absint( wp_unslash( $_POST['automation_id'] ?? 0 ) ); $saved = $id > 0 ? Email_Automation_Repository::update( $id, $payload ) : Email_Automation_Repository::create( $payload ); $saved_id = is_array( $saved ) ? (int) $saved['id'] : 0; $redirect = $saved_id ? admin_url( 'admin.php?page=bookingistic-emails&edit=' . $saved_id . '&saved=1' ) : admin_url( 'admin.php?page=bookingistic-emails' ); wp_safe_redirect( $redirect ); exit; } if ( $action === 'delete_email_automation' ) { \Bookingistic\Core\Capabilities::verify( \Bookingistic\Core\Capabilities::MANAGE_EMAILS ); check_admin_referer( 'bookingistic_admin_email_automation_delete' ); Email_Automation_Repository::delete( absint( wp_unslash( $_POST['automation_id'] ?? 0 ) ) ); wp_safe_redirect( admin_url( 'admin.php?page=bookingistic-emails&deleted=1' ) ); exit; } } }