Online Users

Real-time user tracking system providing online status, activity monitoring, and user presence features across the Extra Chill Platform.

User Activity Tracking

Activity Recording

// Record user activity
function extrachill_track_user_activity($user_id) {
    $current_time = current_time('mysql');
    
    // Update last activity timestamp
    update_user_meta($user_id, 'last_activity', $current_time);
    
    // Update session data
    $_SESSION['last_seen'] = $current_time;
    $_SESSION['user_id'] = $user_id;
    
    // Track page view if available
    if (function_exists('extrachill_track_page_view')) {
        extrachill_track_page_view($user_id, $_SERVER['REQUEST_URI']);
    }
}

Automatic Activity Detection

// Hook into WordPress actions to track activity
function extrachill_setup_activity_tracking() {
    // Track various user actions
    add_action('wp_login', function($user_login, $user) {
        extrachill_track_user_activity($user->ID);
    }, 10, 2);
    
    add_action('comment_post', function($comment_id, $comment_approved) {
        if ($comment_approved === 1) {
            $comment = get_comment($comment_id);
            extrachill_track_user_activity($comment->user_id);
        }
    }, 10, 2);
    
    add_action('bbp_new_topic', function($topic_id, $forum_id, $anonymous_data, $topic_author) {
        extrachill_track_user_activity($topic_author);
    }, 10, 4);
    
    add_action('bbp_new_reply', function($reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author) {
        extrachill_track_user_activity($reply_author);
    }, 10, 5);
}

Online Status Detection

Online Status Calculation

// Check if user is currently online
function extrachill_is_user_online($user_id, $threshold_minutes = 5) {
    $last_activity = get_user_meta($user_id, 'last_activity', true);
    
    if (!$last_activity) {
        return false;
    }
    
    $last_activity_time = strtotime($last_activity);
    $threshold_time = time() - ($threshold_minutes * 60);
    
    return $last_activity_time > $threshold_time;
}

Online Users Query

// Get currently online users
function extrachill_get_online_users($limit = 20, $exclude_admins = false) {
    global $wpdb;
    
    $threshold_time = date('Y-m-d H:i:s', time() - (5 * 60)); // 5 minutes ago
    
    $query = $wpdb->prepare(
        "SELECT u.ID, u.display_name, u.user_nicename, um.meta_value as last_activity
         FROM {$wpdb->users} u
         JOIN {$wpdb->usermeta} um ON u.ID = um.user_id
         WHERE um.meta_key = 'last_activity' 
         AND um.meta_value > %s
         AND u.user_status = 0",
        $threshold_time
    );
    
    if ($exclude_admins) {
        $query .= " AND u.ID NOT IN (
            SELECT user_id FROM {$wpdb->usermeta} 
            WHERE meta_key = '{$wpdb->prefix}capabilities' 
            AND meta_value LIKE '%administrator%'
        )";
    }
    
    $query .= " ORDER BY um.meta_value DESC LIMIT %d";
    $query = $wpdb->prepare($query, $limit);
    
    return $wpdb->get_results($query);
}

Online Statistics

Real-time Stats

// Get online user statistics
function extrachill_get_online_stats() {
    global $wpdb;
    
    $thresholds = [
        'now' => 1,          // 1 minute
        'recent' => 5,       // 5 minutes
        'hour' => 60,        // 1 hour
        'day' => 24 * 60     // 24 hours
    ];
    
    $stats = [];
    
    foreach ($thresholds as $key => $minutes) {
        $threshold_time = date('Y-m-d H:i:s', time() - ($minutes * 60));
        
        $count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT um.user_id)
             FROM {$wpdb->usermeta} um
             WHERE um.meta_key = 'last_activity'
             AND um.meta_value > %s",
            $threshold_time
        ));
        
        $stats[$key] = (int) $count;
    }
    
    return $stats;
}

User Activity Summary

// Get detailed activity summary
function extrachill_get_activity_summary($days = 7) {
    global $wpdb;
    
    $date_limit = date('Y-m-d H:i:s', strtotime("-{$days} days"));
    
    return [
        'unique_active_users' => $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT user_id) 
             FROM {$wpdb->prefix}ec_activity_log 
             WHERE created_at > %s",
            $date_limit
        )),
        'total_activities' => $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) 
             FROM {$wpdb->prefix}ec_activity_log 
             WHERE created_at > %s",
            $date_limit
        )),
        'peak_activity_hour' => extrachill_get_peak_activity_hour($days),
        'most_active_users' => extrachill_get_most_active_users($days, 5)
    ];
}

Online User Display

Online Users Widget

