190) { return 'Please enter a shorter email address.'; } $parts = explode('@', $email); if (count($parts) !== 2) { return 'Please enter a valid email address.'; } [$local, $domain] = $parts; if ($local === '' || $domain === '') { return 'Please enter a valid email address.'; } if (is_disposable_email_domain($domain)) { return 'Please use your real email address. Temporary or disposable inboxes are not allowed.'; } if (!has_valid_email_dns($domain)) { return 'Please use an email with a real mail domain.'; } return null; } function clean_text_input($value, int $max_length = 255): string { $value = trim((string) $value); $value = strip_tags($value); $value = preg_replace('/[-]/u', '', $value) ?? ''; if (function_exists('mb_substr')) { return mb_substr($value, 0, $max_length); } return substr($value, 0, $max_length); } function normalize_timezone_input($value): ?string { $timezone = clean_text_input($value, 100); if ($timezone === '') { return null; } return in_array($timezone, timezone_identifiers_list(), true) ? $timezone : null; } // --- Helper function to fetch webinar details --- function get_webinar_details($id) { if (empty($id)) return null; try { $stmt = db()->prepare("SELECT id, title, description, scheduled_at, presenter FROM webinars WHERE id = ?"); $stmt->execute([$id]); return $stmt->fetch(PDO::FETCH_ASSOC); } catch (PDOException $e) { error_log("Database error fetching webinar ID $id: " . $e->getMessage()); return null; } } // --- Only allow POST requests --- if ($_SERVER["REQUEST_METHOD"] !== "POST") { echo json_encode(['success' => false, 'error' => 'Invalid request method.']); exit; } $webinar_id = filter_input(INPUT_POST, 'webinar_id', FILTER_VALIDATE_INT) ?: 1; $webinar = get_webinar_details($webinar_id); if (!$webinar) { http_response_code(404); echo json_encode(['success' => false, 'error' => 'Webinar not found.']); exit; } // --- DATA CAPTURE --- $email_input = (string) filter_input(INPUT_POST, 'email', FILTER_UNSAFE_RAW); $email = normalize_email_address($email_input); $email_error = validate_registration_email($email); $first_name = clean_text_input(filter_input(INPUT_POST, 'first_name', FILTER_UNSAFE_RAW), 120); $last_name = clean_text_input(filter_input(INPUT_POST, 'last_name', FILTER_UNSAFE_RAW), 120); $company = clean_text_input(filter_input(INPUT_POST, 'company', FILTER_UNSAFE_RAW), 180); $how_did_you_hear = clean_text_input(filter_input(INPUT_POST, 'how_did_you_hear', FILTER_UNSAFE_RAW), 120); $timezone = normalize_timezone_input(filter_input(INPUT_POST, 'timezone', FILTER_UNSAFE_RAW)); $allowed_sources = [ 'Social Media', 'LinkedIn', 'Reddit', 'Threads', 'Advertisement', 'ChatGPT', 'Flatlogic Community Discord', 'Other', ]; // --- VALIDATION --- if (!$first_name || !$last_name || $email === '' || $how_did_you_hear === '') { echo json_encode(['success' => false, 'error' => 'Please fill out all required fields.']); exit; } if ($email_error !== null) { echo json_encode(['success' => false, 'error' => $email_error]); exit; } if (!in_array($how_did_you_hear, $allowed_sources, true)) { echo json_encode(['success' => false, 'error' => 'Please choose how you heard about this webinar from the list.']); exit; } try { // --- CHECK IF ALREADY REGISTERED OR SOFT-DELETED -- - $stmt = db()->prepare("SELECT id, deleted_at FROM attendees WHERE webinar_id = ? AND email = ?"); $stmt->execute([$webinar_id, $email]); $existing_user = $stmt->fetch(PDO::FETCH_ASSOC); $send_email = false; if ($existing_user) { if ($existing_user['deleted_at'] !== null) { // --- USER IS SOFT-DELETED, SO REACTIVATE AND UPDATE --- $sql = "UPDATE attendees SET first_name = ?, last_name = ?, company = ?, how_did_you_hear = ?, timezone = ?, deleted_at = NULL, created_at = NOW(), consented = 1 WHERE id = ?"; $stmt = db()->prepare($sql); $stmt->execute([$first_name, $last_name, $company, $how_did_you_hear, $timezone, $existing_user['id']]); $send_email = true; } else { // --- USER IS ACTIVE, SO REJECT --- echo json_encode(['success' => false, 'error' => 'You are already registered for this webinar.']); exit; } } else { // --- REGISTER NEW USER --- $password_hash = password_hash($email . time(), PASSWORD_DEFAULT); $sql = "INSERT INTO attendees (webinar_id, first_name, last_name, email, company, how_did_you_hear, password, timezone, consented) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1)"; $stmt = db()->prepare($sql); $stmt->execute([$webinar_id, $first_name, $last_name, $email, $company, $how_did_you_hear, $password_hash, $timezone]); $send_email = true; } $email_payload = webinar_build_email_payload($first_name, $webinar, false); $schedule = $email_payload['schedule']; $event_title = $email_payload['event_title']; $google_link = $email_payload['google_link']; $outlook_link = $email_payload['outlook_link']; if ($send_email) { MailService::sendMail($email, $email_payload['subject'], $email_payload['html'], $email_payload['text']); } echo json_encode([ 'success' => true, 'webinar_title' => $event_title . '
Professional Vibe-Coding Webinar', 'google_link' => $google_link, 'outlook_link' => $outlook_link, 'schedule_line' => $schedule['timezone_line'] ]); } catch (Exception $e) { http_response_code(500); echo json_encode(['success' => false, 'error' => 'An unexpected server error occurred. Please try again.']); }