upskill-event-manager/includes/admin/class-admin-dashboard.php
bengizmo 37f4180e1c feat: Add massive missing plugin infrastructure to repository
🚨 CRITICAL: Fixed deployment blockers by adding missing core directories:

**Community System (CRITICAL)**
- includes/community/ - Login_Handler and all community classes
- templates/community/ - Community login forms

**Certificate System (CRITICAL)**
- includes/certificates/ - 8+ certificate classes and handlers
- templates/certificates/ - Certificate reports and generation templates

**Core Individual Classes (CRITICAL)**
- includes/class-hvac-event-summary.php
- includes/class-hvac-trainer-profile-manager.php
- includes/class-hvac-master-dashboard-data.php
- Plus 40+ other individual HVAC classes

**Major Feature Systems (HIGH)**
- includes/database/ - Training leads database tables
- includes/find-trainer/ - Find trainer directory and MapGeo integration
- includes/google-sheets/ - Google Sheets integration system
- includes/zoho/ - Complete Zoho CRM integration
- includes/communication/ - Communication templates system

**Template Infrastructure**
- templates/attendee/, templates/email-attendees/
- templates/event-summary/, templates/status/
- templates/template-parts/ - Shared template components

**Impact:**
- 70+ files added covering 10+ missing directories
- Resolves ALL deployment blockers and feature breakdowns
- Plugin activation should now work correctly
- Multi-machine deployment fully supported

🔧 Generated with Claude Code

Co-Authored-By: Ben Reed <ben@tealmaker.com>
2025-08-11 13:30:11 -03:00

858 lines
No EOL
32 KiB
PHP

