// ========================================================================= // 26 SHORTCODE: Team Penalty Shots /penalty-shots/ // ========================================================================= add_shortcode('otg_penalty_shot_games', 'otg_penalty_shot_games_shortcode'); function otg_penalty_shot_games_shortcode() { global $wpdb; // Determine current page from URL parameter, default to 1 $paged = isset($_GET['ps_page']) ? max(1, intval($_GET['ps_page'])) : 1; $per_page = 25; $offset = ($paged - 1) * $per_page; // Get filter inputs from URL $selected_season = isset($_GET['ps_season']) ? sanitize_text_field($_GET['ps_season']) : ''; $selected_opp = isset($_GET['ps_opp']) ? sanitize_text_field($_GET['ps_opp']) : ''; $selected_outcome = isset($_GET['ps_outcome']) ? sanitize_text_field($_GET['ps_outcome']) : ''; $selected_shooter = isset($_GET['ps_shooter']) ? sanitize_text_field($_GET['ps_shooter']) : ''; $selected_type = isset($_GET['ps_type']) ? sanitize_text_field($_GET['ps_type']) : ''; // Base subquery defining the complete dataset with calculated fields and game type logic $subquery = " SELECT combined.*, CASE WHEN SUBSTRING(CAST(combined.game_id AS CHAR), 6, 1) = '2' THEN 'Regular Season' WHEN SUBSTRING(CAST(combined.game_id AS CHAR), 6, 1) = '3' THEN 'Playoffs' ELSE 'Unknown' END AS game_type_str, CONCAT( LEFT(combined.game_id, 4), '-', RIGHT(CAST(CAST(LEFT(combined.game_id, 4) AS UNSIGNED) + 1 AS CHAR), 2) ) AS season_str FROM ( SELECT 'Goal' AS ps_outcome, s.game_id, s.period, s.time_elapsed, s.scorer_name AS shooter_name, p.ID AS player_id, g.game_date, g.opponent_abbr, g.rangers_score, g.opponent_score, g.game_outcome, g.overtime_status, '' AS penalty_type FROM otg_rangers_scoring s LEFT JOIN otg_rangers_player_boxscores b ON s.game_id = b.game_id AND s.scorer_name = b.player_name LEFT JOIN otg_players p ON b.player_id = p.nhl_id LEFT JOIN otg_rangers_games g ON s.game_id = g.game_id WHERE LOWER(s.strength) IN ('ps', 'p2', 'sp') AND s.team_abbr = 'NYR' UNION ALL SELECT 'Miss' AS ps_outcome, pen.game_id, pen.period, pen.time_elapsed, '' AS shooter_name, NULL AS player_id, g.game_date, g.opponent_abbr, g.rangers_score, g.opponent_score, g.game_outcome, g.overtime_status, pen.penalty_type FROM otg_rangers_penalties pen LEFT JOIN otg_rangers_games g ON pen.game_id = g.game_id WHERE pen.penalty_type LIKE 'ps-%' AND pen.team_abbr != 'NYR' AND NOT EXISTS ( SELECT 1 FROM otg_rangers_scoring s2 WHERE s2.game_id = pen.game_id AND s2.period = pen.period AND s2.time_elapsed = pen.time_elapsed AND LOWER(s2.strength) IN ('ps', 'p2', 'sp') AND s2.team_abbr = 'NYR' ) ) combined "; // Fetch master dataset to dynamically populate filter dropdown options and reliably parse shooter names $master_rows = $wpdb->get_results("SELECT * FROM ({$subquery}) master_data ORDER BY game_date DESC, game_id DESC"); $available_seasons = []; $available_opponents = []; // Will store abbreviation => full team name map $available_shooters = []; $processed_master = []; foreach ($master_rows as $row) { // Resolve shooter name accurately for both goals and misses $current_shooter = $row->shooter_name; if ($row->ps_outcome !== 'Goal' && !empty($row->penalty_type) && strpos($row->penalty_type, 'ps-') === 0) { $trimmed = substr($row->penalty_type, 3); // Remove 'ps-' $parts = explode('-', $trimmed); if (!empty($parts[0])) { $current_shooter = trim($parts[0]); } } $row->resolved_shooter = $current_shooter; $processed_master[] = $row; if (!empty($row->season_str)) { $available_seasons[$row->season_str] = true; } if (!empty($row->opponent_abbr)) { $abbr = $row->opponent_abbr; if (!isset($available_opponents[$abbr])) { $team_name_row = $wpdb->get_row($wpdb->prepare( "SELECT team FROM otg_standings_nhl WHERE abbreviation = %s AND team != '' AND team IS NOT NULL LIMIT 1", $abbr )); $available_opponents[$abbr] = ($team_name_row && !empty($team_name_row->team)) ? $team_name_row->team : $abbr; } } if (!empty($current_shooter)) { $available_shooters[$current_shooter] = true; } } krsort($available_seasons); // Sort seasons descending (newest first) asort($available_opponents); // Sort opponents alphabetically by team name ksort($available_shooters); // Build dynamic SQL WHERE clause based on active filters $filter_clauses = []; $filter_params = []; if (!empty($selected_season)) { $filter_clauses[] = "season_str = %s"; $filter_params[] = $selected_season; } if (!empty($selected_opp)) { $filter_clauses[] = "opponent_abbr = %s"; $filter_params[] = $selected_opp; } if (!empty($selected_outcome)) { $filter_clauses[] = "ps_outcome = %s"; $filter_params[] = $selected_outcome; } if (!empty($selected_shooter)) { // Filter by resolved shooter name computed across rows $filter_clauses[] = "( (ps_outcome = 'Goal' AND shooter_name = %s) OR (ps_outcome != 'Goal' AND penalty_type LIKE %s) )"; $filter_params[] = $selected_shooter; $filter_params[] = 'ps-' . $selected_shooter . '-%'; } if (!empty($selected_type)) { $filter_clauses[] = "game_type_str = %s"; $filter_params[] = $selected_type; } $where_sql = ""; if (!empty($filter_clauses)) { $where_sql = "WHERE " . implode(" AND ", $filter_clauses); } // Fully wrapped subquery for count and pagination $filtered_from_where = "FROM ({$subquery}) filtered_sub {$where_sql}"; $total_rows = intval($wpdb->get_var($wpdb->prepare("SELECT COUNT(*) " . $filtered_from_where, $filter_params))); // Calculate total successful (Goals) based on the exact same active filter criteria $success_query = "SELECT COUNT(*) FROM ({$subquery}) filtered_sub {$where_sql}" . (empty($where_sql) ? " WHERE" : " AND") . " ps_outcome = 'Goal'"; $total_success = intval($wpdb->get_var($wpdb->prepare($success_query, $filter_params))); $total_pages = max(1, ceil($total_rows / $per_page)); // Ensure current page does not exceed total pages if filters narrow results if ($paged > $total_pages) { $paged = $total_pages; $offset = ($paged - 1) * $per_page; } // Fetch final paginated results $final_query = " SELECT * " . $filtered_from_where . " ORDER BY game_date DESC, game_id DESC, period ASC, time_elapsed ASC LIMIT %d OFFSET %d "; $query_params = array_merge($filter_params, [$per_page, $offset]); $penalty_shots = $wpdb->get_results($wpdb->prepare($final_query, $query_params)); // Start output wrapper $output = '
'; // Header Section $output .= '
'; $output .= '
New York Rangers Penalty Shots
'; // Summary Count Pill Display $success_rate = ($total_rows > 0) ? round(($total_success / $total_rows) * 100, 1) : 0; $output .= '
'; $output .= 'Total Attempts: ' . $total_rows . '  |  Successful: ' . $total_success . ' (' . $success_rate . '%)'; $output .= '
'; $output .= '
'; // Filters Section UI $current_page_url = strtok($_SERVER["URI"] ?? $_SERVER["REQUEST_URI"], '?'); $output .= '
'; // Preserve other potential query args if needed foreach ($_GET as $key => $val) { if (!in_array($key, ['ps_season', 'ps_opp', 'ps_outcome', 'ps_shooter', 'ps_type', 'ps_page'])) { $output .= ''; } } // Season Filter $output .= '
'; $output .= ''; $output .= '
'; // Game Type Filter (Regular Season vs Playoffs) $output .= '
'; $output .= ''; $output .= '
'; // Opponent Filter $output .= '
'; $output .= ''; $output .= '
'; // Goal vs Miss Filter $output .= '
'; $output .= ''; $output .= '
'; // Shooter Filter $output .= '
'; $output .= ''; $output .= '
'; // Apply & Permanent Clear Button (Always rendered right after Apply) $output .= '
'; $output .= ''; $output .= 'Clear'; $output .= '
'; $output .= '
'; // Styles matching modern uniform layout + pagination styling + button hover specifications $output .= ''; $output .= ''; if (!$penalty_shots) { $output .= ''; } else { foreach ($penalty_shots as $ps) { // Format game_date to Month Day, Year (e.g., October 12, 2023) $formatted_date = !empty($ps->game_date) ? date('F j, Y', strtotime($ps->game_date)) : ''; // Handle period display name (leave blank if period is 0) if (intval($ps->period) === 0) { $period_name = ''; } else { $period_name = ($ps->period == 4) ? 'Overtime' : get_ordinal($ps->period) . ' Period'; } // Format Result string: [Outcome] [Score] [(OT/SO)] $outcome_label = ''; if (!empty($ps->game_outcome)) { $raw_outcome = strtoupper($ps->game_outcome); // Keep L as L (do not convert to OTL) if ($raw_outcome === 'OTL') { $outcome_label = 'L'; } else { $outcome_label = $raw_outcome; } } // Build score string (e.g., 2-3) $score_part = intval($ps->rangers_score) . '-' . intval($ps->opponent_score); // Format OT or SO inside parentheses if applicable $suffix_part = ''; if (!empty($ps->overtime_status)) { $ot_status_upper = strtoupper($ps->overtime_status); if ($ot_status_upper === 'OT' || $ot_status_upper === 'SO') { $suffix_part = ' (' . $ot_status_upper . ')'; } } $result_display = trim($outcome_label . ' ' . $score_part . $suffix_part); // Handle Shooter extraction & profile linking uniformly for both Goals and Misses $shooter_name = ''; $player_id = $ps->player_id; // Starts with whatever subquery joined (for goals) if ($ps->ps_outcome === 'Goal') { $shooter_name = $ps->shooter_name; $shot_result_display = 'Goal'; } else { // Parse shooter name properly from penalty_type for misses (e.g., ps-Vincent Trocheck-slashing) if (!empty($ps->penalty_type) && strpos($ps->penalty_type, 'ps-') === 0) { $trimmed = substr($ps->penalty_type, 3); // Remove 'ps-' $parts = explode('-', $trimmed); if (!empty($parts[0])) { $shooter_name = trim($parts[0]); } } $shot_result_display = 'Miss'; } // Universal fallback lookup: If player_id is missing, look up ID by Name in otg_players if (empty($player_id) && !empty($shooter_name)) { $matched_player = $wpdb->get_row($wpdb->prepare( "SELECT ID FROM otg_players WHERE Name = %s LIMIT 1", $shooter_name )); if ($matched_player) { $player_id = $matched_player->ID; } } // Format Shooter display with profile link if player ID exists if (!empty($player_id)) { $shooter_display = '' . esc_html($shooter_name) . ''; } else { $shooter_display = !empty($shooter_name) ? esc_html($shooter_name) : 'Unknown'; } // Leave time blank if period is 0 $time_display = (intval($ps->period) === 0) ? '' : esc_html($ps->time_elapsed); // Look up the opponent logo dynamically per row using exact abbreviation and formatted season (YYYY-YY) $opponent_logo = ''; if (!empty($ps->opponent_abbr) && !empty($ps->game_id)) { $logo_row = $wpdb->get_row($wpdb->prepare( "SELECT logo FROM otg_standings_nhl WHERE abbreviation = %s AND season = %s LIMIT 1", $ps->opponent_abbr, $ps->season_str )); if ($logo_row && !empty($logo_row->logo)) { $opponent_logo = $logo_row->logo; } } // Format Opposition display using logo if available, falling back to abbreviation text if (!empty($opponent_logo)) { $opponent_display = '' . esc_attr($ps->opponent_abbr) . ''; } else { $opponent_display = esc_html($ps->opponent_abbr); } $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; } } $output .= '
Date Type Opposition Result Period Time Shooter Shot Result Box Score
No New York Rangers penalty shot attempts found matching the selected filters.
' . esc_html($formatted_date) . '' . esc_html($ps->game_type_str) . '' . $opponent_display . '' . esc_html($result_display) . '' . esc_html($period_name) . '' . $time_display . '' . $shooter_display . '' . $shot_result_display . 'View Box Score
'; // Pagination Links Output (preserving active filters in query parameters) if ($total_pages > 1) { $output .= '
'; $current_url = remove_query_arg('ps_page'); // Previous Link if ($paged > 1) { $prev_url = add_query_arg('ps_page', $paged - 1, $current_url); $output .= '« Prev'; } // Page Number Links Logic $range = 2; for ($i = 1; $i <= $total_pages; $i++) { if ($i == 1 || $i == $total_pages || ($i >= $paged - $range && $i <= $paged + $range)) { if ($i == $paged) { $output .= '' . $i . ''; } else { $page_url = add_query_arg('ps_page', $i, $current_url); $output .= '' . $i . ''; } } elseif ($i == $paged - $range - 1 || $i == $paged + $range + 1) { $output .= ''; } } // Next Link if ($paged < $total_pages) { $next_url = add_query_arg('ps_page', $paged + 1, $current_url); $output .= 'Next »'; } $output .= '
'; } $output .= '
'; // Close main wrapper return $output; } Rangerjunkiekimmie – Activity – OutsideTheGarden Boards – Page 13
DECEMBER
«
Sun
21
Mon
22
Tue
23
Wed
24
Thu
25
Fri
26
Sat
27
»
Rangerjunkiekimmie
Rangerjunkiekimmie
Group: Registered
Joined: 2023-08-26
NHL All Star
2
Follow
JT having a game to forget