// Render online users widget
function extrachill_render_online_users_widget($title = 'Online Now', $limit = 10) {
    $online_users = extrachill_get_online_users($limit);
    
    if (empty($online_users)) {
        return '';
    }
    
    $output = '<div class="online-users-widget">';
    $output .= '<h3>' . esc_html($title) . '</h3>';
    
    $output .= '<div class="online-users-list">';
    
    foreach ($online_users as $user) {
        $profile_url = ec_get_user_profile_url($user->ID);
        $avatar = get_avatar($user->ID, 32);
        $is_online = extrachill_is_user_online($user->ID);
        
        $output .= '<div class="online-user">';
        $output .= '<a href="' . esc_url($profile_url) . '" class="user-link">';
        $output .= '<span class="user-avatar">' . $avatar . '</span>';
        $output .= '<span class="user-info">';
        $output .= '<span class="user-name">' . esc_html($user->display_name) . '</span>';
        $output .= '<span class="online-indicator ' . ($is_online ? 'online' : 'away') . '"></span>';
        $output .= '</span>';
        $output .= '</a>';
        $output .= '</div>';
    }
    
    $output .= '</div>';
    $output .= '</div>';
    
    return $output;
}

Online Status Indicators

// Display online status for a user
function extrachill_display_user_status($user_id, $size = 'small') {
    $is_online = extrachill_is_user_online($user_id);
    $last_activity = get_user_meta($user_id, 'last_activity', true);
    
    $status_class = $is_online ? 'online' : 'offline';
    $status_text = $is_online ? 'Online' : extrachill_get_last_seen_text($last_activity);
    
    $output = '<div class="user-status ' . esc_attr($size) . '">';
    $output .= '<span class="status-indicator ' . esc_attr($status_class) . '"></span>';
    
    if ($size === 'large') {
        $output .= '<span class="status-text">' . esc_html($status_text) . '</span>';
    } else {
        $output .= '<span class="status-text sr-only">' . esc_html($status_text) . '</span>';
    }
    
    $output .= '</div>';
    
    return $output;
}

Activity Logging

Activity Log Recording

// Log user activity to database
function extrachill_log_activity($user_id, $action, $context = []) {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'ec_activity_log';
    
    $log_data = [
        'user_id' => $user_id,
        'action' => $action,
        'context' => json_encode($context),
        'ip_address' => $_SERVER['REMOTE_ADDR'],
        'user_agent' => $_SERVER['HTTP_USER_AGENT'],
        'created_at' => current_time('mysql')
    ];
    
    $wpdb->insert($table_name, $log_data);
    
    // Update user's last activity
    extrachill_track_user_activity($user_id);
}

Activity Types

// Define activity types for tracking
function extrachill_get_activity_types() {
    return [
        'login' => 'User Login',
        'logout' => 'User Logout',
        'post_created' => 'Created Post',
        'comment_posted' => 'Posted Comment',
        'topic_created' => 'Created Forum Topic',
        'reply_posted' => 'Posted Forum Reply',
        'profile_updated' => 'Updated Profile',
        'avatar_uploaded' => 'Uploaded Avatar',
        'badge_earned' => 'Earned Badge',
        'page_view' => 'Viewed Page',
        'search_performed' => 'Performed Search'
    ];
}

Cleanup and Maintenance

Activity Cleanup

// Clean up old activity data
function extrachill_cleanup_activity_data() {
    global $wpdb;
    
    $tables = [
        $wpdb->prefix . 'ec_activity_log' => 30, // Keep 30 days
    ];
    
    foreach ($tables as $table => $days) {
        $cutoff_date = date('Y-m-d H:i:s', strtotime("-{$days} days"));
        
        $wpdb->query($wpdb->prepare(
            "DELETE FROM {$table} WHERE created_at < %s",
            $cutoff_date
        ));
    }
    
    // Clean up stale online status
    $stale_time = date('Y-m-d H:i:s', strtotime('-1 hour'));
    $wpdb->query($wpdb->prepare(
        "DELETE FROM {$wpdb->usermeta} 
         WHERE meta_key = 'last_activity' 
         AND meta_value < %s",
        $stale_time
    ));
}

Scheduled Maintenance

// Schedule cleanup tasks
function extrachill_schedule_maintenance() {
    if (!wp_next_scheduled('extrachill_cleanup_activity_data')) {
        wp_schedule_event(time(), 'daily', 'extrachill_cleanup_activity_data');
    }
}

Integration Points

Community Integration

