render_health_check(); ?>
render_trainer_metrics(); ?> render_event_statistics(); ?> render_revenue_statistics(); ?> render_maintenance_controls(); ?>
get_health_status(); ?>

get_trainer_metrics(); ?>

get_event_statistics(); ?>

get_revenue_statistics(); ?>

$
$

'The Events Calendar', 'status' => $tec_active ? 'ok' : 'error', 'status_text' => $tec_active ? __('Active', 'hvac-ce') : __('Inactive', 'hvac-ce'), 'details' => $tec_active ? __('Plugin is active and functioning', 'hvac-ce') : __('Required plugin is not active', 'hvac-ce') ); if (!$tec_active) { $overall_status = 'critical'; } // Check Community Events $ce_active = class_exists('Tribe__Events__Community__Main'); $checks[] = array( 'component' => 'Community Events', 'status' => $ce_active ? 'ok' : 'warning', 'status_text' => $ce_active ? __('Active', 'hvac-ce') : __('Inactive', 'hvac-ce'), 'details' => $ce_active ? __('Plugin is active', 'hvac-ce') : __('Recommended plugin is not active', 'hvac-ce') ); if (!$ce_active && $overall_status !== 'critical') { $overall_status = 'warning'; } // Check database tables global $wpdb; $tables_exist = $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}posts'") === "{$wpdb->prefix}posts"; $checks[] = array( 'component' => 'Database Tables', 'status' => $tables_exist ? 'ok' : 'error', 'status_text' => $tables_exist ? __('OK', 'hvac-ce') : __('Error', 'hvac-ce'), 'details' => $tables_exist ? __('All required tables exist', 'hvac-ce') : __('Missing required database tables', 'hvac-ce') ); // Check file permissions $upload_dir = wp_upload_dir(); $uploads_writable = wp_is_writable($upload_dir['basedir']); $checks[] = array( 'component' => 'File Permissions', 'status' => $uploads_writable ? 'ok' : 'warning', 'status_text' => $uploads_writable ? __('OK', 'hvac-ce') : __('Warning', 'hvac-ce'), 'details' => $uploads_writable ? __('Upload directory is writable', 'hvac-ce') : __('Upload directory is not writable', 'hvac-ce') ); // Memory limit check $memory_limit = wp_convert_hr_to_bytes(ini_get('memory_limit')); $recommended_limit = 256 * MB_IN_BYTES; $checks[] = array( 'component' => 'Memory Limit', 'status' => $memory_limit >= $recommended_limit ? 'ok' : 'warning', 'status_text' => size_format($memory_limit), 'details' => $memory_limit >= $recommended_limit ? __('Memory limit is sufficient', 'hvac-ce') : sprintf(__('Recommended: %s or higher', 'hvac-ce'), size_format($recommended_limit)) ); return array( 'overall_status' => $overall_status, 'status_text' => $this->get_status_text($overall_status), 'checks' => $checks ); } /** * Get status text */ private function get_status_text($status) { switch ($status) { case 'healthy': return __('All Systems Operational', 'hvac-ce'); case 'warning': return __('Minor Issues Detected', 'hvac-ce'); case 'critical': return __('Critical Issues Found', 'hvac-ce'); default: return __('Unknown Status', 'hvac-ce'); } } /** * Get trainer metrics */ private function get_trainer_metrics() { global $wpdb; // Total trainers $total_trainers = count(get_users(array( 'role' => 'trainer', 'fields' => 'ID' ))); // New trainers this week $week_ago = date('Y-m-d H:i:s', strtotime('-1 week')); $new_trainers_week = count(get_users(array( 'role' => 'trainer', 'date_query' => array( array( 'after' => $week_ago, 'inclusive' => true ) ), 'fields' => 'ID' ))); // Login statistics (would require custom tracking) $total_logins = get_option('hvac_total_logins', 0); $logins_week = get_option('hvac_logins_week', 0); return array( 'total_trainers' => $total_trainers, 'new_trainers_week' => $new_trainers_week, 'total_logins' => $total_logins, 'logins_week' => $logins_week ); } /** * Get event statistics */ private function get_event_statistics() { global $wpdb; $now = current_time('mysql'); // Total events $total_events = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->posts} p WHERE p.post_type = %s AND p.post_status IN ('publish', 'draft', 'private') ", 'tribe_events')); // Past events $past_events = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = %s AND p.post_status = 'publish' AND pm.meta_key = '_EventEndDate' AND pm.meta_value < %s ", 'tribe_events', $now)); // Future events $future_events = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = %s AND p.post_status = 'publish' AND pm.meta_key = '_EventStartDate' AND pm.meta_value > %s ", 'tribe_events', $now)); // Draft events $draft_events = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'draft' ", 'tribe_events')); // Cancelled events (assuming there's a meta field for cancelled status) $cancelled_events = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = %s AND pm.meta_key = '_event_cancelled' AND pm.meta_value = '1' ", 'tribe_events')); // Total attendees using Event Tickets data $total_attendees = 0; // Check if Event Tickets is active if (class_exists('Tribe__Tickets__Main')) { // Get all attendee post types from Event Tickets $attendee_types = [ 'tribe_rsvp_attendees', // RSVP attendees 'tribe_tpp_attendees', // PayPal attendees 'tec_tc_attendee' // Tickets Commerce attendees ]; // Preparing for the SQL query $types_placeholder = implode(', ', array_fill(0, count($attendee_types), '%s')); $query_args = $attendee_types; // Add status condition - Public order statuses // (based on Tribe__Tickets__Attendee_Repository class) $public_order_statuses = [ 'yes', // RSVP 'completed', // PayPal Legacy 'wc-completed', // WooCommerce 'publish', // Easy Digital Downloads, Legacy 'complete', // Easy Digital Downloads ]; // Count attendees with proper status foreach ($attendee_types as $post_type) { $count = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish' ", $post_type)); $total_attendees += (int)$count; } // If WooCommerce Tickets is active, count WooCommerce ticket attendees too if (class_exists('Tribe__Tickets_Plus__Commerce__WooCommerce__Main')) { $wc_attendees = $wpdb->get_var(" SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_tribe_wooticket_attendance' "); $total_attendees += (int)$wc_attendees; } } return array( 'total_events' => $total_events, 'past_events' => $past_events, 'future_events' => $future_events, 'draft_events' => $draft_events, 'cancelled_events' => $cancelled_events, 'total_attendees' => $total_attendees ); } /** * Get revenue statistics */ private function get_revenue_statistics() { global $wpdb; $week_ago = date('Y-m-d H:i:s', strtotime('-1 week')); $total_revenue = 0; $revenue_week = 0; $total_purchases = 0; $purchases_week = 0; // If using Event Tickets Plus with WooCommerce if (class_exists('Tribe__Tickets_Plus__Commerce__WooCommerce__Main')) { // Gather data from WooCommerce orders that contain tickets // First, find all orders with ticket items $ticket_product_ids = $wpdb->get_col(" SELECT ID FROM {$wpdb->posts} WHERE post_type = 'tribe_wooticket' "); if (!empty($ticket_product_ids)) { $ticket_product_ids_str = implode(',', array_map('intval', $ticket_product_ids)); // Find orders that contain ticket products $ticket_order_ids = $wpdb->get_col(" SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items oi JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id WHERE oim.meta_key = '_product_id' AND oim.meta_value IN ({$ticket_product_ids_str}) "); if (!empty($ticket_order_ids)) { $ticket_order_ids_str = implode(',', array_map('intval', $ticket_order_ids)); // Total revenue from these orders $total_revenue = $wpdb->get_var(" SELECT SUM(meta.meta_value) FROM {$wpdb->postmeta} meta JOIN {$wpdb->posts} posts ON meta.post_id = posts.ID WHERE meta.meta_key = '_order_total' AND posts.ID IN ({$ticket_order_ids_str}) AND posts.post_status IN ('wc-completed', 'wc-processing') "); // Revenue this week $revenue_week = $wpdb->get_var($wpdb->prepare(" SELECT SUM(meta.meta_value) FROM {$wpdb->postmeta} meta JOIN {$wpdb->posts} posts ON meta.post_id = posts.ID WHERE meta.meta_key = '_order_total' AND posts.ID IN ({$ticket_order_ids_str}) AND posts.post_status IN ('wc-completed', 'wc-processing') AND posts.post_date >= %s ", $week_ago)); // Total purchases (count of orders) $total_purchases = count($ticket_order_ids); // Purchases this week $purchases_week = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->posts} WHERE ID IN ({$ticket_order_ids_str}) AND post_status IN ('wc-completed', 'wc-processing') AND post_date >= %s ", $week_ago)); } } } // Check for Tickets Commerce data (modern Event Tickets) if (class_exists('TEC\\Tickets\\Commerce\\Order')) { // Get orders through Tickets Commerce $tc_order_post_type = \TEC\Tickets\Commerce\Order::POSTTYPE; $tc_completed_statuses = [ 'completed', 'pfc-completed', 'tpay-completed', 'paid' ]; $placeholders = implode(', ', array_fill(0, count($tc_completed_statuses), '%s')); $query_args = $tc_completed_statuses; // Calculate total revenue $tc_total_revenue = $wpdb->get_var($wpdb->prepare(" SELECT SUM(meta.meta_value) FROM {$wpdb->postmeta} meta JOIN {$wpdb->posts} posts ON meta.post_id = posts.ID WHERE meta.meta_key = '_tec_tc_order_total' AND posts.post_type = %s AND posts.post_status IN ($placeholders) ", array_merge([$tc_order_post_type], $query_args))); // Calculate this week's revenue $query_args[] = $week_ago; $tc_revenue_week = $wpdb->get_var($wpdb->prepare(" SELECT SUM(meta.meta_value) FROM {$wpdb->postmeta} meta JOIN {$wpdb->posts} posts ON meta.post_id = posts.ID WHERE meta.meta_key = '_tec_tc_order_total' AND posts.post_type = %s AND posts.post_status IN ($placeholders) AND posts.post_date >= %s ", array_merge([$tc_order_post_type], $query_args))); // Count total purchases $tc_total_purchases = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status IN ($placeholders) ", array_merge([$tc_order_post_type], $tc_completed_statuses))); // Count purchases this week $tc_purchases_week = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status IN ($placeholders) AND post_date >= %s ", array_merge([$tc_order_post_type], $tc_completed_statuses, [$week_ago]))); // Add TC values to totals $total_revenue += (float)$tc_total_revenue; $revenue_week += (float)$tc_revenue_week; $total_purchases += (int)$tc_total_purchases; $purchases_week += (int)$tc_purchases_week; } // Tribe Commerce PayPal (legacy from Event Tickets) if (class_exists('Tribe__Tickets__Commerce__PayPal__Main')) { // PayPal orders are stored as posts with meta data $pp_completed_status = 'completed'; // Calculate total revenue $pp_total_revenue = $wpdb->get_var($wpdb->prepare(" SELECT SUM(meta.meta_value) FROM {$wpdb->postmeta} meta JOIN {$wpdb->postmeta} status ON status.post_id = meta.post_id WHERE meta.meta_key = '_tribe_tpp_gross' AND status.meta_key = '_tribe_tpp_status' AND status.meta_value = %s ", $pp_completed_status)); // Calculate this week's revenue $pp_revenue_week = $wpdb->get_var($wpdb->prepare(" SELECT SUM(meta.meta_value) FROM {$wpdb->postmeta} meta JOIN {$wpdb->postmeta} status ON status.post_id = meta.post_id JOIN {$wpdb->posts} posts ON meta.post_id = posts.ID WHERE meta.meta_key = '_tribe_tpp_gross' AND status.meta_key = '_tribe_tpp_status' AND status.meta_value = %s AND posts.post_date >= %s ", $pp_completed_status, $week_ago)); // Count total PayPal orders $pp_total_purchases = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key = '_tribe_tpp_status' AND meta_value = %s ", $pp_completed_status)); // Count purchases this week $pp_purchases_week = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT meta.post_id) FROM {$wpdb->postmeta} meta JOIN {$wpdb->posts} posts ON meta.post_id = posts.ID WHERE meta.meta_key = '_tribe_tpp_status' AND meta.meta_value = %s AND posts.post_date >= %s ", $pp_completed_status, $week_ago)); // Add PayPal values to totals $total_revenue += (float)$pp_total_revenue; $revenue_week += (float)$pp_revenue_week; $total_purchases += (int)$pp_total_purchases; $purchases_week += (int)$pp_purchases_week; } return array( 'total_revenue' => $total_revenue ?: 0, 'revenue_week' => $revenue_week ?: 0, 'total_purchases' => $total_purchases ?: 0, 'purchases_week' => $purchases_week ?: 0 ); } /** * AJAX handler for refreshing metrics */ public function ajax_refresh_metrics() { check_ajax_referer('hvac_admin_nonce', 'nonce'); if (!current_user_can('manage_options')) { wp_die('Unauthorized'); } $metrics = array( 'trainer' => $this->get_trainer_metrics(), 'events' => $this->get_event_statistics(), 'revenue' => $this->get_revenue_statistics() ); wp_send_json_success($metrics); } /** * AJAX handler for exporting metrics */ public function ajax_export_metrics() { check_ajax_referer('hvac_admin_nonce', 'nonce'); if (!current_user_can('manage_options')) { wp_die('Unauthorized'); } $metrics = array( 'trainer' => $this->get_trainer_metrics(), 'events' => $this->get_event_statistics(), 'revenue' => $this->get_revenue_statistics() ); // Generate CSV $csv_data = array(); // Headers $csv_data[] = array('Metric Category', 'Metric', 'Value'); // Trainer metrics foreach ($metrics['trainer'] as $key => $value) { $csv_data[] = array('Trainer Metrics', $this->humanize_key($key), $value); } // Event statistics foreach ($metrics['events'] as $key => $value) { $csv_data[] = array('Event Statistics', $this->humanize_key($key), $value); } // Revenue statistics foreach ($metrics['revenue'] as $key => $value) { if (strpos($key, 'revenue') !== false) { $value = '$' . number_format($value, 2); } $csv_data[] = array('Revenue Statistics', $this->humanize_key($key), $value); } // Add timestamp $csv_data[] = array('Export Date', date('Y-m-d H:i:s'), ''); wp_send_json_success(array( 'csv' => $csv_data, 'filename' => 'hvac-metrics-' . date('Y-m-d') . '.csv' )); } /** * AJAX handler for maintenance actions */ public function ajax_run_maintenance() { check_ajax_referer('hvac_admin_nonce', 'nonce'); if (!current_user_can('manage_options')) { wp_die('Unauthorized'); } $action = sanitize_text_field($_POST['action_type']); $result = array(); switch ($action) { case 'clear_transients': $result = $this->clear_transients(); break; case 'optimize_tables': $result = $this->optimize_tables(); break; case 'regenerate_roles': $result = $this->regenerate_roles(); break; case 'sync_event_meta': $result = $this->sync_event_metadata(); break; default: $result = array( 'success' => false, 'message' => __('Invalid maintenance action', 'hvac-ce') ); } if ($result['success']) { wp_send_json_success($result); } else { wp_send_json_error($result); } } /** * Clear transients */ private function clear_transients() { global $wpdb; // Clear all transients $query = "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_%' OR option_name LIKE '_site_transient_%'"; $deleted = $wpdb->query($query); // Clear object cache wp_cache_flush(); return array( 'success' => true, 'message' => sprintf(__('Cleared %d transients and flushed object cache', 'hvac-ce'), $deleted) ); } /** * Optimize database tables */ private function optimize_tables() { global $wpdb; $tables = array( $wpdb->posts, $wpdb->postmeta, $wpdb->users, $wpdb->usermeta, $wpdb->options ); $optimized = 0; foreach ($tables as $table) { if ($wpdb->query("OPTIMIZE TABLE $table")) { $optimized++; } } return array( 'success' => true, 'message' => sprintf(__('Optimized %d database tables', 'hvac-ce'), $optimized) ); } /** * Regenerate user roles */ private function regenerate_roles() { // Re-add custom roles $role_manager = new HVAC_Role_Manager(); $role_manager->add_roles(); return array( 'success' => true, 'message' => __('User roles regenerated successfully', 'hvac-ce') ); } /** * Sync event metadata */ private function sync_event_metadata() { global $wpdb; // Example: Ensure all events have required metadata $events = get_posts(array( 'post_type' => 'tribe_events', 'posts_per_page' => -1, 'post_status' => array('publish', 'draft', 'private') )); $synced = 0; foreach ($events as $event) { // Check for required meta fields if (!get_post_meta($event->ID, '_EventStartDate', true)) { // Set default start date if missing update_post_meta($event->ID, '_EventStartDate', current_time('mysql')); $synced++; } } return array( 'success' => true, 'message' => sprintf(__('Synced metadata for %d events', 'hvac-ce'), $synced) ); } /** * Humanize key for display */ private function humanize_key($key) { $key = str_replace('_', ' ', $key); return ucwords($key); } }