In forum Where Smit Hits The Fan

1 year ago
Get Kreider off the PP

In forum Where Smit Hits The Fan

1 year ago
Give you two guesses

In forum Where Smit Hits The Fan

1 year ago
Can't get more alone in front of the net than that...1-2

In forum Where Smit Hits The Fan

1 year ago
Another BS call against Rempe

In forum Where Smit Hits The Fan

1 year ago
Rangers not run out of the building after 1

In forum Where Smit Hits The Fan

1 year ago
Not at all.

In forum Where Smit Hits The Fan

1 year ago
Mika with his 15 goal 1-1

In forum Where Smit Hits The Fan

1 year ago
When Elon is done finding all the fraud and waste in governm...

In forum Where Smit Hits The Fan

1 year ago
And Housey still has a job.......

In forum Where Smit Hits The Fan

1 year ago
Hopefully the 12 million dollar man can keep us in it

In forum Where Smit Hits The Fan

1 year ago
HAHAHAHA

In forum Where Smit Hits The Fan

1 year ago
My Guess is the Rangers will be; Outmuscled Outworked ...

In forum Where Smit Hits The Fan

1 year ago
Don't think the Rangers will give up 7, but not sure the Ran...

In forum Where Smit Hits The Fan

1 year ago
I would give Mika, Kreider, Fox, K Miller, Lafrienere for Br...

In forum Where Smit Hits The Fan

1 year ago
Page 13 / 106