'iPaymu', 'xendit' => 'Xendit', 'stripe' => 'Stripe', 'paypal' => 'PayPal', 'doku' => 'DOKU', 'cash' => 'cash', 'onsite' => 'cash at the venue', 'comp' => 'complimentary' ); $gateway_label = $gateway_names[ strtolower( $details ) ] ?? ucfirst( $details ); return sprintf( /* translators: %s: value */ __( 'Payment confirmed via %s', 'seathive' ), $gateway_label ); case 'checked_in': return 'qr' === $details ? __( 'Checked in — QR scan', 'seathive' ) : __( 'Checked in — marked manually', 'seathive' ); case 'payment_failed': return $details /* translators: %s: the gateway's own error message */ ? sprintf( __( 'Payment could not be started — %s', 'seathive' ), $details ) : __( 'Payment could not be started', 'seathive' ); case 'login': return $details /* translators: %s: the account's WordPress role(s) */ ? sprintf( __( 'Signed in (%s)', 'seathive' ), $details ) : __( 'Signed in', 'seathive' ); case 'logout': return __( 'Signed out', 'seathive' ); case 'login_failed': return __( 'Failed sign-in attempt', 'seathive' ); case 'cancelled': return __( 'Booking cancelled', 'seathive' ); case 'duplicate_order_blocked': return __( 'Same order sent again — no second order was made', 'seathive' ); case 'payment_webhook': /* translators: %s: what the payment gateway reported */ return sprintf( __( 'Payment gateway: %s', 'seathive' ), $details ); case 'refunded': return sprintf( /* translators: %s: value */ __( 'Refunded: %s', 'seathive' ), $details ); case 'seat_moved': return sprintf( /* translators: %s: value */ __( 'Seat moved: %s', 'seathive' ), $details ); case 'transferred': return sprintf( /* translators: %s: value */ __( 'Ticket transferred: %s', 'seathive' ), $details ); case 'reminder_sent': return sprintf( /* translators: %s: value */ __( 'Reminder sent: %s', 'seathive' ), $details ); case 'auto_cancelled': /* translators: %s: reason */ return sprintf( __( 'Booking auto-cancelled: %s', 'seathive' ), $details ); case 'booking_deleted': /* translators: %s: booking number, buyer, status and seats */ return sprintf( __( 'Booking deleted: %s', 'seathive' ), $details ); case 'email_sent': /* translators: %s: which email and the recipient */ return sprintf( __( 'Email sent: %s', 'seathive' ), $details ); case 'email_failed': /* translators: %s: the mailer's error message */ return sprintf( __( 'Email FAILED: %s', 'seathive' ), $details ); case 'seat_conflict': return '⚠ ' . $details; default: // Escaped once, at output (render_page) — escaping here too // showed "&" instead of "&" in the log. return ucfirst( str_replace( '_', ' ', $action ) ) . ( $details ? ' — ' . $details : '' ); } } public function render_page() { $events = get_posts( array( 'post_type' => 'seatt_event', 'numberposts' => -1 ) ); // 0 = "nothing picked yet" — matches Chart Builder's "select an // event first" screen, so this page doesn't silently default to // whichever event happens to be most recently created. $selected = isset( $_GET['event_id'] ) ? intval( $_GET['event_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only: chooses what to display if ( ! $selected ) { ?>