User Badges
Badge system providing achievement recognition, user engagement incentives, and visual status indicators across the Extra Chill Platform.
Badge Categories
Achievement Badges
// Achievement-based badges
function ec_get_achievement_badges() {
return [
'first_post' => [
'name' => 'First Post',
'description' => 'Made your first community post',
'icon' => 'edit-3',
'color' => '#22c55e',
'type' => 'automatic',
'condition' => ['action' => 'post_created', 'count' => 1]
],
'pioneer' => [
'name' => 'Pioneer',
'description' => 'One of the first 100 members',
'icon' => 'compass',
'color' => '#f59e0b',
'type' => 'automatic',
'condition' => ['user_id_position' => '<= 100']
],
'veteran' => [
'name' => 'Veteran',
'description' => 'Member for over one year',
'icon' => 'calendar-check',
'color' => '#6366f1',
'type' => 'automatic',
'condition' => ['membership_duration' => '> 1 year']
],
'centurion' => [
'name' => 'Centurion',
'description' => 'Created 100+ posts',
'icon' => 'pen-tool',
'color' => '#8b5cf6',
'type' => 'automatic',
'condition' => ['action' => 'post_created', 'count' => 100]
]
];
}
Engagement Badges
// Engagement-based badges
function ec_get_engagement_badges() {
return [
'helpful' => [
'name' => 'Helpful',
'description' => 'Received 50 helpful votes',
'icon' => 'hand-heart',
'color' => '#10b981',
'type' => 'automatic',
'condition' => ['helpful_votes' => 50]
],
'conversationalist' => [
'name' => 'Conversationalist',
'description' => 'Made 200+ replies',
'icon' => 'message-circle',
'color' => '#3b82f6',
'type' => 'automatic',
'condition' => ['action' => 'reply_posted', 'count' => 200]
],
'social_butterfly' => [
'name' => 'Social Butterfly',
'description' => 'Connected with 25+ users',
'icon' => 'users',
'color' => '#ec4899',
'type' => 'automatic',
'condition' => ['connections' => 25]
]
];
}
Role-Based Badges
// Role and status badges
function ec_get_role_badges() {
return [
'moderator' => [
'name' => 'Moderator',
'description' => 'Community moderator',
'icon' => 'shield',
'color' => '#ef4444',
'type' => 'role_based',
'condition' => ['role' => 'moderator']
],
'artist' => [
'name' => 'Artist',
'description' => 'Verified artist on platform',
'icon' => 'music',
'color' => '#a855f7',
'type' => 'role_based',
'condition' => ['is_artist' => true]
],
'team_member' => [
'name' => 'Team Member',
'description' => 'Extra Chill team member',
'icon' => 'award',
'color' => '#0891b2',
'type' => 'role_based',
'condition' => ['is_team_member' => true]
]
];
}
Badge Awarding System
Automatic Badge Detection
// Check and award badges for user
function ec_check_and_award_badges($user_id) {
$all_badges = array_merge(
ec_get_achievement_badges(),
ec_get_engagement_badges(),
ec_get_role_badges()
);
$user_badges = ec_get_user_badges($user_id);
foreach ($all_badges as $badge_key => $badge_data) {
// Skip if already awarded
if (in_array($badge_key, $user_badges)) {
continue;
}
// Check if condition is met
if (ec_badge_condition_met($user_id, $badge_data['condition'])) {
ec_award_badge_to_user($user_id, $badge_key, $badge_data);
}
}
}
Condition Evaluation
// Evaluate badge condition
function ec_badge_condition_met($user_id, $condition) {
switch (key($condition)) {
case 'action':
return ec_check_action_count($user_id, $condition['action'], $condition['count'] ?? 1);
case 'helpful_votes':
return ec_check_helpful_votes($user_id, $condition['helpful_votes']);
case 'membership_duration':
return ec_check_membership_duration($user_id, $condition['membership_duration']);
case 'role':
return ec_check_user_role($user_id, $condition['role']);
case 'is_artist':
return ec_check_artist_status($user_id);
case 'is_team_member':
return ec_is_team_member($user_id);
default:
return false;
}
}
Action Count Checking
// Check if user has performed action specified times
function ec_check_action_count($user_id, $action, $required_count) {
global $wpdb;
$table_name = $wpdb->prefix . 'ec_points_log';
$count = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$table_name}
WHERE user_id = %d AND action = %s",
$user_id, $action
));
return $count >= $required_count;
}
Badge Awarding Process
// Award badge to user
function ec_award_badge_to_user($user_id, $badge_key, $badge_data) {
// Get current badges
$user_badges = ec_get_user_badges($user_id);
// Add new badge
$user_badges[] = $badge_key;
update_user_meta($user_id, 'rank_badges', array_unique($user_badges));
// Log badge award
ec_log_badge_award($user_id, $badge_key, $badge_data);
// Award points for badge
ec_award_points($user_id, 'badge_earned');
// Send notification
ec_send_badge_notification($user_id, $badge_data);
// Trigger action for integrations
do_action('ec_badge_awarded', $user_id, $badge_key, $badge_data);
return true;
}
Badge Display System
Badge Rendering
// Render user badges with HTML
function ec_render_user_badges($user_id, $size = 'medium', $show_tooltips = true) {
$user_badges = ec_get_user_badges($user_id);
$all_badges = ec_get_all_available_badges();
if (empty($user_badges)) {
return '';
}
$output = '<div class="user-badges ' . esc_attr($size) . '">';
foreach ($user_badges as $badge_key) {
if (isset($all_badges[$badge_key])) {
$badge = $all_badges[$badge_key];
$tooltip_attr = $show_tooltips ? ' title="' . esc_attr($badge['description']) . '"' : '';
$output .= '<span class="badge badge-' . esc_attr($badge_key) . '"' . $tooltip_attr . '>';
$output .= '<span class="badge-icon" style="color: ' . esc_attr($badge['color']) . '">';
$output .= ec_get_icon_svg($badge['icon']);
$output .= '</span>';
if ($size === 'large') {
$output .= '<span class="badge-name">' . esc_html($badge['name']) . '</span>';
}
$output .= '</span>';
}
}
$output .= '</div>';
return $output;
}
Badge Collection Page
// Display all badges with earned status
function ec_render_badge_collection($user_id = null) {
if (!$user_id) {
$user_id = get_current_user_id();
}
$user_badges = ec_get_user_badges($user_id);
$all_badges = ec_get_all_available_badges();
$output = '<div class="badge-collection">';
$output .= '<h2>Badge Collection</h2>';
// Group badges by category
$categories = [
'achievement' => 'Achievements',
'engagement' => 'Engagement',
'role' => 'Roles & Status'
];
foreach ($categories as $category => $title) {
$output .= '<h3>' . esc_html($title) . '</h3>';
$output .= '<div class="badge-category">';
foreach ($all_badges as $badge_key => $badge) {
if ($badge['type'] === $category || ($category === 'role' && $badge['type'] === 'role_based')) {
$is_earned = in_array($badge_key, $user_badges);
$earned_class = $is_earned ? 'earned' : 'locked';
$output .= '<div class="badge-item ' . $earned_class . '">';
$output .= '<span class="badge-icon" style="color: ' . esc_attr($badge['color']) . '">';
$output .= ec_get_icon_svg($badge['icon']);
$output .= '</span>';
$output .= '<span class="badge-info">';
$output .= '<span class="badge-name">' . esc_html($badge['name']) . '</span>';
$output .= '<span class="badge-description">' . esc_html($badge['description']) . '</span>';
$output .= '</span>';
$output .= '</div>';
}
}
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
Manual Badge Management
Admin Badge Interface
// Admin interface for manual badge awarding
function ec_admin_badge_management_interface() {
add_users_page(
'Badge Management',
'Badges',
'manage_options',
'badge-management',
'ec_render_badge_management_page'
);
}
Manual Badge Awarding
// Award badge manually (admin function)
function ec_manual_award_badge($user_id, $badge_key, $reason = '') {
$all_badges = ec_get_all_available_badges();
if (!isset($all_badges[$badge_key])) {
return new WP_Error('invalid_badge', 'Badge does not exist');
}
$user_badges = ec_get_user_badges($user_id);
if (in_array($badge_key, $user_badges)) {
return new WP_Error('already_awarded', 'User already has this badge');
}
// Award the badge
$success = ec_award_badge_to_user($user_id, $badge_key, $all_badges[$badge_key]);
if ($success) {
// Log manual award
ec_log_manual_badge_award($user_id, $badge_key, $reason);
return true;
}
return false;
}
Badge Analytics
Badge Statistics
// Get badge awarding statistics
function ec_get_badge_statistics($days = 30) {
global $wpdb;
$table_name = $wpdb->prefix . 'ec_badges_log';
$date_limit = date('Y-m-d H:i:s', strtotime("-{$days} days"));
return [
'total_badges_awarded' => $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$table_name} WHERE awarded_at > %s",
$date_limit
)),
'unique_users_awarded' => $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(DISTINCT user_id) FROM {$table_name} WHERE awarded_at > %s",
$date_limit
)),
'most_popular_badge' => ec_get_most_popular_badge($date_limit),
'badge_award_rate' => ec_get_badge_award_rate($date_limit)
];
}
User Badge Progress
// Get user's progress toward next badges
function ec_get_user_badge_progress($user_id) {
$all_badges = ec_get_all_available_badges();
$user_badges = ec_get_user_badges($user_id);
$progress = [];
foreach ($all_badges as $badge_key => $badge) {
if (in_array($badge_key, $user_badges)) {
continue; // Already earned
}
if ($badge['type'] === 'automatic') {
$progress[$badge_key] = [
'badge' => $badge,
'progress' => ec_calculate_badge_progress($user_id, $badge_key, $badge)
];
}
}
return $progress;
}
Integration Points
Community Integration
// Check badges after community actions
function ec_community_badge_integration($action, $user_id, $context) {
// Immediately check for new badges
ec_check_and_award_badges($user_id);
// Schedule background check for complex badges
wp_schedule_single_event(time() + 60, 'ec_check_complex_badges', [$user_id]);
}
Artist Platform Integration
// Artist-specific badge logic
function ec_artist_badge_integration($artist_id, $action) {
$user_id = get_post_meta($artist_id, 'user_id', true);
if ($user_id) {
switch ($action) {
case 'profile_approved':
ec_manual_award_badge($user_id, 'artist', 'Artist profile approved');
break;
case 'show_scheduled':
ec_check_and_award_badges($user_id); // Check for performance badges
break;
}
}
}
Security and Validation
Badge Validation
// Validate badge awarding request
function ec_validate_badge_award($user_id, $badge_key, $context = []) {
// Check user exists
if (!get_userdata($user_id)) {
return new WP_Error('invalid_user', 'User does not exist');
}
// Check badge exists
$all_badges = ec_get_all_available_badges();
if (!isset($all_badges[$badge_key])) {
return new WP_Error('invalid_badge', 'Badge does not exist');
}
// Check for duplicates
$user_badges = ec_get_user_badges($user_id);
if (in_array($badge_key, $user_badges)) {
return new WP_Error('duplicate_badge', 'User already has this badge');
}
// Validate manual award permissions
if ($context['manual'] && !current_user_can('manage_options')) {
return new WP_Error('permission_denied', 'Cannot manually award badges');
}
return true;
}
Anti-Exploitation
- Rate limiting for badge checks
- Validation of manual awards
- Audit logging for all badge changes
- Protection against badge farming
Performance Optimization
Efficient Badge Checking
// Cache user badge checks
function ec_cached_badge_check($user_id, $badge_key) {
$cache_key = "ec_badge_check_{$user_id}_{$badge_key}";
$cached_result = wp_cache_get($cache_key, 'ec_badges');
if ($cached_result !== false) {
return $cached_result;
}
$result = ec_badge_condition_met($user_id, $badge_key);
wp_cache_set($cache_key, $result, 'ec_badges', 300); // 5 minutes
return $result;
}
Batch Processing
// Schedule batch badge checking
function ec_schedule_batch_badge_check($user_ids) {
// Process in batches of 10 users
$batches = array_chunk($user_ids, 10);
foreach ($batches as $batch) {
wp_schedule_single_event(time() + 30, 'ec_check_batch_badges', [$batch]);
}
}
API Integration
Badge API Endpoints
// Register badge API endpoints
function ec_register_badge_api_endpoints() {
register_rest_route('extrachill/v1', '/users/(?P<user_id>d+)/badges', [
'methods' => 'GET',
'callback' => 'ec_api_get_user_badges',
'permission_callback' => function() {
return is_user_logged_in();
}
]);
register_rest_route('extrachill/v1', '/badges', [
'methods' => 'GET',
'callback' => 'ec_api_get_all_badges',
'permission_callback' => '__return_true'
]);
register_rest_route('extrachill/v1', '/users/(?P<user_id>d+)/badges/award', [
'methods' => 'POST',
'callback' => 'ec_api_award_badge',
'permission_callback' => function() {
return current_user_can('manage_options');
}
]);
}
Badge Progress API
// Get user's badge progress
function ec_api_get_badge_progress($request) {
$user_id = $request->get_param('user_id');
return [
'earned_badges' => ec_get_user_badges($user_id),
'progress' => ec_get_user_badge_progress($user_id),
'total_available' => count(ec_get_all_available_badges()),
'completion_percentage' => ec_get_badge_completion_percentage($user_id)
];
}