prefix . self::$table_name; } /** * Create the contact submissions table * * @return void */ public static function create_table() { global $wpdb; $table_name = self::get_table_name(); $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, trainer_id BIGINT(20) UNSIGNED NOT NULL, trainer_profile_id BIGINT(20) UNSIGNED NOT NULL, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, email VARCHAR(255) NOT NULL, phone VARCHAR(20), city VARCHAR(100), state_province VARCHAR(100), company VARCHAR(255), message TEXT, ip_address VARCHAR(45), user_agent TEXT, submission_date DATETIME DEFAULT CURRENT_TIMESTAMP, status ENUM('new', 'read', 'replied', 'archived') DEFAULT 'new', notes TEXT, PRIMARY KEY (id), KEY trainer_id (trainer_id), KEY trainer_profile_id (trainer_profile_id), KEY status (status), KEY submission_date (submission_date), KEY email (email) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // Store version for future upgrades update_option('hvac_contact_submissions_db_version', '1.0.0'); } /** * Drop the table * * @return void */ public static function drop_table() { global $wpdb; $table_name = self::get_table_name(); $wpdb->query("DROP TABLE IF EXISTS $table_name"); delete_option('hvac_contact_submissions_db_version'); } /** * Insert a new contact submission * * @param array $data Submission data * @return int|false Insert ID or false on failure */ public static function insert_submission($data) { global $wpdb; $defaults = [ 'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'submission_date' => current_time('mysql'), 'status' => 'new' ]; $data = wp_parse_args($data, $defaults); // Sanitize data $data = array_map(function($value) { if (is_string($value)) { return sanitize_text_field($value); } return $value; }, $data); // Special handling for email $data['email'] = sanitize_email($data['email']); // Special handling for message if (isset($data['message'])) { $data['message'] = sanitize_textarea_field($data['message']); } $result = $wpdb->insert( self::get_table_name(), $data, [ '%d', // trainer_id '%d', // trainer_profile_id '%s', // first_name '%s', // last_name '%s', // email '%s', // phone '%s', // city '%s', // state_province '%s', // company '%s', // message '%s', // ip_address '%s', // user_agent '%s', // submission_date '%s', // status '%s' // notes ] ); if ($result === false) { error_log('HVAC Contact Submission Error: ' . $wpdb->last_error); return false; } return $wpdb->insert_id; } /** * Get submissions based on criteria * * @param array $args Query arguments * @return array */ public static function get_submissions($args = []) { global $wpdb; $defaults = [ 'trainer_id' => null, 'status' => null, 'limit' => 20, 'offset' => 0, 'orderby' => 'submission_date', 'order' => 'DESC' ]; $args = wp_parse_args($args, $defaults); $table_name = self::get_table_name(); $where = []; $where_values = []; if ($args['trainer_id']) { $where[] = 'trainer_id = %d'; $where_values[] = $args['trainer_id']; } if ($args['status']) { $where[] = 'status = %s'; $where_values[] = $args['status']; } $where_clause = ''; if (!empty($where)) { $where_clause = 'WHERE ' . implode(' AND ', $where); } $orderby = in_array($args['orderby'], ['submission_date', 'id', 'status']) ? $args['orderby'] : 'submission_date'; $order = in_array($args['order'], ['ASC', 'DESC']) ? $args['order'] : 'DESC'; $query = "SELECT * FROM $table_name $where_clause ORDER BY $orderby $order LIMIT %d OFFSET %d"; $where_values[] = $args['limit']; $where_values[] = $args['offset']; if (!empty($where_values)) { $query = $wpdb->prepare($query, $where_values); } return $wpdb->get_results($query); } /** * Get submission by ID * * @param int $id Submission ID * @return object|null */ public static function get_submission($id) { global $wpdb; return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %s WHERE id = %d", self::get_table_name(), $id ) ); } /** * Update submission status * * @param int $id Submission ID * @param string $status New status * @return bool */ public static function update_status($id, $status) { global $wpdb; $valid_statuses = ['new', 'read', 'replied', 'archived']; if (!in_array($status, $valid_statuses)) { return false; } return $wpdb->update( self::get_table_name(), ['status' => $status], ['id' => $id], ['%s'], ['%d'] ) !== false; } /** * Get submission count by trainer * * @param int $trainer_id Trainer user ID * @param string $status Optional status filter * @return int */ public static function get_submission_count($trainer_id, $status = null) { global $wpdb; $table_name = self::get_table_name(); if ($status) { return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE trainer_id = %d AND status = %s", $trainer_id, $status ) ); } return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE trainer_id = %d", $trainer_id ) ); } /** * Clean old submissions * * @param int $days Number of days to keep * @return int Number of deleted rows */ public static function clean_old_submissions($days = 90) { global $wpdb; $table_name = self::get_table_name(); $cutoff_date = date('Y-m-d H:i:s', strtotime("-{$days} days")); return $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE submission_date < %s AND status = 'archived'", $cutoff_date ) ); } }