'', 'auto_update' => 'true', 'update_interval' => '5000', 'width' => '100%', 'height' => 'auto', 'show_controls' => 'false' ), $atts); if (empty($atts['event_id'])) { return '
Error: Event ID is required for the scoreboard.
'; } $event = get_post($atts['event_id']); if (!$event || $event->post_type !== 'sp_event') { return '
Error: Invalid event ID or not a SportsPress event.
'; } $this->enqueue_scoreboard_assets($atts); $container_id = 'scoreboard-' . $atts['event_id'] . '-' . uniqid(); return sprintf( '
', esc_attr($container_id), esc_attr($atts['event_id']), esc_attr($atts['show_controls']), esc_attr($atts['width']), esc_attr($atts['height']) ); } /** * Render live fixtures shortcode (all active matches) * Usage: [live_fixtures auto_update="true" update_interval="10000" max_fixtures="5"] */ public function render_live_fixtures($atts) { $atts = shortcode_atts(array( 'auto_update' => 'true', 'update_interval' => '10000', 'max_fixtures' => '10', 'width' => '100%', 'show_finished' => 'false' ), $atts); $this->enqueue_scoreboard_assets($atts); $container_id = 'live-fixtures-' . uniqid(); return sprintf( '
', esc_attr($container_id), esc_attr($atts['max_fixtures']), esc_attr($atts['show_finished']), esc_attr($atts['width']) ); } /** * Enqueue necessary scripts and styles */ private function enqueue_scoreboard_assets($atts) { wp_enqueue_script('jquery'); wp_enqueue_script( 'live-scoreboard-js', plugin_dir_url(__FILE__) . 'js/live-scoreboard.js', array('jquery'), '1.0.1', true ); wp_enqueue_style( 'live-scoreboard-css', plugin_dir_url(__FILE__) . 'css/live-scoreboard.css', array(), '1.0.1' ); // Localize script with AJAX data wp_localize_script('live-scoreboard-js', 'scoreboardConfig', array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('scoreboard_nonce'), 'eventId' => isset($atts['event_id']) ? $atts['event_id'] : '', 'autoUpdate' => $atts['auto_update'] === 'true', 'updateInterval' => intval($atts['update_interval']), 'maxFixtures' => isset($atts['max_fixtures']) ? intval($atts['max_fixtures']) : 10, 'showFinished' => isset($atts['show_finished']) ? ($atts['show_finished'] === 'true') : false, 'showControls' => isset($atts['show_controls']) ? ($atts['show_controls'] === 'true') : false, 'canEdit' => current_user_can('manage_scoreboard') )); } /** * AJAX handler to get live fixtures data */ public function ajax_get_live_fixtures() { $max_fixtures = isset($_POST['max_fixtures']) ? intval($_POST['max_fixtures']) : 10; $show_finished = isset($_POST['show_finished']) ? (bool)$_POST['show_finished'] : false; $fixtures_data = $this->get_live_fixtures_data($max_fixtures, $show_finished); if ($fixtures_data !== false) { wp_send_json_success($fixtures_data); } else { wp_send_json_error('Failed to retrieve fixtures data'); } } /** * AJAX handler to get single scoreboard data */ public function ajax_get_scoreboard_data() { $event_id = intval($_POST['event_id']); $last_update = isset($_POST['last_update']) ? intval($_POST['last_update']) : 0; if (!$event_id) { wp_send_json_error('Invalid event ID'); } $scoreboard_data = $this->get_scoreboard_data($event_id); if ($scoreboard_data) { wp_send_json_success($scoreboard_data); } else { wp_send_json_error('Failed to retrieve scoreboard data'); } } /** * Get live fixtures data */ private function get_live_fixtures_data($max_fixtures = 10, $show_finished = false) { // Query for SportsPress events $meta_query = array( array( 'key' => '_scoreboard_data', 'compare' => 'EXISTS' ) ); if (!$show_finished) { $meta_query[] = array( 'key' => '_game_state', 'value' => 'Finished', 'compare' => '!=' ); } $events = get_posts(array( 'post_type' => 'sp_event', 'posts_per_page' => $max_fixtures, 'meta_query' => $meta_query, 'orderby' => 'meta_value', 'meta_key' => '_scoreboard_last_update', 'order' => 'DESC' )); $fixtures = array(); foreach ($events as $event) { $scoreboard_data = $this->get_scoreboard_data($event->ID); if ($scoreboard_data && ($show_finished || $scoreboard_data['game_state'] !== 'Finished')) { $scoreboard_data['event_id'] = $event->ID; $scoreboard_data['event_title'] = $event->post_title; $fixtures[] = $scoreboard_data; } } return array( 'fixtures' => $fixtures, 'timestamp' => time(), 'total_count' => count($fixtures) ); } /** * Get scoreboard data from event metadata */ private function get_scoreboard_data($event_id) { $event = get_post($event_id); if (!$event) { return false; } // Get SportsPress event data $teams = get_post_meta($event_id, 'sp_team', false); $results = get_post_meta($event_id, 'sp_results', true); // Get custom scoreboard metadata $scoreboard_meta = get_post_meta($event_id, '_scoreboard_data', true); if (!is_array($scoreboard_meta)) { $scoreboard_meta = array(); } // Get game state and events $game_state = get_post_meta($event_id, '_game_state', true) ?: 'WaitingForStart'; $event_list = get_post_meta($event_id, '_match_events', true); if (!is_array($event_list)) { $event_list = array(); } // Default scoreboard data structure $default_data = array( 'game_on' => false, 'game_state' => $game_state, 'timer_value' => '00:00', 'half_indicator' => $this->get_half_indicator($game_state), 'home_team_points' => 0, 'away_team_points' => 0, 'event_list' => $event_list, 'timestamp' => time() ); // Merge with saved metadata $scoreboard_data = array_merge($default_data, $scoreboard_meta); // Calculate if game is on $scoreboard_data['game_on'] = in_array($game_state, array('FirstHalf', 'SecondHalf', 'TimeOff')); // Get team information from SportsPress if (!empty($teams)) { $home_team_id = isset($teams[0]) ? $teams[0] : null; $away_team_id = isset($teams[1]) ? $teams[1] : null; if ($home_team_id) { $scoreboard_data['home_team_name'] = get_the_title($home_team_id); $scoreboard_data['home_team_logo'] = $this->get_team_logo($home_team_id); $scoreboard_data['home_team_color'] = get_post_meta($home_team_id, '_team_color', true) ?: '#1e3c72'; } if ($away_team_id) { $scoreboard_data['away_team_name'] = get_the_title($away_team_id); $scoreboard_data['away_team_logo'] = $this->get_team_logo($away_team_id); $scoreboard_data['away_team_color'] = get_post_meta($away_team_id, '_team_color', true) ?: '#2a5298'; } } // Calculate points from events $scores = $this->calculate_scores_from_events($event_list); $scoreboard_data['home_team_points'] = $scores['home']; $scoreboard_data['away_team_points'] = $scores['away']; return $scoreboard_data; } /** * Calculate scores from match events */ private function calculate_scores_from_events($events) { $scores = array('home' => 0, 'away' => 0); foreach ($events as $event) { if (!isset($event['category']) || !isset($event['eventType'])) { continue; } $team = strtolower($event['category']); if (!in_array($team, array('home', 'away'))) { continue; } switch ($event['eventType']) { case 'Try': $scores[$team] += 5; break; case 'Conversion': $scores[$team] += 2; break; case 'Penalty': case 'DropGoal': $scores[$team] += 3; break; } } return $scores; } /** * Get half indicator text based on game state */ private function get_half_indicator($game_state) { switch ($game_state) { case 'WaitingForStart': return 'Pre-Match'; case 'FirstHalf': return '1st Half'; case 'HalfTime': return 'Half Time'; case 'SecondHalf': return '2nd Half'; case 'TimeOff': return 'Time Off'; case 'Finished': return 'Full Time'; default: return 'Pre-Match'; } } /** * AJAX handler to add team event (admin only) */ public function ajax_add_team_event() { if (!current_user_can('manage_scoreboard')) { wp_send_json_error('Insufficient permissions'); } if (!wp_verify_nonce($_POST['nonce'], 'scoreboard_nonce')) { wp_send_json_error('Security check failed'); } $event_id = intval($_POST['event_id']); $team = sanitize_text_field($_POST['team']); $event_type = sanitize_text_field($_POST['event_type']); if (!$event_id || !$team || !$event_type) { wp_send_json_error('Invalid data'); } $result = $this->add_team_event($event_id, $team, $event_type); if ($result) { wp_send_json_success('Event added successfully'); } else { wp_send_json_error('Failed to add event'); } } /** * Add team event to match */ private function add_team_event($event_id, $team, $event_type) { $events = get_post_meta($event_id, '_match_events', true); if (!is_array($events)) { $events = array(); } $new_event = array( 'id' => uniqid(), 'category' => $team, 'eventType' => $event_type, 'timestamp' => time(), 'minute' => $this->get_current_match_minute($event_id) ); $events[] = $new_event; $result = update_post_meta($event_id, '_match_events', $events); // Update last modified timestamp update_post_meta($event_id, '_scoreboard_last_update', time()); return $result; } /** * Get current match minute (placeholder - you'd implement based on your timer logic) */ private function get_current_match_minute($event_id) { // This would calculate based on your match start time and current time // For now, return a placeholder return '00:00'; } /** * AJAX handler to delete event (admin only) */ public function ajax_delete_event() { if (!current_user_can('manage_scoreboard')) { wp_send_json_error('Insufficient permissions'); } if (!wp_verify_nonce($_POST['nonce'], 'scoreboard_nonce')) { wp_send_json_error('Security check failed'); } $event_id = intval($_POST['event_id']); $match_event_id = sanitize_text_field($_POST['match_event_id']); if (!$event_id || !$match_event_id) { wp_send_json_error('Invalid data'); } $result = $this->delete_match_event($event_id, $match_event_id); if ($result) { wp_send_json_success('Event deleted successfully'); } else { wp_send_json_error('Failed to delete event'); } } /** * Delete a specific match event */ private function delete_match_event($event_id, $match_event_id) { $events = get_post_meta($event_id, '_match_events', true); if (!is_array($events)) { return false; } $updated_events = array_filter($events, function($event) use ($match_event_id) { return $event['id'] !== $match_event_id; }); $result = update_post_meta($event_id, '_match_events', array_values($updated_events)); // Update last modified timestamp update_post_meta($event_id, '_scoreboard_last_update', time()); return $result; } /** * AJAX handler to update game state (admin only) */ public function ajax_update_game_state() { if (!current_user_can('manage_scoreboard')) { wp_send_json_error('Insufficient permissions'); } if (!wp_verify_nonce($_POST['nonce'], 'scoreboard_nonce')) { wp_send_json_error('Security check failed'); } $event_id = intval($_POST['event_id']); $new_state = sanitize_text_field($_POST['game_state']); if (!$event_id || !$new_state) { wp_send_json_error('Invalid data'); } $result = update_post_meta($event_id, '_game_state', $new_state); update_post_meta($event_id, '_scoreboard_last_update', time()); if ($result) { wp_send_json_success('Game state updated successfully'); } else { wp_send_json_error('Failed to update game state'); } } /** * Get team logo URL */ private function get_team_logo($team_id) { $logo_id = get_post_thumbnail_id($team_id); if ($logo_id) { $logo_url = wp_get_attachment_image_url($logo_id, 'thumbnail'); return $logo_url ?: 'https://via.placeholder.com/60x60/cccccc/ffffff?text=T'; } return 'https://via.placeholder.com/60x60/cccccc/ffffff?text=T'; } } // Initialize the shortcode new LiveScoreboardShortcode(); /** * Add scoreboard control meta box for events (admin only) */ add_action('add_meta_boxes', 'add_scoreboard_control_meta_box'); function add_scoreboard_control_meta_box() { if (current_user_can('manage_scoreboard')) { add_meta_box( 'scoreboard-controls', 'Live Scoreboard Controls', 'render_scoreboard_control_meta_box', 'sp_event', 'side', 'high' ); } } function render_scoreboard_control_meta_box($post) { $scoreboard_data = get_post_meta($post->ID, '_scoreboard_data', true); $game_state = get_post_meta($post->ID, '_game_state', true) ?: 'WaitingForStart'; if (!is_array($scoreboard_data)) { $scoreboard_data = array( 'timer_value' => '00:00' ); } wp_nonce_field('scoreboard_meta_box', 'scoreboard_meta_box_nonce'); ?>

post_type !== 'sp_event') { return; } if (!isset($_POST['scoreboard_meta_box_nonce']) || !wp_verify_nonce($_POST['scoreboard_meta_box_nonce'], 'scoreboard_meta_box')) { return; } if (!current_user_can('edit_post', $post_id)) { return; } $scoreboard_data = array( 'timer_value' => sanitize_text_field($_POST['timer_value']), 'timestamp' => time() ); $game_state = sanitize_text_field($_POST['game_state']); update_post_meta($post_id, '_scoreboard_data', $scoreboard_data); update_post_meta($post_id, '_game_state', $game_state); update_post_meta($post_id, '_scoreboard_last_update', time()); } function add_scoreboard_capability() { $editor = get_role('editor'); $editor->add_cap('manage_scoreboard'); $admin = get_role('administrator'); $admin->add_cap('manage_scoreboard'); } add_action('init', 'add_scoreboard_capability'); ?>