// ========================================================================= // 38. SHORTCODE: Player Contracts /contracts/ // ========================================================================= add_shortcode('otg_rangers_contracts', 'otg_render_rangers_contracts_shortcode'); function otg_get_waiver_status( $player_id, $season, $wpdb ) { // 1. Fetch player details $player = $wpdb->get_row( $wpdb->prepare( "SELECT ID, nhl_id, Birthday, Position FROM otg_players WHERE ID = %s OR ID = (SELECT player_id FROM otg_rangers_contracts WHERE contract_id = %s LIMIT 1)", $player_id, $player_id ) ); if ( ! $player || empty( $player->Birthday ) ) { return [ 'exempt' => true, 'label' => 'Exempt (Data Pending)' ]; } // 2. Fetch first contract date and check for slide reduction flag $contract = $wpdb->get_row( $wpdb->prepare( "SELECT first_contract_date, slide_contract FROM otg_rangers_contracts WHERE player_id = %s AND first_contract_date IS NOT NULL AND CAST(first_contract_date AS CHAR) != '' AND first_contract_date > '1000-01-01' ORDER BY first_contract_date ASC LIMIT 1", $player->ID ) ); if ( ! $contract || empty( $contract->first_contract_date ) ) { $fallback_year = $wpdb->get_var( $wpdb->prepare( "SELECT season FROM otg_rangers_contract_years WHERE player_id = %s ORDER BY season ASC LIMIT 1", $player->ID )); if ( !empty( $fallback_year ) ) { $base_contract_year = intval( explode( '-', $fallback_year )[0] ); $first_contract_date_approx = $base_contract_year . '-09-15'; $slide_contract_val = 0; } else { return [ 'exempt' => true, 'label' => 'Exempt (Data Pending)' ]; } } else { $first_contract_date_approx = $contract->first_contract_date; $slide_contract_val = isset( $contract->slide_contract ) ? intval( $contract->slide_contract ) : 0; } $signing_year = intval( date( 'Y', strtotime( $first_contract_date_approx ) ) ); // 3. Determine Waiver Age (Dec 31 of contract year + Sept 15 rule) $birth_date_obj = new DateTime( $player->Birthday ); $dec31_obj = new DateTime( $signing_year . '-12-31' ); $calendar_waiver_age = $birth_date_obj->diff( $dec31_obj )->y; $birth_month_day = $birth_date_obj->format( 'm-d' ); if ( $calendar_waiver_age == 18 ) { $waiver_age = ( $birth_month_day >= '09-16' && $birth_month_day <= '12-31' ) ? 19 : 18; } else { $waiver_age = $calendar_waiver_age; } if ( $waiver_age >= 25 ) { $waiver_age = 25; } // 4. Gather NHL Game Stats & First-Season GP $is_goalie = ( stripos( $player->Position, 'Goaltender' ) !== false ); $nhl_id = $player->nhl_id; $total_nhl_gp = 0; $first_season_gp = 0; if ( !empty( $nhl_id ) ) { $stats_table = $is_goalie ? 'otg_goalie_seasonal_stats' : 'otg_player_seasonal_stats'; $nhl_seasons_games = $wpdb->get_results( $wpdb->prepare( "SELECT season, SUM(games_played) as total_gp FROM {$stats_table} WHERE nhl_id = %s AND league_name = 'NHL' GROUP BY season ORDER BY season ASC", $nhl_id ) ); foreach ( $nhl_seasons_games as $stat_row ) { $season_start_year = intval( explode( '-', $stat_row->season )[0] ); $gp = intval( $stat_row->total_gp ); if ( $season_start_year == $signing_year ) { $first_season_gp = $gp; } $total_nhl_gp += $gp; } } // 5. Look up Base Limits based on Position and Waiver Age $max_seasons = 0; $max_gp = 0; if ( ! $is_goalie ) { switch ( $waiver_age ) { case 18: $max_seasons = ( $first_season_gp >= 11 ) ? 3 : 5; $max_gp = 160; break; case 19: $max_seasons = ( $first_season_gp >= 11 ) ? 3 : 4; $max_gp = 160; break; case 20: $max_seasons = 3; $max_gp = 160; break; case 21: $max_seasons = 3; $max_gp = 80; break; case 22: $max_seasons = 3; $max_gp = 70; break; case 23: $max_seasons = 3; $max_gp = 60; break; case 24: $max_seasons = 2; $max_gp = 60; break; default: $max_seasons = 1; $max_gp = 0; break; } } else { switch ( $waiver_age ) { case 18: $max_seasons = ( $first_season_gp >= 11 ) ? 4 : 6; $max_gp = 80; break; case 19: $max_seasons = ( $first_season_gp >= 11 ) ? 4 : 5; $max_gp = 80; break; case 20: $max_seasons = 4; $max_gp = 80; break; case 21: $max_seasons = 4; $max_gp = 60; break; case 22: $max_seasons = 4; $max_gp = 60; break; case 23: $max_seasons = 3; $max_gp = 60; break; case 24: $max_seasons = 2; $max_gp = 60; break; default: $max_seasons = 1; $max_gp = 0; break; } } // Apply slide_contract penalty if it equals -1 if ( $slide_contract_val === -1 ) { $max_seasons = max( 1, $max_seasons - 1 ); } // 6. Calculate Seasons Elapsed (Ordinal distance from signing year) $current_season_year = intval( explode( '-', $season )[0] ); $seasons_elapsed = max( 0, $current_season_year - $signing_year ); // 7. Final Threshold & Remaining Calculation if ( $max_gp > 0 && $total_nhl_gp >= $max_gp ) { return [ 'exempt' => false, 'label' => 'Requires Waivers' ]; } if ( $seasons_elapsed >= $max_seasons ) { return [ 'exempt' => false, 'label' => 'Requires Waivers' ]; } $seasons_left = $max_seasons - $seasons_elapsed; if ( $seasons_left <= 0 ) { return [ 'exempt' => false, 'label' => 'Requires Waivers' ]; } return [ 'exempt' => true, 'label' => sprintf( 'Exempt (%d %s Left)', $seasons_left, ( $seasons_left == 1 ? 'Season' : 'Seasons' ) ) ]; } function otg_render_rangers_contracts_shortcode($atts) { global $wpdb; // 1. Exact raw table names $years_table = 'otg_rangers_contract_years'; $contracts_table = 'otg_rangers_contracts'; $players_table = 'otg_players'; $games_table = 'otg_rangers_games'; $settings_table = 'otg_rangers_season_settings'; // Helper function to generate status icon HTML based on roster status $get_status_icon_html = function($roster_status) { $status_upper = strtoupper(trim($roster_status)); $icon_url = ''; $alt_text = ''; if ($status_upper === 'IR') { $icon_url = 'https://outsidethegarden.com/wp-content/uploads/2026/07/IR.png'; $alt_text = 'Injured Reserve'; } elseif ($status_upper === 'LTIR') { $icon_url = 'https://outsidethegarden.com/wp-content/uploads/2026/07/LTIR.png'; $alt_text = 'Long-Term Injured Reserve'; } elseif ($status_upper === 'SUSPENDED') { $icon_url = 'https://outsidethegarden.com/wp-content/uploads/2026/07/suspended.png'; $alt_text = 'Suspended'; } elseif ($status_upper === 'NON-ROSTER' || $status_upper === 'NON ROSTER') { $icon_url = 'https://outsidethegarden.com/wp-content/uploads/2026/07/non-roster.png'; $alt_text = 'Non-Roster'; } elseif ($status_upper === 'RETIRED') { // No image icon output for retired status as requested $icon_url = ''; $alt_text = ''; } if (!empty($icon_url)) { return '' . esc_attr($alt_text) . ''; } return ''; }; // 2. Fetch distinct seasons for the filter dropdown $seasons_query = "SELECT DISTINCT season FROM {$years_table} WHERE season IS NOT NULL AND season != '' ORDER BY season DESC"; $raw_seasons = $wpdb->get_col($seasons_query); // 3. Default to the season where active_season = 'y' from otg_rangers_season_settings, falling back to most recent if not found $table_active_season = $wpdb->get_var($wpdb->prepare("SELECT season FROM {$settings_table} WHERE active_season = %s LIMIT 1", 'y')); $default_season = !empty($table_active_season) ? $table_active_season : (!empty($raw_seasons) ? $raw_seasons[0] : '2026-27'); // 4. Sanitize filter & view inputs $selected_season = isset($_GET['con_season']) ? sanitize_text_field($_GET['con_season']) : $default_season; $selected_status = isset($_GET['con_status']) ? sanitize_text_field($_GET['con_status']) : ''; $selected_fa_type = isset($_GET['con_fa_type']) ? sanitize_text_field($_GET['con_fa_type']) : ''; $selected_player = isset($_GET['con_player']) ? sanitize_text_field($_GET['con_player']) : ''; $current_view = isset($_GET['view']) ? sanitize_text_field($_GET['view']) : 'season'; // In summary view, if a specific metric season isn't requested via query string, use the default/latest season for top metrics $metric_season = ($current_view === 'summary') ? (isset($_GET['metric_season']) ? sanitize_text_field($_GET['metric_season']) : $default_season) : $selected_season; // Determine if the selected/metric season is a future season relative to the current live date $current_live_season_start_year = intval(explode('-', $default_season)[0]); $target_season_start_year = intval(explode('-', $metric_season)[0]); $is_future_season = ($target_season_start_year > $current_live_season_start_year); // 5. Build query conditions for main query (Season View) - Adjusted to pull from contracts base so unsigned FAs appear in their fa_season $where_clauses = ["(T2.season = %s OR (T2.season IS NULL AND T1.fa_season = %s))"]; $params = [$selected_season, $selected_season]; if (!empty($selected_status)) { $where_clauses[] = "T2.roster_status = %s"; $params[] = $selected_status; } if (!empty($selected_fa_type)) { if (strtoupper($selected_fa_type) === 'RFA') { $where_clauses[] = "(T1.free_agent_type = 'RFA' OR T1.free_agent_type LIKE 'RFA-%' OR T1.free_agent_type LIKE 'RFA%')"; } else { $where_clauses[] = "T1.free_agent_type = %s"; $params[] = $selected_fa_type; } } if (!empty($selected_player)) { $where_clauses[] = "(T1.player_id LIKE %s OR p.Name LIKE %s)"; $params[] = '%' . $selected_player . '%'; $params[] = '%' . $selected_player . '%'; } $where_sql = implode(" AND ", $where_clauses); $query = $wpdb->prepare(" SELECT COALESCE(T2.player_id, T1.player_id) AS profile_id, COALESCE(T2.player_id, T1.player_id) AS player_id, T1.aav, T1.free_agent_type, T1.fa_season, COALESCE(T2.season, T1.fa_season) AS season, T2.cap_hit, T2.clause, T2.roster_status, p.Name AS player_name, p.position AS player_position FROM {$contracts_table} AS T1 LEFT JOIN {$years_table} AS T2 ON T1.contract_id = T2.contract_id AND T2.season = %s LEFT JOIN {$players_table} AS p ON COALESCE(T2.player_id, T1.player_id) = p.ID WHERE {$where_sql} ORDER BY T2.cap_hit DESC ", array_merge([$selected_season], $params)); $results = $wpdb->get_results($query); // Fetch season settings banner data using metric_season $settings = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$settings_table} WHERE season = %s", $metric_season )); // Fallback active settings row if active_season = 'y' is needed for league minimum lookup $active_settings = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$settings_table} WHERE active_season = %s LIMIT 1", 'y' )); $league_minimum_val = ($active_settings && !empty($active_settings->league_minimum)) ? floatval($active_settings->league_minimum) : ($settings && !empty($settings->league_minimum) ? floatval($settings->league_minimum) : 775000); // 6. Calculate Top Box Metrics & Date Calculations based on $metric_season $salary_cap = $settings && !empty($settings->salary_cap) ? floatval($settings->salary_cap) : 88000000; $all_season_query = $wpdb->prepare(" SELECT T2.cap_hit, T2.roster_status, T2.player_id, T1.aav, T2.clause FROM {$years_table} AS T2 LEFT JOIN {$contracts_table} AS T1 ON T2.contract_id = T1.contract_id WHERE T2.season = %s ", $metric_season); $all_season_records = $wpdb->get_results($all_season_query); $season_start = ($settings && !empty($settings->regular_season_start)) ? $settings->regular_season_start : $metric_season . '-10-01'; $season_end = ($settings && !empty($settings->regular_season_end)) ? $settings->regular_season_end : (intval(explode('-', $metric_season)[0]) + 1) . '-04-15'; $season_start_ts = strtotime($season_start); $season_end_ts = strtotime($season_end); $current_date_ts = current_time('timestamp'); $total_season_days = max(1, round(($season_end_ts - $season_start_ts) / 86400)); $elapsed_days = 0; if ($current_date_ts >= $season_start_ts) { $elapsed_days = min($total_season_days, round((min($current_date_ts, $season_end_ts) - $season_start_ts) / 86400)); } $remaining_days = max(0, $total_season_days - $elapsed_days); $total_allocated_cap = 0; $total_buried_relief = 0; foreach ($all_season_records as $rec) { $status_lower = strtolower(trim($rec->roster_status)); $clause_upper = strtoupper(trim($rec->clause)); // Retired 35+ contracts do not count against the active cap allocation if ($status_lower === 'retired' && ($clause_upper === '35+' || $clause_upper === '35 PLUS' || strpos($clause_upper, '35+') !== false)) { continue; } // Check if player's contract is buried (status is exactly "minors" or contains "minors") if ($status_lower === 'minors' || $status_lower === 'minors/buried' || $status_lower === 'buried' || strpos($status_lower, 'minor') !== false) { $player_aav = !empty($rec->cap_hit) ? floatval($rec->cap_hit) : (!empty($rec->aav) ? floatval($rec->aav) : 0); $diff = max(0, $player_aav - $league_minimum_val); $total_buried_relief += $diff; $total_allocated_cap += $diff; } elseif ($status_lower !== 'minors/buried' && $status_lower !== 'minors' && $status_lower !== 'buried') { $total_allocated_cap += floatval($rec->cap_hit); } } $projected_cap_space = $salary_cap - $total_allocated_cap; $deadline_date_str = ''; if ($settings && !empty($settings->trade_deadline)) { $deadline_date_str = $settings->trade_deadline; } elseif ($settings && !empty($settings->regular_season_end)) { $deadline_date_str = date('Y-m-d', strtotime($settings->regular_season_end . ' - 40 days')); } else { $deadline_date_str = date('Y-m-d', strtotime('+40 days')); } $deadline_timestamp = strtotime($deadline_date_str); $days_to_deadline = max(0, ($deadline_timestamp - $season_start_ts) / 86400); $daily_accrual_space = ($projected_cap_space > 0) ? ($projected_cap_space / $total_season_days) * min($days_to_deadline, $total_season_days) : 0; $deadline_space = $projected_cap_space + $daily_accrual_space; $calculate_actual_days = function($row) use ($is_future_season, $elapsed_days) { if ($is_future_season) { return ''; } $status = strtolower(trim($row->roster_status)); if ($status === 'retired') { return ''; } if (in_array($status, ['minors/buried', 'minors', 'buried']) || strpos($status, 'minor') !== false) { return 0; } return intval($elapsed_days); }; $calculate_projected_days = function($row) use ($is_future_season, $elapsed_days, $remaining_days) { if ($is_future_season) { return ''; } $status = strtolower(trim($row->roster_status)); if ($status === 'retired') { return ''; } if (in_array($status, ['minors/buried', 'minors', 'buried']) || strpos($status, 'minor') !== false) { return 0; } if (in_array($status, ['roster', 'ir', 'ltir'])) { return intval($elapsed_days + $remaining_days); } return intval($elapsed_days); }; // Helper function for mapping clause tooltip descriptions and button styles $get_clause_details = function($raw_clause) { $trimmed = trim($raw_clause); $upper = strtoupper($trimmed); $desc = $trimmed; if ($upper === 'ELC') { $desc = 'Entry Level Contract'; } elseif ($upper === '35+' || $upper === '35 PLUS') { $desc = '35+ Contract'; } elseif ($upper === 'NM') { $desc = 'No Movement Clause'; } elseif ($upper === 'NM NT' || $upper === 'NMN/T' || $upper === 'NMN-T') { $desc = 'No Movement Clause and No Trade Clause'; } elseif (preg_match('/^NM\s+NT(\d+)$/i', $trimmed, $matches)) { $x = $matches[1]; $desc = 'No Movement Clause and ' . $x . ' Team No Trade Clause'; } elseif (preg_match('/^NT(\d+)$/i', $trimmed, $matches)) { $x = $matches[1]; $desc = $x . ' Team No Trade Clause'; } // Color styling rules: 'ELC' -> green, '35+' -> silver/gray (#c0c0c0), anything with 'NM' -> darker orange $bg_color = 'rgba(241, 196, 15, 0.1)'; $border_color = 'rgba(241, 196, 15, 0.3)'; $text_color = '#f1c40f'; if ($upper === 'ELC' || strpos($upper, 'ELC') !== false) { $bg_color = 'rgba(46, 204, 113, 0.15)'; $border_color = 'rgba(46, 204, 113, 0.4)'; $text_color = '#2ecc71'; } elseif ($upper === '35+' || $upper === '35 PLUS' || strpos($upper, '35+') !== false) { $bg_color = 'rgba(192, 192, 192, 0.15)'; $border_color = 'rgba(192, 192, 192, 0.4)'; $text_color = '#c0c0c0'; } elseif (strpos($upper, 'NM') !== false) { $bg_color = 'rgba(211, 84, 0, 0.18)'; $border_color = 'rgba(211, 84, 0, 0.45)'; $text_color = '#e67e22'; // Darker orange tone } return [ 'desc' => $desc, 'style' => 'background: ' . $bg_color . '; border: 1px solid ' . $border_color . '; color: ' . $text_color . '; padding: 1px 4px; border-radius: 3px; font-size: 0.65em; font-weight: bold; text-align: center; justify-self: center; white-space: nowrap;', 'button_style' => 'background: ' . $bg_color . '; border: 1px solid ' . $border_color . '; color: ' . $text_color . '; padding: 2px 6px; border-radius: 4px; font-size: 0.7em; font-weight: bold; display: inline-block; text-align: center; text-transform: uppercase;' ]; }; // 7. UI Styling & Layout Wrapper $input_style = 'width: 100%; height: 34px; padding: 0 8px; background: #222; border: 1px solid #444; color: #fff; border-radius: 4px; box-sizing: border-box; font-size: 0.85em;'; $html = '
'; // Inject CSS for hover states on top view buttons $html .= ''; $html .= '
New York Rangers Player Contracts
'; // View Toggles Styles $btn_selected = 'background: #0073aa; color: #000000; border: 1px solid #0073aa;'; $btn_unhighlighted = 'background: #181818; color: #0073aa; border: 1px solid #0073aa;'; $season_style = ($current_view === 'season') ? $btn_selected : $btn_unhighlighted; $summary_style = ($current_view === 'summary') ? $btn_selected : $btn_unhighlighted; $html .= '
'; $html .= '
'; $html .= 'Season Summary'; $html .= 'Multi-year'; $html .= '
'; if ($current_view === 'summary') { $html .= '
'; $html .= 'Metrics Season:'; $html .= ''; $html .= '
'; } $html .= '
'; // Top Three Summary Metric Boxes $html .= '
'; $html .= '
'; $html .= '
Salary Cap (' . esc_html($metric_season) . ')
'; $html .= '
$' . number_format($salary_cap, 0) . '
'; $html .= '
'; $cap_space_color = $projected_cap_space >= 0 ? '#2ecc71' : '#e74c3c'; $html .= '
'; $html .= '
Projected Cap Space
'; $html .= '
$' . number_format($projected_cap_space, 0) . '
'; $html .= '
'; $html .= '
'; $html .= '
Deadline Cap Space
'; $html .= '
$' . number_format($deadline_space, 0) . '
'; $html .= '
Deadline: ' . esc_html($deadline_date_str) . '
'; $html .= '
'; $html .= '
'; if ($settings) { $html .= '
'; $html .= 'League Minimum: $' . number_format($league_minimum_val, 0) . ''; if (!empty($settings->regular_season_start) && !empty($settings->regular_season_end)) { $html .= ' | Regular Season: ' . esc_html($settings->regular_season_start) . ' to ' . esc_html($settings->regular_season_end) . ''; } if (!empty($settings->trade_deadline)) { $html .= ' | Trade Deadline: ' . esc_html($settings->trade_deadline) . ''; } $html .= '
'; } // 8. Render Selection Filter Form (Only shown in Season View) if ($current_view !== 'summary') { $current_url = strtok($_SERVER["URI"] ?? $_SERVER['REQUEST_URI'], '?'); $html .= '
'; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $clear_url = add_query_arg('view', $current_view, $current_url); $html .= 'Clear'; $html .= '
'; $html .= '
'; } if ($current_view !== 'summary' && empty($results)) { $html .= '
No contract records found matching the selected criteria.
'; $html .= '
'; return $html; } // 9. Categorize and Group Records (Handling Retired 35+ contracts separately) $forwards = []; $defense = []; $goalies = []; $bought_out = []; $retained = []; $bonuses = []; $retired_35_plus = []; $non_roster_forwards = []; $non_roster_defense = []; $non_roster_goalies = []; $non_roster_other = []; $table_total_cap_hit = 0; foreach ($results as $row) { $status = strtolower(trim($row->roster_status)); $clause = strtoupper(trim($row->clause)); $pos = trim($row->player_position); // Check for Retired 35+ contract if ($status === 'retired' && ($clause === '35+' || $clause === '35 PLUS' || strpos($clause, '35+') !== false)) { $retired_35_plus[] = $row; // Retired 35+ contracts do not count toward table_total_cap_hit or active salary allocations continue; } if ($status === 'buyout' || strpos($status, 'buyout') !== false) { $bought_out[] = $row; $table_total_cap_hit += floatval($row->cap_hit); continue; } if ($status === 'retained' || strpos($status, 'retained') !== false) { $retained[] = $row; $table_total_cap_hit += floatval($row->cap_hit); continue; } if ($status === 'bonus' || strpos($status, 'bonus') !== false || strpos($status, 'bonus charge' ) !== false || $status === 'bonus carryover' || strpos($status, 'carryover') !== false) { $bonuses[] = $row; $table_total_cap_hit += floatval($row->cap_hit); continue; } // Exclude other deceased or retired statuses from active/non-roster regular tables if (in_array($status, ['deceased', 'retired'])) { continue; } $is_non_roster = ($status === 'minors/buried' || $status === 'minors' || $status === 'buried' || strpos($status, 'minor') !== false); if ($is_non_roster) { if (in_array($pos, ['C', 'L', 'R', 'Center', 'Left Wing', 'Right Wing'])) { $non_roster_forwards[] = $row; } elseif (in_array($pos, ['D', 'Defenseman'])) { $non_roster_defense[] = $row; } elseif (in_array($pos, ['G', 'Goaltender'])) { $non_roster_goalies[] = $row; } else { $non_roster_other[] = $row; } } else { $table_total_cap_hit += floatval($row->cap_hit); if (in_array($pos, ['C', 'L', 'R', 'Center', 'Left Wing', 'Right Wing'])) { $forwards[] = $row; } elseif (in_array($pos, ['D', 'Defenseman'])) { $defense[] = $row; } elseif (in_array($pos, ['G', 'Goaltender'])) { $goalies[] = $row; } else { $forwards[] = $row; } } } $render_fa_badge = function($raw_fa_type) { $fa_raw_trimmed = trim($raw_fa_type); $fa_upper = strtoupper($fa_raw_trimmed); if (empty($fa_upper)) return '-'; $fa_color = ''; $is_rfa = (strpos($fa_upper, 'RFA') !== false); $is_ufa = (strpos($fa_upper, 'UFA') !== false); if ($is_rfa) { $fa_color = '#e74c3c'; } elseif ($is_ufa) { $fa_color = '#3498db'; } if (!empty($fa_color)) { $badge_style = 'background: ' . $fa_color . '; color: #fff; padding: 2px 5px; border-radius: 3px; font-size: 0.75em; font-weight: bold; display: inline-flex; align-items: center; justify-content: center; gap: 3px; line-height: 1.2; width: 58px; box-sizing: border-box; text-align: center;'; $badge_html = ''; $has_arbitration = ($fa_upper === 'RFA-A' || $fa_upper === 'RFA (A)' || preg_match('/^RFA[\s\-\(]+A[\)]?$/i', $fa_raw_trimmed)); if ($has_arbitration) { $badge_html .= 'RFAArbitration'; } else { $badge_html .= esc_html($fa_upper); } $badge_html .= ''; return $badge_html; } return esc_html($fa_raw_trimmed); }; // ========================================== // MULTI-YEAR SUMMARY LOGIC & RENDER // ========================================== if ($current_view === 'summary') { $all_players_query = "SELECT DISTINCT player_id FROM {$years_table} WHERE player_id IS NOT NULL AND player_id != ''"; $all_player_ids = $wpdb->get_col($all_players_query); if (!empty($all_player_ids)) { $ids_str = implode("','", array_map('esc_sql', $all_player_ids)); $future_query = " SELECT T2.player_id AS profile_id, T2.player_id, T1.aav, T1.free_agent_type, T1.fa_season, T2.season, T2.cap_hit, T2.clause, T2.roster_status, p.Name AS player_name, p.position AS player_position FROM {$years_table} AS T2 LEFT JOIN {$contracts_table} AS T1 ON T2.contract_id = T1.contract_id LEFT JOIN {$players_table} AS p ON T2.player_id = p.ID WHERE T2.player_id IN ('$ids_str') "; $future_records = $wpdb->get_results($future_query); } else { $future_records = []; } $player_future_years = []; $player_meta = []; foreach ($future_records as $fr) { $pid = $fr->player_id; // Check if player's roster status in this year view is deceased or retired (excluding retired 35+ contracts which have their own section) $status_check = strtolower(trim($fr->roster_status)); $clause_check = strtoupper(trim($fr->clause)); $is_ret_35 = ($status_check === 'retired' && ($clause_check === '35+' || $clause_check === '35 PLUS' || strpos($clause_check, '35+') !== false)); if ($status_check === 'deceased' || ($status_check === 'retired' && !$is_ret_35)) { continue; } if (!isset($player_future_years[$pid])) { $player_future_years[$pid] = []; } // Fetch one_way from contract years or contracts table for image checking $one_way_val = $wpdb->get_var($wpdb->prepare( "SELECT one_way FROM {$years_table} WHERE player_id = %s AND season = %s LIMIT 1", $pid, $fr->season )); if ($one_way_val === null) { $one_way_val = $wpdb->get_var($wpdb->prepare( "SELECT one_way FROM {$contracts_table} AS T1 JOIN {$years_table} AS T2 ON T1.contract_id = T2.contract_id WHERE T2.player_id = %s AND T2.season = %s LIMIT 1", $pid, $fr->season )); } // Calculate adjusted cap hit for multi-year view if buried or retired 35+ $effective_cap_hit = floatval($fr->cap_hit); if ($is_ret_35) { $effective_cap_hit = 0; // Retired 35+ contracts count as 0 against cap totals } elseif ($status_check === 'minors' || $status_check === 'minors/buried' || $status_check === 'buried' || strpos($status_check, 'minor') !== false) { $p_aav = $effective_cap_hit > 0 ? $effective_cap_hit : (!empty($fr->aav) ? floatval($fr->aav) : 0); $effective_cap_hit = max(0, $p_aav - $league_minimum_val); } $player_future_years[$pid][$fr->season] = [ 'cap_hit' => $effective_cap_hit, 'raw_cap_hit' => floatval($fr->cap_hit), 'clause' => $fr->clause, 'fa_type' => $fr->free_agent_type, 'one_way' => $one_way_val, 'roster_status' => $fr->roster_status ]; if (!isset($player_meta[$pid])) { $player_meta[$pid] = $fr; } } $min_season = null; $max_season = null; foreach ($future_records as $fr) { if (!empty($fr->season)) { if ($min_season === null || strcmp($fr->season, $min_season) < 0) { $min_season = $fr->season; } if ($max_season === null || strcmp($fr->season, $max_season) > 0) { $max_season = $fr->season; } } } if ($min_season === null) $min_season = $default_season; if ($max_season === null) $max_season = $default_season; $inc_season = function($s) { $p = explode('-', $s); if (count($p) == 2) { return ($p[0]+1) . '-' . str_pad(($p[1]+1), 2, '0', STR_PAD_LEFT); } return $s; }; $display_seasons = []; $curr = $min_season; while (strcmp($curr, $max_season) <= 0) { $display_seasons[] = $curr; $curr = $inc_season($curr); } if (!in_array($max_season, $display_seasons)) { $display_seasons[] = $max_season; } // Fetch Salary Cap per season from settings table for the bottom summary breakdown $season_caps = []; $caps_results = $wpdb->get_results("SELECT season, salary_cap FROM {$settings_table}"); foreach ($caps_results as $cr) { $season_caps[$cr->season] = floatval($cr->salary_cap); } $sum_forwards = []; $sum_defense = []; $sum_goalies = []; $sum_bought_out = []; $sum_retained = []; $sum_bonuses = []; $sum_retired_35_plus = []; $sum_non_roster_forwards = []; $sum_non_roster_defense = []; $sum_non_roster_goalies = []; $sum_non_roster_other = []; foreach ($player_meta as $pid => $row) { $status = strtolower(trim($row->roster_status)); $clause = strtoupper(trim($row->clause)); $pos = trim($row->player_position); $is_ret_35 = ($status === 'retired' && ($clause === '35+' || $clause === '35 PLUS' || strpos($clause, '35+') !== false)); if ($status === 'deceased' || ($status === 'retired' && !$is_ret_35)) { continue; } if ($is_ret_35) { $sum_retired_35_plus[] = $row; continue; } if ($status === 'buyout' || strpos($status, 'buyout') !== false) { $sum_bought_out[] = $row; continue; } if ($status === 'retained' || strpos($status, 'retained') !== false) { $sum_retained[] = $row; continue; } if ($status === 'bonus' || strpos($status, 'bonus') !== false || strpos($status, 'bonus charge') !== false || $status === 'bonus carryover' || strpos($status, 'carryover') !== false) { $sum_bonuses[] = $row; continue; } $is_non_roster = ($status === 'minors/buried' || $status === 'minors' || $status === 'buried' || strpos($status, 'minor') !== false); if ($is_non_roster) { if (in_array($pos, ['C', 'L', 'R', 'Center', 'Left Wing', 'Right Wing'])) { $sum_non_roster_forwards[] = $row; } elseif (in_array($pos, ['D', 'Defenseman'])) { $sum_non_roster_defense[] = $row; } elseif (in_array($pos, ['G', 'Goaltender'])) { $sum_non_roster_goalies[] = $row; } else { $sum_non_roster_other[] = $row; } } else { if (in_array($pos, ['C', 'L', 'R', 'Center', 'Left Wing', 'Right Wing'])) { $sum_forwards[] = $row; } elseif (in_array($pos, ['D', 'Defenseman'])) { $sum_defense[] = $row; } elseif (in_array($pos, ['G', 'Goaltender'])) { $sum_goalies[] = $row; } else { $sum_forwards[] = $row; } } } $total_cols = count($display_seasons) + 1; // Player column + season columns $html .= '
'; $html .= ''; $html .= ''; $html .= ''; foreach ($display_seasons as $s) { $html .= ''; } $html .= ''; // Main Header Row $html .= ''; $html .= ''; foreach ($display_seasons as $s) { $html .= ''; } $html .= ''; $render_summary_section = function($title, $rows, $is_first_section = false) use ($player_future_years, $display_seasons, $inc_season, $render_fa_badge, $total_cols, $get_clause_details, $get_status_icon_html) { if (empty($rows)) return ['', array_fill_keys($display_seasons, 0)]; usort($rows, function($a, $b) use ($player_future_years) { $a_max = 0; if (isset($player_future_years[$a->player_id])) { $a_max = max(array_column($player_future_years[$a->player_id], 'cap_hit')); } $b_max = 0; if (isset($player_future_years[$b->player_id])) { $b_max = max(array_column($player_future_years[$b->player_id], 'cap_hit')); } return $b_max <=> $a_max; }); // Added top margin spacing if not the very first section $top_border_style = $is_first_section ? 'border-top: 2px solid #333;' : 'border-top: 15px solid #0b0b0b; border-bottom: 1px solid #333;'; $sec_html = ''; $season_totals = array_fill_keys($display_seasons, 0); foreach ($rows as $row) { $display_name = !empty($row->player_name) ? $row->player_name : $row->player_id; $profile_link = esc_url(home_url('/profile/?player_id=' . intval($row->profile_id))); $sec_html .= ''; $p_data = isset($player_future_years[$row->player_id]) ? $player_future_years[$row->player_id] : []; $p_max_season = ''; $latest_fa_type = $row->free_agent_type; foreach ($p_data as $s => $data) { if (strcmp($s, $p_max_season) > 0) { $p_max_season = $s; } if (!empty($data['fa_type'])) { $latest_fa_type = $data['fa_type']; } } if (empty($p_max_season)) { $p_max_season = $row->season; } $current_row_status = isset($p_data[$p_max_season]['roster_status']) ? $p_data[$p_max_season]['roster_status'] : (isset($row->roster_status) ? $row->roster_status : ''); $player_status_icon = $get_status_icon_html($current_row_status); $sec_html .= ''; $fa_season_target = $inc_season($p_max_season); foreach ($display_seasons as $s) { $sec_html .= ''; } $sec_html .= ''; } $sec_html .= ''; $sec_html .= ''; foreach ($display_seasons as $s) { $sec_html .= ''; } $sec_html .= ''; return [$sec_html, $season_totals]; }; list($f_html, $f_totals) = $render_summary_section('Forwards', $sum_forwards, true); list($d_html, $d_totals) = $render_summary_section('Defensemen', $sum_defense, false); list($g_html, $g_totals) = $render_summary_section('Goaltenders', $sum_goalies, false); list($bo_html, $bo_totals) = $render_summary_section('Bought Out Contracts', $sum_bought_out, false); list($re_html, $re_totals) = $render_summary_section('Retained Salary Transactions', $sum_retained, false); list($bn_html, $bn_totals) = $render_summary_section('Salary Bonus Charges', $sum_bonuses, false); list($r35_html, $r35_totals) = $render_summary_section('Retired 35+ Contracts', $sum_retired_35_plus, false); // ========================================== // SEASON-BY-SEASON TOTAL SUMMARY BLOCK // ========================================== $summary_block_html = ''; $render_summary_row_html = function($label, $totals_arr, $highlight = false, $custom_color = '#fff') use ($display_seasons) { $row_bg = $highlight ? '#1c1c1c' : '#121212'; $r_html = ''; $r_html .= ''; foreach ($display_seasons as $s) { $val = isset($totals_arr[$s]) ? $totals_arr[$s] : 0; $r_html .= ''; } $r_html .= ''; return $r_html; }; // 1. Total Salary (Forwards + Defensemen + Goaltenders) $total_salary_totals = []; foreach ($display_seasons as $s) { $total_salary_totals[$s] = (isset($f_totals[$s]) ? $f_totals[$s] : 0) + (isset($d_totals[$s]) ? $d_totals[$s] : 0) + (isset($g_totals[$s]) ? $g_totals[$s] : 0); } $summary_block_html .= $render_summary_row_html('Total Salary:', $total_salary_totals, false, '#ccc'); // 2. Total Buyout $summary_block_html .= $render_summary_row_html('Total Buyout:', $bo_totals, false, '#ccc'); // 3. Total Retained $summary_block_html .= $render_summary_row_html('Total Retained:', $re_totals, false, '#ccc'); // 4. Total Bonus Carryover $summary_block_html .= $render_summary_row_html('Total Bonus Carryover:', $bn_totals, false, '#ccc'); // 5. Retired 35+ Contracts Total Line $summary_block_html .= $render_summary_row_html('Retired 35+ Contracts:', $r35_totals, false, '#ccc'); // 6. Total Cap Hit (Sum of relevant lines, excluding Retired 35+ contracts which are 0) $total_cap_hit_totals = []; foreach ($display_seasons as $s) { $total_cap_hit_totals[$s] = (isset($total_salary_totals[$s]) ? $total_salary_totals[$s] : 0) + (isset($bo_totals[$s]) ? $bo_totals[$s] : 0) + (isset($re_totals[$s]) ? $re_totals[$s] : 0) + (isset($bn_totals[$s]) ? $bn_totals[$s] : 0); } $summary_block_html .= $render_summary_row_html('Total Cap Hit:', $total_cap_hit_totals, true, '#fff'); // 7. Salary Cap $salary_cap_totals = []; foreach ($display_seasons as $s) { $salary_cap_totals[$s] = isset($season_caps[$s]) ? $season_caps[$s] : $salary_cap; } $summary_block_html .= $render_summary_row_html('Salary Cap:', $salary_cap_totals, false, '#3498db'); // 8. Cap Space $cap_space_totals = []; foreach ($display_seasons as $s) { $cap_space_totals[$s] = $salary_cap_totals[$s] - $total_cap_hit_totals[$s]; } $space_row_bg = '#1c1c1c'; $summary_block_html .= ''; $summary_block_html .= ''; foreach ($display_seasons as $s) { $c_space = $cap_space_totals[$s]; $space_color = $c_space >= 0 ? '#2ecc71' : '#e74c3c'; $summary_block_html .= ''; } $summary_block_html .= ''; // Append active roster sections, retired 35+, and the summary block first $html .= $f_html . $d_html . $g_html . $bo_html . $re_html . $bn_html . $r35_html . $summary_block_html; // Render Non-Roster sections at the BOTTOM in Summary view if (!empty($sum_non_roster_forwards) || !empty($sum_non_roster_defense) || !empty($sum_non_roster_goalies) || !empty($sum_non_roster_other)) { list($nrf_html, $nrf_totals) = $render_summary_section('Non-Roster Forwards', $sum_non_roster_forwards, false); list($nrd_html, $nrd_totals) = $render_summary_section('Non-Roster Defensemen', $sum_non_roster_defense, false); list($nrg_html, $nrg_totals) = $render_summary_section('Non-Roster Goaltenders', $sum_non_roster_goalies, false); list($nro_html, $nro_totals) = $render_summary_section('Non-Roster Other', $sum_non_roster_other, false); $non_roster_block_html = ''; $non_roster_block_html .= $nrf_html . $nrd_html . $nrg_html . $nro_html; $html .= $non_roster_block_html; } $html .= '
Player' . esc_html($s) . '
' . esc_html($title) . '
' . esc_html($display_name) . '' . $player_status_icon . ''; if (isset($p_data[$s])) { $ch = $p_data[$s]['cap_hit']; $clause = $p_data[$s]['clause']; $one_way_val = $p_data[$s]['one_way']; $season_totals[$s] += $ch; $sec_html .= '
'; $left_group = '
'; if (!empty($clause)) { $c_info = $get_clause_details($clause); $left_group .= '' . esc_html($clause) . ''; } if ($one_way_val !== null && strtolower(trim((string)$one_way_val)) === 'n') { $left_group .= 'Two-Way'; } $left_group .= '
'; $sec_html .= $left_group; $sec_html .= '$' . number_format($ch, 0) . ''; $sec_html .= '
'; } elseif ($s === $fa_season_target) { $sec_html .= '
' . $render_fa_badge($latest_fa_type) . '
'; } else { $sec_html .= '
-
'; } $sec_html .= '
' . esc_html($title) . ' Total:'; if ($season_totals[$s] > 0) { $sec_html .= '
$' . number_format($season_totals[$s], 0) . '
'; } else { $sec_html .= '-'; } $sec_html .= '
Season Summary Breakdown
' . esc_html($label) . ''; if ($val > 0) { $r_html .= '
$' . number_format($val, 0) . '
'; } else { $r_html .= '
-
'; } $r_html .= '
Cap Space:'; $summary_block_html .= '
$' . number_format($c_space, 0) . '
'; $summary_block_html .= '
Non-Roster Players
'; } else { // ========================================== // SEASON VIEW LOGIC & RENDER // ========================================== $active_total_cap = 0; $render_section_table = function($title, $rows, &$total_sum, $selected_season, $wpdb, $league_minimum_val, $is_retired_block = false) use ($calculate_actual_days, $calculate_projected_days, $render_fa_badge, $get_clause_details, $get_status_icon_html, $contracts_table, $years_table) { if (empty($rows)) return ''; $section_sum = 0; if (!$is_retired_block) { foreach ($rows as $r) { if (!empty($r->cap_hit)) { $status_lower = strtolower(trim($r->roster_status)); if ($status_lower === 'minors' || $status_lower === 'minors/buried' || $status_lower === 'buried' || strpos($status_lower, 'minor') !== false) { $p_aav = floatval($r->cap_hit); $section_sum += max(0, $p_aav - $league_minimum_val); } else { $section_sum += floatval($r->cap_hit); } } } $total_sum += $section_sum; } $html = '
' . esc_html($title) . '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; foreach ($rows as $row) { $display_name = !empty($row->player_name) ? $row->player_name : $row->player_id; $profile_link = esc_url(home_url('/profile/?player_id=' . intval($row->profile_id))); $actual_days = $calculate_actual_days($row); $projected_days = $calculate_projected_days($row); // Fetch Waiver Status $waiver_status = otg_get_waiver_status( $row->player_id, $selected_season, $wpdb ); $badge_bg = $waiver_status['exempt'] ? 'rgba(46, 204, 113, 0.15)' : 'rgba(231, 76, 60, 0.15)'; $badge_border = $waiver_status['exempt'] ? '#2ecc71' : '#e74c3c'; $badge_color = $waiver_status['exempt'] ? '#2ecc71' : '#e74c3c'; $player_status_icon = $get_status_icon_html($row->roster_status); $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; // Right-justified FA badge container $html .= ''; $html .= ''; $html .= ''; $html .= ''; } $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
PlayerPositionCap HitStatusActual DaysProjected DaysFA TypeFA SeasonWaivers
' . esc_html($display_name) . '' . $player_status_icon . '' . esc_html($row->player_position) . ''; if (!empty($row->cap_hit)) { $contract_info = $wpdb->get_row($wpdb->prepare( "SELECT one_way FROM {$contracts_table} WHERE player_id = %s OR contract_id = (SELECT contract_id FROM {$years_table} WHERE player_id = %s AND season = %s LIMIT 1) LIMIT 1", $row->player_id, $row->player_id, $selected_season )); $one_way_val = $contract_info ? $contract_info->one_way : null; if ($one_way_val === null) { $one_way_val = $wpdb->get_var($wpdb->prepare( "SELECT one_way FROM {$years_table} WHERE player_id = %s AND season = %s LIMIT 1", $row->player_id, $selected_season )); } $status_lower = strtolower(trim($row->roster_status)); $display_cap_val = floatval($row->cap_hit); if ($is_retired_block) { $display_cap_val = floatval($row->cap_hit); // Show contract AAV/cap hit on row, but totals are unaffected } else { $is_buried_contract = ($status_lower === 'minors' || $status_lower === 'minors/buried' || $status_lower === 'buried' || strpos($status_lower, 'minor') !== false); if ($is_buried_contract) { $display_cap_val = max(0, floatval($row->cap_hit) - $league_minimum_val); } } $html .= '
'; $left_group = '
'; if (!empty($row->clause)) { $c_info = $get_clause_details($row->clause); $left_group .= '' . esc_html($row->clause) . ''; } if ($one_way_val !== null && strtolower(trim((string)$one_way_val)) === 'n') { $left_group .= 'Two-Way'; } $left_group .= '
'; $html .= $left_group; $cap_display_text = '$' . number_format($display_cap_val, 0); $html .= '' . $cap_display_text . ''; $html .= '
'; } else { $html .= '-'; } $html .= '
' . (!empty($row->roster_status) ? esc_html($row->roster_status) : 'Free Agent') . '' . (!empty($row->cap_hit) && $actual_days !== '' ? $actual_days : '-') . '' . (!empty($row->cap_hit) && $projected_days !== '' ? $projected_days : '-') . '
' . $render_fa_badge($row->free_agent_type) . '
' . esc_html($row->fa_season) . '' . esc_html($waiver_status['label']) . '
' . esc_html($title) . ' Total:
-
'; return $html; }; $render_non_roster_table = function($title, $rows, $selected_season, $wpdb, $league_minimum_val) use ($calculate_actual_days, $calculate_projected_days, $render_fa_badge, $get_clause_details, $get_status_icon_html, $contracts_table, $years_table) { if (empty($rows)) return ''; $html = '
' . esc_html($title) . '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $non_roster_sum = 0; foreach ($rows as $row) { if (!empty($row->cap_hit)) { $status_lower = strtolower(trim($row->roster_status)); if ($status_lower === 'minors' || $status_lower === 'minors/buried' || $status_lower === 'buried' || strpos($status_lower, 'minor') !== false) { $p_aav = floatval($row->cap_hit); $non_roster_sum += max(0, $p_aav - $league_minimum_val); } else { $non_roster_sum += floatval($row->cap_hit); } } $display_name = !empty($row->player_name) ? $row->player_name : $row->player_id; $profile_link = esc_url(home_url('/profile/?player_id=' . intval($row->profile_id))); $actual_days = $calculate_actual_days($row); $projected_days = $calculate_projected_days($row); // Fetch Waiver Status $waiver_status = otg_get_waiver_status( $row->player_id, $selected_season, $wpdb ); $badge_bg = $waiver_status['exempt'] ? 'rgba(46, 204, 113, 0.15)' : 'rgba(231, 76, 60, 0.15)'; $badge_border = $waiver_status['exempt'] ? '#2ecc71' : '#e74c3c'; $badge_color = $waiver_status['exempt'] ? '#2ecc71' : '#e74c3c'; $player_status_icon = $get_status_icon_html($row->roster_status); $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; // Right-justified FA badge container $html .= ''; $html .= ''; $html .= ''; $html .= ''; } $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
PlayerPositionCap HitStatusActual DaysProjected DaysFA TypeFA SeasonWaivers
' . esc_html($display_name) . '' . $player_status_icon . '' . esc_html($row->player_position) . ''; if (!empty($row->cap_hit)) { $contract_info = $wpdb->get_row($wpdb->prepare( "SELECT one_way FROM {$contracts_table} WHERE player_id = %s OR contract_id = (SELECT contract_id FROM {$years_table} WHERE player_id = %s AND season = %s LIMIT 1) LIMIT 1", $row->player_id, $row->player_id, $selected_season )); $one_way_val = $contract_info ? $contract_info->one_way : null; if ($one_way_val === null) { $one_way_val = $wpdb->get_var($wpdb->prepare( "SELECT one_way FROM {$years_table} WHERE player_id = %s AND season = %s LIMIT 1", $row->player_id, $selected_season )); } $status_lower = strtolower(trim($row->roster_status)); $display_cap_val = floatval($row->cap_hit); $is_buried_contract = ($status_lower === 'minors' || $status_lower === 'minors/buried' || $status_lower === 'buried' || strpos($status_lower, 'minor') !== false); if ($is_buried_contract) { $display_cap_val = max(0, floatval($row->cap_hit) - $league_minimum_val); } $html .= '
'; $left_group = '
'; if (!empty($row->clause)) { $c_info = $get_clause_details($row->clause); $left_group .= '' . esc_html($row->clause) . ''; } if ($one_way_val !== null && strtolower(trim((string)$one_way_val)) === 'n') { $left_group .= 'Two-Way'; } $left_group .= '
'; $html .= $left_group; $cap_display_text = '$' . number_format($display_cap_val, 0); $html .= '' . $cap_display_text . ''; $html .= '
'; } else { $html .= '-'; } $html .= '
' . (!empty($row->roster_status) ? esc_html($row->roster_status) : 'Free Agent') . '' . (!empty($row->cap_hit) && $actual_days !== '' ? $actual_days : '-') . '' . (!empty($row->cap_hit) && $projected_days !== '' ? $projected_days : '-') . '
' . $render_fa_badge($row->free_agent_type) . '
' . esc_html($row->fa_season) . '' . esc_html($waiver_status['label']) . '
' . esc_html($title) . ' Total:
$' . number_format($non_roster_sum, 0) . '
'; return $html; }; // Render active roster sections first $html .= $render_section_table('Forwards', $forwards, $active_total_cap, $selected_season, $wpdb, $league_minimum_val); $html .= $render_section_table('Defensemen', $defense, $active_total_cap, $selected_season, $wpdb, $league_minimum_val); $html .= $render_section_table('Goaltenders', $goalies, $active_total_cap, $selected_season, $wpdb, $league_minimum_val); $html .= $render_section_table('Bought Out Contracts', $bought_out, $active_total_cap, $selected_season, $wpdb, $league_minimum_val); $html .= $render_section_table('Retained Salary Transactions', $retained, $active_total_cap, $selected_season, $wpdb, $league_minimum_val); $html .= $render_section_table('Salary Bonus Charges', $bonuses, $active_total_cap, $selected_season, $wpdb, $league_minimum_val); // Render Retired 35+ contracts block in Season view if present if (!empty($retired_35_plus)) { $html .= $render_section_table('Retired 35+ Contracts', $retired_35_plus, $active_total_cap, $selected_season, $wpdb, $league_minimum_val, true); } // Render Non-Roster sections at the BOTTOM in Season View if (!empty($non_roster_forwards) || !empty($non_roster_defense) || !empty($non_roster_goalies) || !empty($non_roster_other)) { $html .= '
Non-Roster players
'; $html .= $render_non_roster_table('Non-Roster Forwards', $non_roster_forwards, $selected_season, $wpdb, $league_minimum_val); $html .= $render_non_roster_table('Non-Roster Defensemen', $non_roster_defense, $selected_season, $wpdb, $league_minimum_val); $html .= $render_non_roster_table('Non-Roster Goaltenders', $non_roster_goalies, $selected_season, $wpdb, $league_minimum_val); $html .= $render_non_roster_table('Non-Roster Other', $non_roster_other, $selected_season, $wpdb, $league_minimum_val); } $html .= '
'; $html .= 'Total Cap Hit Allocation:'; $html .= '$' . number_format($active_total_cap, 0) . ''; $html .= '
'; } $html .= ''; return $html; } Rangerjunkiekimmie – Activity – OutsideTheGarden Boards – Page 49
MARCH
«
Thu
5
Fri
6
Sat
7
Sun
8
Mon
9
Tue
10
Wed
11
»
Rangerjunkiekimmie
Rangerjunkiekimmie
Group: Registered
Joined: 2023-08-26
NHL All Star
2
Follow
That penguin was freer than Hunter

In forum Where Smit Hits The Fan

2 years ago
Kreider has to be the worst Ranger ever at clearing the puck

In forum Where Smit Hits The Fan

2 years ago
Anytime they don't give up a goal in the first or last minut...

In forum Where Smit Hits The Fan

2 years ago
Zib, Panarin, Kakko, Miller any one of them can be next

In forum Where Smit Hits The Fan

2 years ago
Can't stand Ferraro

In forum Where Smit Hits The Fan

2 years ago
This team as constructed is toast. Drury should be fired imm...

In forum Where Smit Hits The Fan

2 years ago
Big changes are still very much needed

In forum Where Smit Hits The Fan

2 years ago
Losing streak snapped

In forum Where Smit Hits The Fan

2 years ago
OK! He sucks at clearing the puck, he's too soft on the puck

In forum Where Smit Hits The Fan

2 years ago
so soft

In forum Where Smit Hits The Fan

2 years ago
Kreider sucks

In forum Where Smit Hits The Fan

2 years ago
Are the Rangers hitting? 😮

In forum Where Smit Hits The Fan

2 years ago
If that were Rempe he'd be sent down immediately after the g...

In forum Where Smit Hits The Fan

2 years ago
A younger Josh Anderson

In forum Where Smit Hits The Fan

2 years ago
We need a Josh Anderson type

In forum Where Smit Hits The Fan

2 years ago
Page 49 / 106