// Community online features
function extrachill_community_online_integration() {
    // Show online status in forum posts
    add_filter('bbp_get_author_link', function($author_link, $post_id) {
        $user_id = get_post_field('post_author', $post_id);
        $status = extrachill_display_user_status($user_id, 'small');
        
        return $author_link . ' ' . $status;
    }, 10, 2);
    
    // Add online users to community sidebar
    add_action('bbp_theme_before_sidebar', function() {
        echo extrachill_render_online_users_widget('Community Members Online', 15);
    });
}

Chat Integration

// Chat online presence
function extrachill_chat_online_integration($user_id) {
    // Update chat presence
    if (function_exists('extrachill_chat_update_presence')) {
        extrachill_chat_update_presence($user_id, extrachill_is_user_online($user_id));
    }
    
    // Notify about user coming online/going offline
    $previous_status = get_user_meta($user_id, 'previous_online_status', true);
    $current_status = extrachill_is_user_online($user_id);
    
    if ($previous_status !== $current_status) {
        do_action('extrachill_user_status_changed', $user_id, $previous_status, $current_status);
        update_user_meta($user_id, 'previous_online_status', $current_status);
    }
}

Performance Optimization

Efficient Queries

// Optimize online users query with caching
function extrachill_cached_get_online_users($limit = 20) {
    $cache_key = "online_users_{$limit}";
    $cached = wp_cache_get($cache_key, 'extrachill_online');
    
    if ($cached !== false) {
        return $cached;
    }
    
    $users = extrachill_get_online_users($limit);
    wp_cache_set($cache_key, $users, 'extrachill_online', 60); // 1 minute cache
    
    return $users;
}

Database Indexing

// Create database indexes for performance
function extrachill_setup_database_indexes() {
    global $wpdb;
    
    $wpdb->query(
        "CREATE INDEX IF NOT EXISTS idx_last_activity 
         ON {$wpdb->usermeta} (meta_key, meta_value)"
    );
    
    $wpdb->query(
        "CREATE INDEX IF NOT EXISTS idx_activity_created_at 
         ON {$wpdb->prefix}ec_activity_log (created_at)"
    );
    
    $wpdb->query(
        "CREATE INDEX IF NOT EXISTS idx_activity_user_created 
         ON {$wpdb->prefix}ec_activity_log (user_id, created_at)"
    );
}

API Integration

Online Status API

// Register online status API endpoints
function extrachill_register_online_api_endpoints() {
    register_rest_route('extrachill/v1', '/users/online', [
        'methods' => 'GET',
        'callback' => 'extrachill_api_get_online_users',
        'permission_callback' => '__return_true'
    ]);
    
    register_rest_route('extrachill/v1', '/users/(?P<user_id>d+)/status', [
        'methods' => 'GET',
        'callback' => 'extrachill_api_get_user_status',
        'permission_callback' => function() {
            return is_user_logged_in();
        }
    ]);
    
    register_rest_route('extrachill/v1', '/stats/online', [
        'methods' => 'GET',
        'callback' => 'extrachill_api_get_online_stats',
        'permission_callback' => '__return_true'
    ]);
}

Real-time Updates

// WebSocket-like updates for real-time status
function extrachill_realtime_status_update($user_id, $action) {
    if (function_exists('extrachill_push_notification')) {
        $payload = [
            'type' => 'user_status',
            'user_id' => $user_id,
            'action' => $action,
            'timestamp' => time()
        ];
        
        extrachill_push_notification('user_activity', $payload);
    }
}

Security and Privacy

Privacy Controls

// Respect user privacy settings
function extrachill_should_show_online_status($user_id) {
    $privacy_setting = get_user_meta($user_id, 'show_online_status', true);
    
    // Default to showing status
    if ($privacy_setting === '') {
        return true;
    }
    
    return (bool) $privacy_setting;
}

Activity Filtering

// Filter sensitive activities from logs
function extrachill_filter_sensitive_activities($activity) {
    $sensitive_actions = [
        'password_reset',
        'email_change',
        'admin_login',
        'security_event'
    ];
    
    return !in_array($activity['action'], $sensitive_actions);
}

Analytics and Reporting

Activity Reports

// Generate activity report
function extrachill_generate_activity_report($start_date, $end_date) {
    global $wpdb;
    
    return $wpdb->get_results($wpdb->prepare(
        "SELECT 
            DATE(created_at) as date,
            COUNT(DISTINCT user_id) as unique_users,
            COUNT(*) as total_activities,
            action,
            COUNT(*) as action_count
         FROM {$wpdb->prefix}ec_activity_log
         WHERE created_at BETWEEN %s AND %s
         GROUP BY DATE(created_at), action
         ORDER BY date DESC, action_count DESC",
        $start_date, $end_date
    ));
}