// ========================================================================= // 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 6
MAY
«
Fri
14
Sat
15
Sun
16
Mon
17
Tue
18
Wed
19
Thu
20
»
Rangerjunkiekimmie
Rangerjunkiekimmie
Group: Registered
Joined: 2023-08-26
NHL All Star
2
Follow
Younger, bigger  

In forum Where Smit Hits The Fan

10 months ago
Well that's a good thing. Thanks  

In forum Where Smit Hits The Fan

10 months ago
Parsnip with the long awaited goal

In forum Where Smit Hits The Fan

10 months ago
Is this Panarins final year of his contract?

In forum Where Smit Hits The Fan

10 months ago
Robertson is better than Soucy I think

In forum Where Smit Hits The Fan

10 months ago
N O P E !!  

In forum Where Smit Hits The Fan

10 months ago
8 periods, NO goals

In forum Where Smit Hits The Fan

10 months ago
Give him some time...This is only his 6th year  

In forum Where Smit Hits The Fan

10 months ago
Don't worry Quinn will fix it.........

In forum Where Smit Hits The Fan

10 months ago
They should put Miller in front of the net  

In forum Where Smit Hits The Fan

10 months ago
11 for 11 on the PK

In forum Where Smit Hits The Fan

10 months ago
At least Sheary is still in the line-up

In forum Where Smit Hits The Fan

10 months ago
Might as well replace a nobody with another nobody Just ho...

In forum Where Smit Hits The Fan

10 months ago
Same old same old

In forum Where Smit Hits The Fan

10 months ago
Like Laba, don't like the 3rd line

In forum Where Smit Hits The Fan

10 months ago
Page 6 / 106