<?php
/**
* Admin Dashboard for HVAC Community Events
*
* @package HVAC_Community_Events
* @subpackage Admin
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Admin Dashboard class
*/
class HVAC_Admin_Dashboard {
/**
* Constructor
*/
public function __construct() {
add_action('wp_ajax_hvac_refresh_dashboard_metrics', array($this, 'ajax_refresh_metrics'));
add_action('wp_ajax_hvac_export_metrics', array($this, 'ajax_export_metrics'));
add_action('wp_ajax_hvac_run_maintenance', array($this, 'ajax_run_maintenance'));
}
/**
* Render the dashboard page
*/
public function render_page() {
?>
<div class="wrap hvac-admin-dashboard">
<h1><?php _e('HVAC Community Events Dashboard', 'hvac-ce'); ?></h1>
<?php $this->render_health_check(); ?>
<div class="hvac-dashboard-grid">
<?php $this->render_trainer_metrics(); ?>
<?php $this->render_event_statistics(); ?>
<?php $this->render_revenue_statistics(); ?>
<?php $this->render_maintenance_controls(); ?>
</div>
<div class="hvac-dashboard-actions">
<button class="button button-primary" id="refresh-metrics">
<?php _e('Refresh All Metrics', 'hvac-ce'); ?>
</button>
<button class="button" id="export-metrics">
<?php _e('Export Metrics (CSV)', 'hvac-ce'); ?>
</button>
</div>
</div>
<?php
}
/**
* Render health check section
*/
private function render_health_check() {
$health_status = $this->get_health_status();
?>
<div class="hvac-health-check">
<h2><?php _e('System Health', 'hvac-ce'); ?></h2>
<div class="health-status <?php echo esc_attr($health_status['overall_status']); ?>">
<span class="status-indicator"></span>
<?php _e('Overall Status:', 'hvac-ce'); ?>
<strong><?php echo esc_html($health_status['status_text']); ?></strong>
</div>
<table class="wp-list-table widefat striped">
<thead>
<tr>
<th><?php _e('Component', 'hvac-ce'); ?></th>
<th><?php _e('Status', 'hvac-ce'); ?></th>
<th><?php _e('Details', 'hvac-ce'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($health_status['checks'] as $check): ?>
<tr>
<td><?php echo esc_html($check['component']); ?></td>
<td>
<span class="status-badge status-<?php echo esc_attr($check['status']); ?>">
<?php echo esc_html($check['status_text']); ?>
</span>
</td>
<td><?php echo esc_html($check['details']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
}
/**
* Render trainer metrics widget
*/
private function render_trainer_metrics() {
$metrics = $this->get_trainer_metrics();
?>
<div class="hvac-dashboard-widget">
<h3><?php _e('Trainer Metrics', 'hvac-ce'); ?></h3>
<div class="metrics-grid">
<div class="metric">
<div class="metric-value"><?php echo esc_html($metrics['total_trainers']); ?></div>
<div class="metric-label"><?php _e('Total Trainers', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($metrics['new_trainers_week']); ?></div>
<div class="metric-label"><?php _e('New This Week', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($metrics['total_logins']); ?></div>
<div class="metric-label"><?php _e('Total Logins', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($metrics['logins_week']); ?></div>
<div class="metric-label"><?php _e('Logins This Week', 'hvac-ce'); ?></div>
</div>
</div>
</div>
<?php
}
/**
* Render event statistics widget
*/
private function render_event_statistics() {
$stats = $this->get_event_statistics();
?>
<div class="hvac-dashboard-widget">
<h3><?php _e('Event Statistics', 'hvac-ce'); ?></h3>
<div class="metrics-grid">
<div class="metric">
<div class="metric-value"><?php echo esc_html($stats['total_events']); ?></div>
<div class="metric-label"><?php _e('Total Events', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($stats['past_events']); ?></div>
<div class="metric-label"><?php _e('Past Events', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($stats['future_events']); ?></div>
<div class="metric-label"><?php _e('Future Events', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($stats['draft_events']); ?></div>
<div class="metric-label"><?php _e('Draft Events', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($stats['cancelled_events']); ?></div>
<div class="metric-label"><?php _e('Cancelled Events', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($stats['total_attendees']); ?></div>
<div class="metric-label"><?php _e('Total Attendees', 'hvac-ce'); ?></div>
</div>
</div>
</div>
<?php
}
/**
* Render revenue statistics widget
*/
private function render_revenue_statistics() {
$revenue = $this->get_revenue_statistics();
?>
<div class="hvac-dashboard-widget">
<h3><?php _e('Revenue Statistics', 'hvac-ce'); ?></h3>
<div class="metrics-grid">
<div class="metric">
<div class="metric-value">$<?php echo number_format($revenue['total_revenue'], 2); ?></div>
<div class="metric-label"><?php _e('Total Revenue', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value">$<?php echo number_format($revenue['revenue_week'], 2); ?></div>
<div class="metric-label"><?php _e('Revenue This Week', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($revenue['total_purchases']); ?></div>
<div class="metric-label"><?php _e('Total Purchases', 'hvac-ce'); ?></div>
</div>
<div class="metric">
<div class="metric-value"><?php echo esc_html($revenue['purchases_week']); ?></div>
<div class="metric-label"><?php _e('Purchases This Week', 'hvac-ce'); ?></div>
</div>
</div>
</div>
<?php
}
/**
* Render maintenance controls
*/
private function render_maintenance_controls() {
?>
<div class="hvac-dashboard-widget maintenance-controls">
<h3><?php _e('Maintenance Controls', 'hvac-ce'); ?></h3>
<div class="maintenance-actions">
<button class="button" data-action="clear_transients">
<?php _e('Clear Cache', 'hvac-ce'); ?>
</button>
<button class="button" data-action="optimize_tables">
<?php _e('Optimize Database Tables', 'hvac-ce'); ?>
</button>
<button class="button" data-action="regenerate_roles">
<?php _e('Regenerate User Roles', 'hvac-ce'); ?>
</button>
<button class="button" data-action="sync_event_meta">
<?php _e('Sync Event Metadata', 'hvac-ce'); ?>
</button>
</div>
<div class="maintenance-log" style="display:none;">
<h4><?php _e('Maintenance Log', 'hvac-ce'); ?></h4>
<pre id="maintenance-output"></pre>
</div>
</div>
<?php
}
/**
* Get health status
*/
private function get_health_status() {
$checks = array();
$overall_status = 'healthy';
// Check plugin dependencies
$tec_active = class_exists('Tribe__Events__Main');
$checks[] = array(
'component' => '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);
}
}