init_hooks(); } /** * Initialize hooks */ private function init_hooks() { // AJAX handlers add_action('wp_ajax_hvac_submit_contact_form', [$this, 'ajax_submit_form']); add_action('wp_ajax_nopriv_hvac_submit_contact_form', [$this, 'ajax_submit_form']); // Admin hooks add_action('admin_menu', [$this, 'add_admin_menu']); add_action('admin_init', [$this, 'register_settings']); // Cron job for cleanup add_action('hvac_cleanup_old_submissions', [$this, 'cleanup_old_submissions']); if (!wp_next_scheduled('hvac_cleanup_old_submissions')) { wp_schedule_event(time(), 'daily', 'hvac_cleanup_old_submissions'); } } /** * AJAX handler for form submission */ public function ajax_submit_form() { check_ajax_referer('hvac_find_trainer', 'nonce'); $form_data = [ 'trainer_id' => intval($_POST['trainer_id'] ?? 0), 'trainer_profile_id' => intval($_POST['trainer_profile_id'] ?? 0), 'first_name' => sanitize_text_field($_POST['first_name'] ?? ''), 'last_name' => sanitize_text_field($_POST['last_name'] ?? ''), 'email' => sanitize_email($_POST['email'] ?? ''), 'phone' => sanitize_text_field($_POST['phone'] ?? ''), 'city' => sanitize_text_field($_POST['city'] ?? ''), 'state_province' => sanitize_text_field($_POST['state_province'] ?? ''), 'company' => sanitize_text_field($_POST['company'] ?? ''), 'message' => sanitize_textarea_field($_POST['message'] ?? '') ]; // Validate form data $validation = $this->validate_form_data($form_data); if (!$validation['valid']) { wp_send_json_error([ 'message' => 'Please correct the following errors:', 'errors' => $validation['errors'] ]); } // Check rate limiting if (!$this->check_submission_rate_limit($form_data['email'])) { wp_send_json_error([ 'message' => 'You have reached the submission limit. Please try again later.' ]); } // Save submission $submission_id = $this->save_submission($form_data); if (!$submission_id) { wp_send_json_error([ 'message' => 'An error occurred while saving your submission. Please try again.' ]); } // Send notifications $this->send_notifications($submission_id); wp_send_json_success([ 'message' => 'Your message has been sent successfully! The trainer will contact you soon.', 'submission_id' => $submission_id ]); } /** * Validate form data * * @param array $data Form data * @return array Validation result */ public function validate_form_data($data) { $errors = []; $valid = true; // Required fields $required_fields = [ 'trainer_id' => 'Trainer ID', 'trainer_profile_id' => 'Trainer Profile ID', 'first_name' => 'First Name', 'last_name' => 'Last Name', 'email' => 'Email' ]; foreach ($required_fields as $field => $label) { if (empty($data[$field])) { $errors[$field] = $label . ' is required.'; $valid = false; } } // Validate email format if (!empty($data['email']) && !is_email($data['email'])) { $errors['email'] = 'Please enter a valid email address.'; $valid = false; } // Validate phone format (optional) if (!empty($data['phone'])) { $phone = preg_replace('/[^0-9+()-.\s]/', '', $data['phone']); if (strlen($phone) < 10) { $errors['phone'] = 'Please enter a valid phone number.'; $valid = false; } } // Validate trainer exists if (!empty($data['trainer_id'])) { $trainer = get_userdata($data['trainer_id']); if (!$trainer || !in_array('hvac_trainer', $trainer->roles) && !in_array('hvac_master_trainer', $trainer->roles)) { $errors['trainer_id'] = 'Invalid trainer selected.'; $valid = false; } } // Validate trainer profile exists if (!empty($data['trainer_profile_id'])) { $profile = get_post($data['trainer_profile_id']); if (!$profile || $profile->post_type !== 'trainer_profile') { $errors['trainer_profile_id'] = 'Invalid trainer profile.'; $valid = false; } } // Message length if (!empty($data['message']) && strlen($data['message']) > 5000) { $errors['message'] = 'Message is too long (maximum 5000 characters).'; $valid = false; } return [ 'valid' => $valid, 'errors' => $errors ]; } /** * Check submission rate limit * * @param string $email Email address * @return bool True if within limits */ public function check_submission_rate_limit($email) { $transient_key = 'hvac_contact_' . md5($email); $submissions = get_transient($transient_key); if ($submissions === false) { $submissions = 0; } if ($submissions >= self::RATE_LIMIT_SUBMISSIONS) { return false; } set_transient($transient_key, $submissions + 1, self::RATE_LIMIT_WINDOW); return true; } /** * Save submission to database * * @param array $data Form data * @return int|false Submission ID or false on failure */ public function save_submission($data) { // Include the database table class if (!class_exists('HVAC_Contact_Submissions_Table')) { require_once HVAC_PLUGIN_DIR . 'includes/database/class-hvac-contact-submissions-table.php'; } return HVAC_Contact_Submissions_Table::insert_submission($data); } /** * Send notifications for new submission * * @param int $submission_id Submission ID */ public function send_notifications($submission_id) { global $wpdb; $table_name = $wpdb->prefix . 'hvac_contact_submissions'; $submission = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $submission_id) ); if (!$submission) { return; } // Get trainer email $trainer = get_userdata($submission->trainer_id); if (!$trainer) { return; } // Send email to trainer $this->send_trainer_notification($trainer, $submission); // Send confirmation to submitter $this->send_submitter_confirmation($submission); // Send admin notification if enabled if (get_option('hvac_contact_admin_notifications', false)) { $this->send_admin_notification($submission); } } /** * Send notification email to trainer * * @param WP_User $trainer Trainer user object * @param object $submission Submission data */ private function send_trainer_notification($trainer, $submission) { $subject = sprintf( 'New Contact Request from %s %s', $submission->first_name, $submission->last_name ); $message = $this->get_email_template('trainer_notification', [ 'trainer_name' => $trainer->display_name, 'submitter_name' => $submission->first_name . ' ' . $submission->last_name, 'submitter_email' => $submission->email, 'submitter_phone' => $submission->phone, 'submitter_city' => $submission->city, 'submitter_state' => $submission->state_province, 'submitter_company' => $submission->company, 'submitter_message' => $submission->message, 'submission_date' => $submission->submission_date, 'dashboard_url' => home_url('/trainer/dashboard/') ]); $headers = [ 'Content-Type: text/html; charset=UTF-8', 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>', 'Reply-To: ' . $submission->first_name . ' ' . $submission->last_name . ' <' . $submission->email . '>' ]; wp_mail($trainer->user_email, $subject, $message, $headers); } /** * Send confirmation email to submitter * * @param object $submission Submission data */ private function send_submitter_confirmation($submission) { $trainer = get_userdata($submission->trainer_id); if (!$trainer) { return; } $subject = 'Your message has been sent to ' . $trainer->display_name; $message = $this->get_email_template('submitter_confirmation', [ 'submitter_name' => $submission->first_name, 'trainer_name' => $trainer->display_name, 'message_copy' => $submission->message, 'submission_date' => $submission->submission_date ]); $headers = [ 'Content-Type: text/html; charset=UTF-8', 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>' ]; wp_mail($submission->email, $subject, $message, $headers); } /** * Send admin notification * * @param object $submission Submission data */ private function send_admin_notification($submission) { $admin_email = get_option('hvac_contact_admin_email', get_option('admin_email')); $trainer = get_userdata($submission->trainer_id); $subject = 'New Contact Form Submission on Find a Trainer'; $message = $this->get_email_template('admin_notification', [ 'trainer_name' => $trainer ? $trainer->display_name : 'Unknown', 'submitter_name' => $submission->first_name . ' ' . $submission->last_name, 'submitter_email' => $submission->email, 'submitter_phone' => $submission->phone, 'submitter_company' => $submission->company, 'submission_date' => $submission->submission_date, 'admin_url' => admin_url('admin.php?page=hvac-contact-submissions') ]); $headers = [ 'Content-Type: text/html; charset=UTF-8', 'From: ' . get_bloginfo('name') . ' ' ]; wp_mail($admin_email, $subject, $message, $headers); } /** * Get email template * * @param string $template Template name * @param array $variables Template variables * @return string Email HTML */ private function get_email_template($template, $variables = []) { $template_file = HVAC_PLUGIN_DIR . 'templates/emails/' . $template . '.php'; if (!file_exists($template_file)) { // Use default template return $this->get_default_email_template($template, $variables); } extract($variables); ob_start(); include $template_file; return ob_get_clean(); } /** * Get default email template * * @param string $template Template name * @param array $vars Template variables * @return string Email HTML */ private function get_default_email_template($template, $vars) { $html = ''; $html .= '
'; switch ($template) { case 'trainer_notification': $html .= '

New Contact Request

'; $html .= '

Hello ' . esc_html($vars['trainer_name']) . ',

'; $html .= '

You have received a new contact request through the Find a Trainer directory.

'; $html .= '

Contact Details:

'; $html .= ''; if ($vars['submitter_message']) { $html .= '

Message:

'; $html .= '

' . nl2br(esc_html($vars['submitter_message'])) . '

'; } $html .= '

View in Dashboard

'; break; case 'submitter_confirmation': $html .= '

Message Sent Successfully

'; $html .= '

Hello ' . esc_html($vars['submitter_name']) . ',

'; $html .= '

Your message has been successfully sent to ' . esc_html($vars['trainer_name']) . '. They will contact you soon.

'; if ($vars['message_copy']) { $html .= '

Your Message:

'; $html .= '

' . nl2br(esc_html($vars['message_copy'])) . '

'; } $html .= '

Thank you for using our Find a Trainer directory!

'; break; case 'admin_notification': $html .= '

New Contact Form Submission

'; $html .= '

A new contact form has been submitted on the Find a Trainer page.

'; $html .= '

Details:

'; $html .= ''; $html .= '

View All Submissions

'; break; } $html .= '
'; $html .= '

This is an automated message from ' . get_bloginfo('name') . '

'; $html .= '
'; return $html; } /** * Add admin menu for contact submissions */ public function add_admin_menu() { add_submenu_page( 'hvac-plugin', 'Contact Submissions', 'Contact Submissions', 'manage_options', 'hvac-contact-submissions', [$this, 'render_admin_page'] ); } /** * Register plugin settings */ public function register_settings() { register_setting('hvac_contact_settings', 'hvac_contact_admin_notifications'); register_setting('hvac_contact_settings', 'hvac_contact_admin_email'); register_setting('hvac_contact_settings', 'hvac_contact_retention_days'); } /** * Render admin page for contact submissions */ public function render_admin_page() { if (!class_exists('HVAC_Contact_Submissions_Table')) { require_once HVAC_PLUGIN_DIR . 'includes/database/class-hvac-contact-submissions-table.php'; } // Handle status updates if (isset($_POST['update_status']) && isset($_POST['submission_id'])) { check_admin_referer('hvac_update_submission_status'); $submission_id = intval($_POST['submission_id']); $new_status = sanitize_text_field($_POST['new_status']); HVAC_Contact_Submissions_Table::update_status($submission_id, $new_status); echo '

Status updated successfully!

'; } // Get submissions $args = [ 'limit' => 50, 'offset' => (get_query_var('paged', 1) - 1) * 50 ]; if (isset($_GET['status'])) { $args['status'] = sanitize_text_field($_GET['status']); } $submissions = HVAC_Contact_Submissions_Table::get_submissions($args); ?>

Contact Submissions

trainer_id); ?>
ID Date From Email Trainer Message Status Actions
id); ?> submission_date))); ?> first_name . ' ' . $submission->last_name); ?> email); ?> display_name) : 'Unknown'; ?> message, 0, 100)) . (strlen($submission->message) > 100 ? '...' : ''); ?> status)); ?>
No submissions found.
0) { error_log("HVAC Contact Form: Cleaned up $deleted old submissions"); } } }