Support multi-team printable schedule titles
Allow the printable calendar URL builders to select multiple teams and carry the selected title_format parameter through CSV, iCal, and print URLs. Add selected-first and matchup title modes so single-team schedules can show only the opponent while multi-team schedules consistently place a chosen team first, using vs for selected home games and at for away or selected-vs-selected games. Keep team-layout exports available for multiple selected teams, including title, separator, and opponent columns derived from the selected-team perspective. Adjust printable calendar matchup day styling so date numbers stay visible while event content can use the full day cell behind the badge. Extend schedule exporter tests for multi-team team layout, selected-first titles, matchup titles, and printable URL title_format propagation.
This commit is contained in:
@@ -332,7 +332,7 @@ body.month-pages .event.matchup .event-venue {
|
||||
position: absolute;
|
||||
top: var(--corner-badge-offset);
|
||||
left: var(--corner-badge-offset);
|
||||
z-index: 4;
|
||||
z-index: 20;
|
||||
width: var(--corner-badge-size);
|
||||
height: var(--corner-badge-size);
|
||||
display: flex;
|
||||
@@ -354,6 +354,15 @@ body.month-pages .event.matchup .event-venue {
|
||||
border: 1px solid var(--pc-border);
|
||||
}
|
||||
|
||||
.day.has-matchups .day-num {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
background: #fff;
|
||||
color: var(--team-ink, #111) !important;
|
||||
text-shadow: none !important;
|
||||
box-shadow: 0 0 0 1px var(--pc-border);
|
||||
}
|
||||
|
||||
body.month-pages .day .day-num {
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
@@ -366,6 +375,8 @@ body.month-pages .day .day-num {
|
||||
}
|
||||
|
||||
.events-stack {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: repeat(var(--event-count), minmax(0, 1fr));
|
||||
@@ -375,7 +386,7 @@ body.month-pages .day .day-num {
|
||||
box-sizing: border-box;
|
||||
grid-template-rows: repeat(var(--event-count), minmax(0, 1fr));
|
||||
gap: 2px;
|
||||
padding: calc(var(--corner-badge-size) + 5px) 2px 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.event {
|
||||
|
||||
@@ -62,7 +62,9 @@ function tse_sp_event_export_get_column_definitions() {
|
||||
'time' => __( 'Time', 'tonys-sportspress-enhancements' ),
|
||||
'season' => __( 'Season', 'tonys-sportspress-enhancements' ),
|
||||
'league' => __( 'League', 'tonys-sportspress-enhancements' ),
|
||||
'title' => __( 'Title', 'tonys-sportspress-enhancements' ),
|
||||
'team_name' => __( 'Team', 'tonys-sportspress-enhancements' ),
|
||||
'separator' => __( 'Separator', 'tonys-sportspress-enhancements' ),
|
||||
'opponent_name' => __( 'Opponent', 'tonys-sportspress-enhancements' ),
|
||||
'location_flag' => __( 'Home/Away', 'tonys-sportspress-enhancements' ),
|
||||
'field_name' => __( 'Field Name', 'tonys-sportspress-enhancements' ),
|
||||
@@ -85,12 +87,24 @@ function tse_sp_event_export_get_column_definitions() {
|
||||
function tse_sp_event_export_get_default_columns( $format ) {
|
||||
$defaults = array(
|
||||
'matchup' => array( 'date', 'time', 'season', 'league', 'away_team', 'home_team', 'field_name' ),
|
||||
'team' => array( 'label', 'date', 'time', 'season', 'league', 'opponent_name', 'location_flag', 'field_name' ),
|
||||
'team' => array( 'label', 'date', 'time', 'season', 'league', 'title', 'field_name' ),
|
||||
);
|
||||
|
||||
return isset( $defaults[ $format ] ) ? $defaults[ $format ] : $defaults['matchup'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize event title format.
|
||||
*
|
||||
* @param string $format Raw title format.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_event_export_sanitize_title_format( $format ) {
|
||||
$format = sanitize_key( (string) $format );
|
||||
|
||||
return in_array( $format, array( 'selected_first', 'matchup' ), true ) ? $format : 'selected_first';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize an export format.
|
||||
*
|
||||
@@ -179,6 +193,7 @@ function tse_sp_event_export_normalize_request_args( $source = null ) {
|
||||
$season_ids = isset( $source['season_id'] ) ? tse_sp_event_export_parse_id_list( wp_unslash( $source['season_id'] ) ) : array();
|
||||
$league_ids = isset( $source['league_id'] ) ? tse_sp_event_export_parse_id_list( wp_unslash( $source['league_id'] ) ) : array();
|
||||
$field_ids = isset( $source['field_id'] ) ? tse_sp_event_export_parse_id_list( wp_unslash( $source['field_id'] ) ) : array();
|
||||
$title_format = isset( $source['title_format'] ) ? tse_sp_event_export_sanitize_title_format( wp_unslash( $source['title_format'] ) ) : 'selected_first';
|
||||
|
||||
return array(
|
||||
'team_id' => isset( $team_ids[0] ) ? $team_ids[0] : 0,
|
||||
@@ -190,6 +205,7 @@ function tse_sp_event_export_normalize_request_args( $source = null ) {
|
||||
'field_id' => isset( $field_ids[0] ) ? $field_ids[0] : 0,
|
||||
'field_ids' => $field_ids,
|
||||
'format' => $format,
|
||||
'title_format' => $title_format,
|
||||
'columns' => isset( $source['columns'] ) ? tse_sp_event_export_sanitize_columns( $format, wp_unslash( $source['columns'] ) ) : tse_sp_event_export_get_default_columns( $format ),
|
||||
);
|
||||
}
|
||||
@@ -212,9 +228,6 @@ function tse_sp_event_export_validate_filters( $filters ) {
|
||||
wp_die( esc_html__( 'Team format requires a team filter.', 'tonys-sportspress-enhancements' ), '', array( 'response' => 400 ) );
|
||||
}
|
||||
|
||||
if ( count( $team_ids ) > 1 ) {
|
||||
wp_die( esc_html__( 'Team format does not support multiple teams.', 'tonys-sportspress-enhancements' ), '', array( 'response' => 400 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,11 +307,10 @@ function tse_sp_event_export_query_posts( $filters ) {
|
||||
* @return array
|
||||
*/
|
||||
function tse_sp_event_export_get_events( $filters ) {
|
||||
$team_id = isset( $filters['team_id'] ) ? absint( $filters['team_id'] ) : 0;
|
||||
$selected_ids = isset( $filters['team_ids'] ) && is_array( $filters['team_ids'] ) ? array_values( array_filter( array_map( 'absint', $filters['team_ids'] ) ) ) : array();
|
||||
$title_format = tse_sp_event_export_sanitize_title_format( isset( $filters['title_format'] ) ? $filters['title_format'] : 'selected_first' );
|
||||
$query_posts = tse_sp_event_export_query_posts( $filters );
|
||||
$events = array();
|
||||
$team_name = $team_id > 0 ? get_the_title( $team_id ) : '';
|
||||
|
||||
foreach ( $query_posts as $event ) {
|
||||
$event_id = $event instanceof WP_Post ? (int) $event->ID : 0;
|
||||
@@ -314,21 +326,22 @@ function tse_sp_event_export_get_events( $filters ) {
|
||||
$home_id = isset( $teams[0] ) ? (int) $teams[0] : 0;
|
||||
$away_id = isset( $teams[1] ) ? (int) $teams[1] : 0;
|
||||
$venue = tse_sp_event_export_get_primary_field( $event_id );
|
||||
$context = tse_sp_event_export_get_team_context( $home_id, $away_id, $selected_ids );
|
||||
|
||||
if ( $team_id > 0 ) {
|
||||
$location_flag = $home_id === $team_id ? 'Home' : 'Away';
|
||||
$opponent_id = $home_id === $team_id ? $away_id : $home_id;
|
||||
} else {
|
||||
$location_flag = '';
|
||||
$opponent_id = 0;
|
||||
}
|
||||
$context_team_id = isset( $context['team_id'] ) ? (int) $context['team_id'] : 0;
|
||||
$opponent_id = isset( $context['opponent_id'] ) ? (int) $context['opponent_id'] : 0;
|
||||
$separator = isset( $context['separator'] ) ? (string) $context['separator'] : '';
|
||||
$location_flag = isset( $context['location_flag'] ) ? (string) $context['location_flag'] : '';
|
||||
$title = tse_sp_event_export_get_event_title_value( $home_id, $away_id, $selected_ids, $title_format );
|
||||
|
||||
$events[] = array(
|
||||
'event_id' => $event_id,
|
||||
'label' => '',
|
||||
'date' => get_post_time( 'm/d/Y', false, $event_id, true ),
|
||||
'time' => strtoupper( (string) ( function_exists( 'sp_get_time' ) ? sp_get_time( $event_id ) : get_post_time( get_option( 'time_format' ), false, $event_id, true ) ) ),
|
||||
'team_name' => is_string( $team_name ) ? $team_name : '',
|
||||
'title' => $title,
|
||||
'team_name' => $context_team_id > 0 ? get_the_title( $context_team_id ) : '',
|
||||
'separator' => $separator,
|
||||
'opponent_name' => $opponent_id > 0 ? get_the_title( $opponent_id ) : '',
|
||||
'location_flag' => $location_flag,
|
||||
'home_team' => $home_id > 0 ? get_the_title( $home_id ) : '',
|
||||
@@ -352,6 +365,100 @@ function tse_sp_event_export_get_events( $filters ) {
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a display title for a schedule event.
|
||||
*
|
||||
* @param int $home_id Home team ID.
|
||||
* @param int $away_id Away team ID.
|
||||
* @param int[] $selected_ids Selected team IDs.
|
||||
* @param string $title_format Title format.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_event_export_get_event_title_value( $home_id, $away_id, $selected_ids, $title_format ) {
|
||||
$home_id = absint( $home_id );
|
||||
$away_id = absint( $away_id );
|
||||
$selected_ids = array_values( array_filter( array_map( 'absint', (array) $selected_ids ) ) );
|
||||
$title_format = tse_sp_event_export_sanitize_title_format( $title_format );
|
||||
|
||||
if ( 'matchup' === $title_format ) {
|
||||
return tse_sp_event_export_join_title_parts( $away_id, 'at', $home_id );
|
||||
}
|
||||
|
||||
$context = tse_sp_event_export_get_team_context( $home_id, $away_id, $selected_ids );
|
||||
if ( empty( $context['team_id'] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( 1 === count( $selected_ids ) ) {
|
||||
$opponent_id = isset( $context['opponent_id'] ) ? (int) $context['opponent_id'] : 0;
|
||||
return $opponent_id > 0 ? get_the_title( $opponent_id ) : '';
|
||||
}
|
||||
|
||||
return tse_sp_event_export_join_title_parts(
|
||||
isset( $context['team_id'] ) ? (int) $context['team_id'] : 0,
|
||||
isset( $context['separator'] ) ? (string) $context['separator'] : '',
|
||||
isset( $context['opponent_id'] ) ? (int) $context['opponent_id'] : 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join two team names with a title separator.
|
||||
*
|
||||
* @param int $first_id First team ID.
|
||||
* @param string $separator Separator.
|
||||
* @param int $second_id Second team ID.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_event_export_join_title_parts( $first_id, $separator, $second_id ) {
|
||||
$first_name = $first_id > 0 ? get_the_title( $first_id ) : '';
|
||||
$second_name = $second_id > 0 ? get_the_title( $second_id ) : '';
|
||||
$parts = array_values( array_filter( array( $first_name, trim( $separator ), $second_name ), 'strlen' ) );
|
||||
|
||||
return implode( ' ', $parts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the team-layout perspective for an event.
|
||||
*
|
||||
* The selected team is always first. If both selected teams are in the game,
|
||||
* use the away team first and the home team second.
|
||||
*
|
||||
* @param int $home_id Home team ID.
|
||||
* @param int $away_id Away team ID.
|
||||
* @param int[] $selected_ids Selected team IDs.
|
||||
* @return array
|
||||
*/
|
||||
function tse_sp_event_export_get_team_context( $home_id, $away_id, $selected_ids ) {
|
||||
$home_id = absint( $home_id );
|
||||
$away_id = absint( $away_id );
|
||||
$selected_ids = array_values( array_filter( array_map( 'absint', (array) $selected_ids ) ) );
|
||||
|
||||
if ( $away_id > 0 && in_array( $away_id, $selected_ids, true ) ) {
|
||||
return array(
|
||||
'team_id' => $away_id,
|
||||
'opponent_id' => $home_id,
|
||||
'separator' => 'at',
|
||||
'location_flag' => 'Away',
|
||||
);
|
||||
}
|
||||
|
||||
if ( $home_id > 0 && in_array( $home_id, $selected_ids, true ) ) {
|
||||
return array(
|
||||
'team_id' => $home_id,
|
||||
'opponent_id' => $away_id,
|
||||
'separator' => 'vs',
|
||||
'location_flag' => 'Home',
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'team_id' => 0,
|
||||
'opponent_id' => 0,
|
||||
'separator' => '',
|
||||
'location_flag' => '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event term names as a semicolon-delimited string.
|
||||
*
|
||||
@@ -478,23 +585,20 @@ function tse_sp_event_export_fold_ical_line( $line ) {
|
||||
function tse_sp_event_export_get_ical_summary( $event, $filters ) {
|
||||
$format = tse_sp_event_export_sanitize_format( isset( $filters['format'] ) ? $filters['format'] : 'matchup' );
|
||||
$team_ids = isset( $filters['team_ids'] ) && is_array( $filters['team_ids'] ) ? array_values( array_filter( array_map( 'absint', $filters['team_ids'] ) ) ) : array();
|
||||
$title_format = tse_sp_event_export_sanitize_title_format( isset( $filters['title_format'] ) ? $filters['title_format'] : 'selected_first' );
|
||||
$team_id = isset( $team_ids[0] ) ? $team_ids[0] : 0;
|
||||
|
||||
if ( 'team' === $format && $team_id > 0 ) {
|
||||
$teams = array_values( array_unique( array_map( 'intval', get_post_meta( $event->ID, 'sp_team', false ) ) ) );
|
||||
$home_id = isset( $teams[0] ) ? (int) $teams[0] : 0;
|
||||
$away_id = isset( $teams[1] ) ? (int) $teams[1] : 0;
|
||||
$context = tse_sp_event_export_get_team_context( $home_id, $away_id, $team_ids );
|
||||
|
||||
if ( in_array( $team_id, $teams, true ) ) {
|
||||
$is_home = $home_id === $team_id;
|
||||
$opponent_id = $is_home ? $away_id : $home_id;
|
||||
$opponent = $opponent_id > 0 ? get_the_title( $opponent_id ) : __( 'TBD', 'tonys-sportspress-enhancements' );
|
||||
$summary = sprintf(
|
||||
/* translators: 1: preposition, 2: opponent name. */
|
||||
__( '%1$s %2$s', 'tonys-sportspress-enhancements' ),
|
||||
$is_home ? 'vs' : 'at',
|
||||
$opponent
|
||||
);
|
||||
if ( ! empty( $context['team_id'] ) ) {
|
||||
$summary = tse_sp_event_export_get_event_title_value( $home_id, $away_id, $team_ids, $title_format );
|
||||
if ( '' === $summary ) {
|
||||
$summary = $event->post_title;
|
||||
}
|
||||
|
||||
return apply_filters( 'sportspress_ical_feed_summary', $summary, $event );
|
||||
}
|
||||
@@ -921,6 +1025,7 @@ function tse_sp_event_export_get_feed_url( $args = array(), $feed_type = 'csv' )
|
||||
'season_id' => ! empty( $filters['season_ids'] ) ? implode( ',', $filters['season_ids'] ) : '',
|
||||
'league_id' => ! empty( $filters['league_ids'] ) ? implode( ',', $filters['league_ids'] ) : '',
|
||||
'field_id' => ! empty( $filters['field_ids'] ) ? implode( ',', $filters['field_ids'] ) : '',
|
||||
'title_format' => isset( $filters['title_format'] ) ? tse_sp_event_export_sanitize_title_format( $filters['title_format'] ) : 'selected_first',
|
||||
'columns' => implode( ',', $filters['columns'] ),
|
||||
);
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$vars[] = 'sp_field';
|
||||
$vars[] = 'team_label';
|
||||
$vars[] = 'field_label';
|
||||
$vars[] = 'title_format';
|
||||
$vars[] = 'paper';
|
||||
$vars[] = 'autoprint';
|
||||
$vars[] = 'month_pages';
|
||||
@@ -444,13 +445,12 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
|
||||
echo '<div class="tse-printable-url-builder" style="max-width:1100px;margin-top:28px;padding:20px 24px;border:1px solid #dcdcde;background:#fff;">';
|
||||
echo '<h2 style="margin-top:0;">' . esc_html__( 'Printable Calendar URL Builder', 'tonys-sportspress-enhancements' ) . '</h2>';
|
||||
echo '<p>' . esc_html__( 'Build a shareable printable calendar URL with team, season, league, paper size, and optional auto-print.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
echo '<p>' . esc_html__( 'Build a shareable printable calendar URL with teams, season, league, field, label formats, paper size, and optional auto-print.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
|
||||
echo '<table class="form-table" role="presentation"><tbody>';
|
||||
|
||||
echo '<tr><th scope="row"><label for="tse-printable-builder-team">' . esc_html__( 'Team', 'tonys-sportspress-enhancements' ) . '</label></th><td>';
|
||||
echo '<select id="tse-printable-builder-team" style="min-width:280px;">';
|
||||
echo '<option value="0">' . esc_html__( 'Choose a team', 'tonys-sportspress-enhancements' ) . '</option>';
|
||||
echo '<select id="tse-printable-builder-team" multiple="multiple" size="' . esc_attr( (string) min( 8, max( 3, count( $teams ) ) ) ) . '" style="min-width:280px;">';
|
||||
foreach ( $teams as $team ) {
|
||||
if ( ! $team instanceof WP_Post ) {
|
||||
continue;
|
||||
@@ -458,6 +458,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
echo '<option value="' . esc_attr( (string) $team->ID ) . '">' . esc_html( $team->post_title ) . '</option>';
|
||||
}
|
||||
echo '</select>';
|
||||
echo '<p class="description">' . esc_html__( 'Select one or more teams. Multiple teams create a combined matchup calendar.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
echo '</td></tr>';
|
||||
|
||||
echo '<tr><th scope="row"><label for="tse-printable-builder-season">' . esc_html__( 'Season', 'tonys-sportspress-enhancements' ) . '</label></th><td>';
|
||||
@@ -520,6 +521,14 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
echo '</select>';
|
||||
echo '</td></tr>';
|
||||
|
||||
echo '<tr><th scope="row"><label for="tse-printable-builder-title-format">' . esc_html__( 'Title Format', 'tonys-sportspress-enhancements' ) . '</label></th><td>';
|
||||
echo '<select id="tse-printable-builder-title-format" style="min-width:280px;">';
|
||||
foreach ( $this->get_title_format_options() as $format => $label ) {
|
||||
echo '<option value="' . esc_attr( $format ) . '">' . esc_html( $label ) . '</option>';
|
||||
}
|
||||
echo '</select>';
|
||||
echo '</td></tr>';
|
||||
|
||||
echo '<tr><th scope="row">' . esc_html__( 'Options', 'tonys-sportspress-enhancements' ) . '</th><td>';
|
||||
echo '<label for="tse-printable-builder-autoprint" style="display:inline-flex;align-items:center;gap:6px;">';
|
||||
echo '<input id="tse-printable-builder-autoprint" type="checkbox" value="1" />';
|
||||
@@ -542,7 +551,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
echo '</button>';
|
||||
echo '</div>';
|
||||
echo '<p><a id="tse-printable-builder-open" class="button button-primary" href="' . esc_url( home_url( '/' ) ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Open Printable URL', 'tonys-sportspress-enhancements' ) . '</a></p>';
|
||||
echo '<p class="description">' . esc_html__( 'The printable route requires a single team selection.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
echo '<p class="description">' . esc_html__( 'The printable route requires at least one selected team.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
echo '</div>';
|
||||
|
||||
$this->render_printable_url_builder_script();
|
||||
@@ -573,18 +582,32 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
var paper = root.querySelector('#tse-printable-builder-paper');
|
||||
var teamLabel = root.querySelector('#tse-printable-builder-team-label');
|
||||
var fieldLabel = root.querySelector('#tse-printable-builder-field-label');
|
||||
var titleFormat = root.querySelector('#tse-printable-builder-title-format');
|
||||
var autoprint = root.querySelector('#tse-printable-builder-autoprint');
|
||||
var monthPages = root.querySelector('#tse-printable-builder-month-pages');
|
||||
var output = root.querySelector('#tse-printable-builder-output');
|
||||
var copyButton = root.querySelector('#tse-printable-builder-copy');
|
||||
var openLink = root.querySelector('#tse-printable-builder-open');
|
||||
|
||||
function selectedValues(select) {
|
||||
if (!select) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.prototype.slice.call(select.selectedOptions || []).map(function(option){
|
||||
return option.value;
|
||||
}).filter(function(value){
|
||||
return value && value !== '0';
|
||||
});
|
||||
}
|
||||
|
||||
function buildUrl() {
|
||||
var url = new URL(baseUrl, window.location.origin);
|
||||
var teamValues = selectedValues(team);
|
||||
url.searchParams.set(queryFlag, '1');
|
||||
|
||||
if (team.value && team.value !== '0') {
|
||||
url.searchParams.set('sp_team', team.value);
|
||||
if (teamValues.length) {
|
||||
url.searchParams.set('sp_team', teamValues.join(','));
|
||||
} else {
|
||||
url.searchParams.delete('sp_team');
|
||||
}
|
||||
@@ -619,6 +642,10 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
url.searchParams.set('field_label', fieldLabel.value);
|
||||
}
|
||||
|
||||
if (titleFormat.value) {
|
||||
url.searchParams.set('title_format', titleFormat.value);
|
||||
}
|
||||
|
||||
if (autoprint.checked) {
|
||||
url.searchParams.set('autoprint', '1');
|
||||
} else {
|
||||
@@ -633,10 +660,10 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
|
||||
output.value = url.toString();
|
||||
openLink.href = url.toString();
|
||||
openLink.toggleAttribute('disabled', !(team.value && team.value !== '0'));
|
||||
openLink.toggleAttribute('disabled', !teamValues.length);
|
||||
}
|
||||
|
||||
[team, season, league, field, paper, teamLabel, fieldLabel, autoprint, monthPages].forEach(function(input){
|
||||
[team, season, league, field, paper, teamLabel, fieldLabel, titleFormat, autoprint, monthPages].forEach(function(input){
|
||||
input.addEventListener('change', buildUrl);
|
||||
});
|
||||
|
||||
@@ -705,6 +732,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$field_ids = $this->parse_term_ids( get_query_var( 'sp_field' ), 'sp_venue' );
|
||||
$team_label_mode = $this->sanitize_label_mode( get_query_var( 'team_label' ), 'abbreviation' );
|
||||
$field_label_mode = $this->sanitize_label_mode( get_query_var( 'field_label' ), $this->get_venue_label_mode() );
|
||||
$title_format = $this->sanitize_title_format( get_query_var( 'title_format' ) );
|
||||
|
||||
$paper = $this->normalize_paper_size( (string) get_query_var( 'paper' ) );
|
||||
$autoprint = '1' === (string) get_query_var( 'autoprint' );
|
||||
@@ -719,7 +747,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$qr_url = 'https://api.qrserver.com/v1/create-qr-code/?size=144x144&data=' . rawurlencode( $site_url );
|
||||
$season_name = '';
|
||||
$field_name = count( $field_ids ) === 1 ? $this->get_term_label( (int) $field_ids[0], 'sp_venue', $field_label_mode ) : '';
|
||||
$entries = $this->get_schedule_entries( $team_ids, $season_id, $league_id, $field_ids, $team_label_mode, $field_label_mode );
|
||||
$entries = $this->get_schedule_entries( $team_ids, $season_id, $league_id, $field_ids, $team_label_mode, $field_label_mode, $title_format );
|
||||
$team_palette = $is_multi_team ? $this->get_default_printable_palette() : $this->get_team_color_palette( $primary_team_id );
|
||||
$team_primary_for_fields = $is_multi_team ? '' : $this->get_strict_team_primary_color( $primary_team_id );
|
||||
$entries_by_day = array();
|
||||
@@ -897,7 +925,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
* @param string $paper Paper size.
|
||||
* @return string
|
||||
*/
|
||||
private function build_url( $team_id, $season_id, $paper, $league_id = 0, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = '' ) {
|
||||
private function build_url( $team_id, $season_id, $paper, $league_id = 0, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = '', $title_format = 'selected_first' ) {
|
||||
$paper = $this->normalize_paper_size( $paper );
|
||||
$field_label_mode = '' === $field_label_mode ? $this->get_venue_label_mode() : $field_label_mode;
|
||||
|
||||
@@ -910,6 +938,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
'sp_field' => $field_id > 0 ? (string) absint( $field_id ) : '',
|
||||
'team_label' => $this->sanitize_label_mode( $team_label_mode, 'name' ),
|
||||
'field_label' => $this->sanitize_label_mode( $field_label_mode, $this->get_venue_label_mode() ),
|
||||
'title_format' => $this->sanitize_title_format( $title_format ),
|
||||
'paper' => (string) $paper,
|
||||
'month_pages' => $month_pages ? '1' : '',
|
||||
),
|
||||
@@ -1124,6 +1153,31 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
return $this->sanitize_label_mode( $value, 'name' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported event title formats.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_title_format_options() {
|
||||
return array(
|
||||
'selected_first' => __( 'Selected Teams First', 'tonys-sportspress-enhancements' ),
|
||||
'matchup' => __( 'Matchup', 'tonys-sportspress-enhancements' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize event title format.
|
||||
*
|
||||
* @param mixed $value Raw value.
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_title_format( $value ) {
|
||||
$format = is_string( $value ) ? sanitize_key( $value ) : '';
|
||||
$options = array_keys( $this->get_title_format_options() );
|
||||
|
||||
return in_array( $format, $options, true ) ? $format : 'selected_first';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether SportsPress is available.
|
||||
*
|
||||
@@ -1384,13 +1438,14 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
* @param int[] $field_ids Field IDs.
|
||||
* @return array
|
||||
*/
|
||||
private function get_schedule_entries( $team_ids, $season_id, $league_id = 0, $field_ids = array(), $team_label_mode = 'abbreviation', $field_label_mode = '' ) {
|
||||
private function get_schedule_entries( $team_ids, $season_id, $league_id = 0, $field_ids = array(), $team_label_mode = 'abbreviation', $field_label_mode = '', $title_format = 'selected_first' ) {
|
||||
$team_ids = is_array( $team_ids ) ? array_values( array_filter( array_map( 'absint', $team_ids ) ) ) : array( absint( $team_ids ) );
|
||||
$primary_team = isset( $team_ids[0] ) ? (int) $team_ids[0] : 0;
|
||||
$is_multi_team = count( $team_ids ) > 1;
|
||||
$field_ids = is_array( $field_ids ) ? array_values( array_filter( array_map( 'absint', $field_ids ) ) ) : array();
|
||||
$team_label_mode = $this->sanitize_label_mode( $team_label_mode, 'abbreviation' );
|
||||
$field_label_mode = '' === $field_label_mode ? $this->get_venue_label_mode() : $this->sanitize_label_mode( $field_label_mode, $this->get_venue_label_mode() );
|
||||
$title_format = $this->sanitize_title_format( $title_format );
|
||||
|
||||
if ( empty( $team_ids ) ) {
|
||||
return array();
|
||||
@@ -1478,6 +1533,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$title_data = $this->get_event_title_data( $home_id, $away_id, $team_ids, $team_label_mode, $title_format );
|
||||
|
||||
$venue = $this->get_event_venue_term( $event_id );
|
||||
$venue_name = '';
|
||||
@@ -1495,9 +1551,12 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
'month_key' => wp_date( 'Y-m', $timestamp ),
|
||||
'timestamp' => $timestamp,
|
||||
'is_home' => ! $is_multi_team && $home_id === $context_id,
|
||||
'is_matchup' => $is_multi_team,
|
||||
'is_matchup' => 'matchup' === $title_format,
|
||||
'opponent_id' => $opponent_id,
|
||||
'opponent_name' => $opponent_id > 0 ? $this->get_team_label( $opponent_id, $team_label_mode ) : __( 'TBD', 'tonys-sportspress-enhancements' ),
|
||||
'title_team_name' => $title_data['team_name'],
|
||||
'title_separator' => $title_data['separator'],
|
||||
'title_opponent_name' => $title_data['opponent_name'],
|
||||
'home_team_id' => $home_id,
|
||||
'away_team_id' => $away_id,
|
||||
'home_team_name' => $home_id > 0 ? $this->get_team_label( $home_id, $team_label_mode ) : __( 'TBD', 'tonys-sportspress-enhancements' ),
|
||||
@@ -1547,6 +1606,91 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
return $months;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event title parts for the selected title format.
|
||||
*
|
||||
* @param int $home_id Home team ID.
|
||||
* @param int $away_id Away team ID.
|
||||
* @param int[] $selected_ids Selected team IDs.
|
||||
* @param string $team_label_mode Team label mode.
|
||||
* @param string $title_format Title format.
|
||||
* @return array
|
||||
*/
|
||||
private function get_event_title_data( $home_id, $away_id, $selected_ids, $team_label_mode, $title_format ) {
|
||||
$home_id = absint( $home_id );
|
||||
$away_id = absint( $away_id );
|
||||
$selected_ids = array_values( array_filter( array_map( 'absint', (array) $selected_ids ) ) );
|
||||
$title_format = $this->sanitize_title_format( $title_format );
|
||||
|
||||
if ( 'matchup' === $title_format ) {
|
||||
return array(
|
||||
'team_name' => $away_id > 0 ? $this->get_team_label( $away_id, $team_label_mode ) : __( 'TBD', 'tonys-sportspress-enhancements' ),
|
||||
'separator' => 'at',
|
||||
'opponent_name' => $home_id > 0 ? $this->get_team_label( $home_id, $team_label_mode ) : __( 'TBD', 'tonys-sportspress-enhancements' ),
|
||||
);
|
||||
}
|
||||
|
||||
$context = $this->get_selected_team_context( $home_id, $away_id, $selected_ids );
|
||||
if ( empty( $context['team_id'] ) ) {
|
||||
return array(
|
||||
'team_name' => '',
|
||||
'separator' => '',
|
||||
'opponent_name' => '',
|
||||
);
|
||||
}
|
||||
|
||||
$opponent_id = isset( $context['opponent_id'] ) ? (int) $context['opponent_id'] : 0;
|
||||
if ( 1 === count( $selected_ids ) ) {
|
||||
return array(
|
||||
'team_name' => '',
|
||||
'separator' => '',
|
||||
'opponent_name' => $opponent_id > 0 ? $this->get_team_label( $opponent_id, $team_label_mode ) : __( 'TBD', 'tonys-sportspress-enhancements' ),
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'team_name' => $this->get_team_label( (int) $context['team_id'], $team_label_mode ),
|
||||
'separator' => isset( $context['separator'] ) ? (string) $context['separator'] : '',
|
||||
'opponent_name' => $opponent_id > 0 ? $this->get_team_label( $opponent_id, $team_label_mode ) : __( 'TBD', 'tonys-sportspress-enhancements' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selected-team perspective for an event.
|
||||
*
|
||||
* @param int $home_id Home team ID.
|
||||
* @param int $away_id Away team ID.
|
||||
* @param int[] $selected_ids Selected team IDs.
|
||||
* @return array
|
||||
*/
|
||||
private function get_selected_team_context( $home_id, $away_id, $selected_ids ) {
|
||||
$home_id = absint( $home_id );
|
||||
$away_id = absint( $away_id );
|
||||
$selected_ids = array_values( array_filter( array_map( 'absint', (array) $selected_ids ) ) );
|
||||
|
||||
if ( $away_id > 0 && in_array( $away_id, $selected_ids, true ) ) {
|
||||
return array(
|
||||
'team_id' => $away_id,
|
||||
'opponent_id' => $home_id,
|
||||
'separator' => 'at',
|
||||
);
|
||||
}
|
||||
|
||||
if ( $home_id > 0 && in_array( $home_id, $selected_ids, true ) ) {
|
||||
return array(
|
||||
'team_id' => $home_id,
|
||||
'opponent_id' => $away_id,
|
||||
'separator' => 'vs',
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'team_id' => 0,
|
||||
'opponent_id' => 0,
|
||||
'separator' => '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a single month grid.
|
||||
*
|
||||
@@ -1585,7 +1729,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$day_entries = isset( $entries_by_day[ $day_key ] ) ? $entries_by_day[ $day_key ] : array();
|
||||
$has_matchup = false;
|
||||
foreach ( $day_entries as $day_entry ) {
|
||||
if ( ! empty( $day_entry['is_matchup'] ) || $is_multi_team ) {
|
||||
if ( ! empty( $day_entry['is_matchup'] ) || ! empty( $day_entry['title_team_name'] ) ) {
|
||||
$has_matchup = true;
|
||||
break;
|
||||
}
|
||||
@@ -1599,7 +1743,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
if ( ! empty( $day_entries ) ) {
|
||||
$first_entry = $day_entries[0];
|
||||
$first_is_home = ! empty( $first_entry['is_home'] );
|
||||
$first_is_matchup = ! empty( $first_entry['is_matchup'] ) || $is_multi_team;
|
||||
$first_is_matchup = ! empty( $first_entry['is_matchup'] ) || ! empty( $first_entry['title_team_name'] );
|
||||
$first_venue_key = isset( $first_entry['venue_key'] ) && is_string( $first_entry['venue_key'] ) ? $first_entry['venue_key'] : '';
|
||||
$first_venue_color = ( '' !== $first_venue_key && isset( $venue_colors[ $first_venue_key ]['color'] ) ) ? (string) $venue_colors[ $first_venue_key ]['color'] : '';
|
||||
$first_background = '' !== $first_venue_color ? $first_venue_color : ( $first_is_home || $first_is_matchup ? $team_palette['primary'] : $team_palette['secondary'] );
|
||||
@@ -1617,14 +1761,15 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
echo '<div class="events-stack" style="--event-count:' . esc_attr( (string) count( $day_entries ) ) . ';">';
|
||||
foreach ( $day_entries as $entry ) {
|
||||
$is_home = ! empty( $entry['is_home'] );
|
||||
$is_matchup = ! empty( $entry['is_matchup'] ) || $is_multi_team;
|
||||
$event_class = $is_matchup ? 'matchup' : ( $is_home ? 'h' : 'a' );
|
||||
$is_matchup = ! empty( $entry['is_matchup'] );
|
||||
$uses_split_title = $is_matchup || ! empty( $entry['title_team_name'] );
|
||||
$event_class = $uses_split_title ? 'matchup' : ( $is_home ? 'h' : 'a' );
|
||||
$venue_key = isset( $entry['venue_key'] ) && is_string( $entry['venue_key'] ) ? $entry['venue_key'] : '';
|
||||
$venue_color = ( '' !== $venue_key && isset( $venue_colors[ $venue_key ]['color'] ) ) ? (string) $venue_colors[ $venue_key ]['color'] : '';
|
||||
$opponent_id = isset( $entry['opponent_id'] ) ? (int) $entry['opponent_id'] : 0;
|
||||
$logo = ( ! $is_matchup && $opponent_id > 0 ) ? get_the_post_thumbnail( $opponent_id, 'medium', array( 'class' => 'event-logo-img', 'loading' => 'eager', 'decoding' => 'async' ) ) : '';
|
||||
$logo = ( ! $uses_split_title && $opponent_id > 0 ) ? get_the_post_thumbnail( $opponent_id, 'medium', array( 'class' => 'event-logo-img', 'loading' => 'eager', 'decoding' => 'async' ) ) : '';
|
||||
$has_logo = '' !== $logo;
|
||||
$event_background = '' !== $venue_color ? $venue_color : ( $is_home || $is_matchup ? $team_palette['primary'] : $team_palette['secondary'] );
|
||||
$event_background = '' !== $venue_color ? $venue_color : ( $is_home || $uses_split_title ? $team_palette['primary'] : $team_palette['secondary'] );
|
||||
$event_foreground = $this->get_readable_text_color( $event_background );
|
||||
$event_background = $this->ensure_minimum_contrast( $event_background, $event_foreground, self::MIN_WHITE_CONTRAST );
|
||||
$event_foreground = $this->get_readable_text_color( $event_background );
|
||||
@@ -1635,16 +1780,17 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
if ( $has_logo ) {
|
||||
echo wp_kses_post( $logo );
|
||||
} else {
|
||||
if ( $is_matchup ) {
|
||||
$away_name = isset( $entry['away_team_name'] ) ? (string) $entry['away_team_name'] : __( 'TBD', 'tonys-sportspress-enhancements' );
|
||||
$home_name = isset( $entry['home_team_name'] ) ? (string) $entry['home_team_name'] : __( 'TBD', 'tonys-sportspress-enhancements' );
|
||||
echo '<span class="event-name matchup-name"><span class="matchup-team away-team">' . esc_html( $away_name ) . '</span><span class="matchup-vs">' . esc_html__( 'vs', 'tonys-sportspress-enhancements' ) . '</span><span class="matchup-team home-team">' . esc_html( $home_name ) . '</span></span>';
|
||||
if ( $uses_split_title ) {
|
||||
$team_name = isset( $entry['title_team_name'] ) ? (string) $entry['title_team_name'] : __( 'TBD', 'tonys-sportspress-enhancements' );
|
||||
$separator = isset( $entry['title_separator'] ) ? (string) $entry['title_separator'] : 'at';
|
||||
$opponent_name = isset( $entry['title_opponent_name'] ) ? (string) $entry['title_opponent_name'] : __( 'TBD', 'tonys-sportspress-enhancements' );
|
||||
echo '<span class="event-name matchup-name"><span class="matchup-team away-team">' . esc_html( $team_name ) . '</span><span class="matchup-vs">' . esc_html( $separator ) . '</span><span class="matchup-team home-team">' . esc_html( $opponent_name ) . '</span></span>';
|
||||
} else {
|
||||
echo '<span class="event-name">' . esc_html( isset( $entry['opponent_name'] ) ? (string) $entry['opponent_name'] : '' ) . '</span>';
|
||||
echo '<span class="event-name">' . esc_html( isset( $entry['title_opponent_name'] ) ? (string) $entry['title_opponent_name'] : '' ) . '</span>';
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
if ( ! $is_matchup ) {
|
||||
if ( ! $uses_split_title ) {
|
||||
echo '<span class="ha-flag">' . esc_html( $is_home ? 'H' : 'A' ) . '</span>';
|
||||
}
|
||||
echo '<div class="event-meta">';
|
||||
|
||||
@@ -91,9 +91,7 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
$field_id = tse_sp_schedule_exporter_resolve_field_id( $fields );
|
||||
$export_type = tse_sp_schedule_exporter_resolve_export_type();
|
||||
$subformat = tse_sp_schedule_exporter_resolve_subformat();
|
||||
if ( 'team' === $subformat && count( $team_ids ) > 1 ) {
|
||||
$subformat = 'matchup';
|
||||
}
|
||||
$title_format = tse_sp_schedule_exporter_resolve_title_format();
|
||||
|
||||
if ( empty( $teams ) ) {
|
||||
return '<p>' . esc_html__( 'No SportsPress teams match the selected league and season.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
@@ -118,6 +116,15 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
<p class="description"><?php esc_html_e( 'CSV builds a feed URL, iCal Link builds a subscription URL, and Printable opens the printable page.', 'tonys-sportspress-enhancements' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div data-title-format-wrap="1" style="margin-bottom:16px;">
|
||||
<label for="tse-public-title-format"><strong><?php esc_html_e( 'Title Format', 'tonys-sportspress-enhancements' ); ?></strong></label><br />
|
||||
<select id="tse-public-title-format" name="title_format">
|
||||
<option value="selected_first" <?php selected( $title_format, 'selected_first' ); ?>><?php esc_html_e( 'Selected Teams First', 'tonys-sportspress-enhancements' ); ?></option>
|
||||
<option value="matchup" <?php selected( $title_format, 'matchup' ); ?>><?php esc_html_e( 'Matchup', 'tonys-sportspress-enhancements' ); ?></option>
|
||||
</select>
|
||||
<p class="description"><?php esc_html_e( 'Selected Teams First shows only the opponent when one team is selected; Matchup always shows away at home.', 'tonys-sportspress-enhancements' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div data-subformat-wrap="1" style="margin-bottom:16px;">
|
||||
<label for="tse-public-subformat"><strong><?php esc_html_e( 'CSV Layout', 'tonys-sportspress-enhancements' ); ?></strong></label><br />
|
||||
<select id="tse-public-subformat" name="subformat">
|
||||
@@ -127,7 +134,7 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description"><?php esc_html_e( 'Matchup is away vs home. Team is opponent-based and requires one specific team.', 'tonys-sportspress-enhancements' ); ?></p>
|
||||
<p class="description"><?php esc_html_e( 'Matchup is away vs home. Team puts a selected team first with vs or at as the separator.', 'tonys-sportspress-enhancements' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
@@ -162,7 +169,7 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description"><?php esc_html_e( 'Select one or more teams. Multiple teams use the matchup CSV layout and a combined printable schedule.', 'tonys-sportspress-enhancements' ); ?></p>
|
||||
<p class="description"><?php esc_html_e( 'Select one or more teams. Team layout keeps one selected team first for each game.', 'tonys-sportspress-enhancements' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
@@ -190,9 +197,9 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
<?php tse_sp_schedule_exporter_render_column_picker( 'team', 'public', $subformat ); ?>
|
||||
|
||||
<?php
|
||||
$csv_url = tse_sp_event_export_get_feed_url( array( 'team_id' => $team_ids, 'season_id' => $season_id, 'league_id' => $league_id, 'field_id' => $field_id, 'format' => $subformat ), 'csv' );
|
||||
$ics_url = tse_sp_event_export_get_feed_url( array( 'team_id' => $team_ids, 'season_id' => $season_id, 'league_id' => $league_id, 'field_id' => $field_id ), 'ics' );
|
||||
$print_url = tse_sp_schedule_exporter_get_printable_url( $team_ids, $season_id, 'letter', $league_id, false, $field_id );
|
||||
$csv_url = tse_sp_event_export_get_feed_url( array( 'team_id' => $team_ids, 'season_id' => $season_id, 'league_id' => $league_id, 'field_id' => $field_id, 'format' => $subformat, 'title_format' => $title_format ), 'csv' );
|
||||
$ics_url = tse_sp_event_export_get_feed_url( array( 'team_id' => $team_ids, 'season_id' => $season_id, 'league_id' => $league_id, 'field_id' => $field_id, 'title_format' => $title_format ), 'ics' );
|
||||
$print_url = tse_sp_schedule_exporter_get_printable_url( $team_ids, $season_id, 'letter', $league_id, false, $field_id, false, 'name', 'name', $title_format );
|
||||
$current_url = tse_sp_schedule_exporter_get_output_url( $export_type, $csv_url, $ics_url, $print_url );
|
||||
?>
|
||||
<div style="display:flex;align-items:center;gap:8px;max-width:100%;margin-top:16px;">
|
||||
@@ -561,6 +568,29 @@ function tse_sp_schedule_exporter_resolve_subformat() {
|
||||
return tse_sp_event_export_sanitize_format( $requested );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve selected title format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_schedule_exporter_resolve_title_format() {
|
||||
$requested = isset( $_GET['title_format'] ) ? sanitize_key( wp_unslash( $_GET['title_format'] ) ) : 'selected_first';
|
||||
|
||||
return tse_sp_schedule_exporter_resolve_title_format_value( $requested );
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a title format value.
|
||||
*
|
||||
* @param string $value Raw value.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_schedule_exporter_resolve_title_format_value( $value ) {
|
||||
$value = sanitize_key( (string) $value );
|
||||
|
||||
return in_array( $value, array( 'selected_first', 'matchup' ), true ) ? $value : 'selected_first';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current output URL for the selected export type.
|
||||
*
|
||||
@@ -720,9 +750,10 @@ function tse_sp_schedule_exporter_get_primary_venue( $event_id ) {
|
||||
* @param int $league_id League ID.
|
||||
* @param string $team_label_mode Team label mode.
|
||||
* @param string $field_label_mode Field label mode.
|
||||
* @param string $title_format Title format.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $paper, $league_id = 0, $autoprint = false, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = 'name' ) {
|
||||
function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $paper, $league_id = 0, $autoprint = false, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = 'name', $title_format = 'selected_first' ) {
|
||||
$team_ids = is_array( $team_id ) ? array_values( array_filter( array_map( 'absint', $team_id ) ) ) : array( absint( $team_id ) );
|
||||
|
||||
return add_query_arg(
|
||||
@@ -734,6 +765,7 @@ function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $pape
|
||||
'sp_field' => $field_id > 0 ? (string) absint( $field_id ) : '',
|
||||
'team_label' => sanitize_key( (string) $team_label_mode ),
|
||||
'field_label' => sanitize_key( (string) $field_label_mode ),
|
||||
'title_format' => tse_sp_schedule_exporter_resolve_title_format_value( $title_format ),
|
||||
'paper' => $paper,
|
||||
'autoprint' => $autoprint ? '1' : '',
|
||||
'month_pages' => $month_pages ? '1' : '',
|
||||
@@ -787,6 +819,7 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
var team = form.querySelector('[name="team_id[]"], [name="team_id"]');
|
||||
var exportType = form.querySelector('[name="export_type"]');
|
||||
var subformat = form.querySelector('[name="subformat"]');
|
||||
var titleFormat = form.querySelector('[name="title_format"]');
|
||||
var field = form.querySelector('[name="field_id"]');
|
||||
var monthPages = form.querySelector('[name="month_pages"]');
|
||||
var outputUrl = scope.querySelector('.tse-output-url');
|
||||
@@ -806,12 +839,6 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
var teamValue = teamValues.length ? teamValues.join(',') : '0';
|
||||
var activeSubformat = subformat ? (subformat.value || 'matchup') : 'matchup';
|
||||
var selectedExportType = exportType ? (exportType.value || 'csv') : 'csv';
|
||||
if (teamValues.length > 1 && activeSubformat === 'team') {
|
||||
activeSubformat = 'matchup';
|
||||
if (subformat) {
|
||||
subformat.value = 'matchup';
|
||||
}
|
||||
}
|
||||
|
||||
scope.querySelectorAll('[data-column-group]').forEach(function(group){
|
||||
var visible = selectedExportType === 'csv' && group.getAttribute('data-column-group') === activeSubformat;
|
||||
@@ -833,6 +860,7 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
if (season) csvUrl.searchParams.set('season_id', season.value || '0');
|
||||
if (team) csvUrl.searchParams.set('team_id', teamValue);
|
||||
if (field) csvUrl.searchParams.set('field_id', field.value || '0');
|
||||
if (titleFormat) csvUrl.searchParams.set('title_format', titleFormat.value || 'selected_first');
|
||||
csvUrl.searchParams.set('format', activeSubformat);
|
||||
var columns = Array.prototype.slice.call(scope.querySelectorAll('[data-columns-format="' + activeSubformat + '"]:checked')).map(function(input){
|
||||
return input.value;
|
||||
@@ -849,6 +877,7 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
if (season) icsUrl.searchParams.set('season_id', season.value || '0');
|
||||
if (team) icsUrl.searchParams.set('team_id', teamValue);
|
||||
if (field) icsUrl.searchParams.set('field_id', field.value || '0');
|
||||
if (titleFormat) icsUrl.searchParams.set('title_format', titleFormat.value || 'selected_first');
|
||||
icsUrl.searchParams.delete('format');
|
||||
icsUrl.searchParams.delete('columns');
|
||||
}
|
||||
@@ -858,6 +887,7 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
if (season) printUrl.searchParams.set('sp_season', season.value || '0');
|
||||
if (team) printUrl.searchParams.set('sp_team', teamValue);
|
||||
if (field) printUrl.searchParams.set('sp_field', field.value || '0');
|
||||
if (titleFormat) printUrl.searchParams.set('title_format', titleFormat.value || 'selected_first');
|
||||
if (monthPages && monthPages.checked) {
|
||||
printUrl.searchParams.set('month_pages', '1');
|
||||
} else {
|
||||
@@ -884,7 +914,7 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
}
|
||||
} else if (selectedExportType === 'csv' && activeSubformat === 'team' && teamValue === '0') {
|
||||
disabled = true;
|
||||
note = 'CSV team layout requires one selected team.';
|
||||
note = 'CSV team layout requires at least one selected team.';
|
||||
}
|
||||
|
||||
if (outputUrl) {
|
||||
|
||||
@@ -112,6 +112,7 @@ class Test_SP_Schedule_Exporter extends WP_UnitTestCase {
|
||||
$this->assertSame( '90', $query['sp_field'] );
|
||||
$this->assertSame( 'name', $query['team_label'] );
|
||||
$this->assertSame( 'name', $query['field_label'] );
|
||||
$this->assertSame( 'selected_first', $query['title_format'] );
|
||||
$this->assertSame( '1', $query['month_pages'] );
|
||||
}
|
||||
|
||||
@@ -172,9 +173,94 @@ class Test_SP_Schedule_Exporter extends WP_UnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-team printable entries should return one matchup row per event.
|
||||
* Team CSV layout should support multiple selected teams with away-first context.
|
||||
*/
|
||||
public function test_printable_multi_team_entries_are_matchup_rows() {
|
||||
public function test_team_export_multiple_selected_teams_uses_away_team_first() {
|
||||
$home_id = $this->create_team( 'Home Team' );
|
||||
$away_id = $this->create_team( 'Away Team' );
|
||||
$this->create_event( $home_id, $away_id );
|
||||
|
||||
$events = tse_sp_event_export_get_events(
|
||||
array(
|
||||
'team_ids' => array( $home_id, $away_id ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertCount( 1, $events );
|
||||
$this->assertSame( 'Away Team', $events[0]['team_name'] );
|
||||
$this->assertSame( 'Away Team at Home Team', $events[0]['title'] );
|
||||
$this->assertSame( 'at', $events[0]['separator'] );
|
||||
$this->assertSame( 'Home Team', $events[0]['opponent_name'] );
|
||||
$this->assertSame( 'Away', $events[0]['location_flag'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Team CSV layout should use vs when the selected team is home.
|
||||
*/
|
||||
public function test_team_export_home_selected_team_uses_vs_separator() {
|
||||
$home_id = $this->create_team( 'Home Team' );
|
||||
$away_id = $this->create_team( 'Away Team' );
|
||||
$this->create_event( $home_id, $away_id );
|
||||
|
||||
$events = tse_sp_event_export_get_events(
|
||||
array(
|
||||
'team_ids' => array( $home_id ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertCount( 1, $events );
|
||||
$this->assertSame( 'Home Team', $events[0]['team_name'] );
|
||||
$this->assertSame( 'Away Team', $events[0]['title'] );
|
||||
$this->assertSame( 'vs', $events[0]['separator'] );
|
||||
$this->assertSame( 'Away Team', $events[0]['opponent_name'] );
|
||||
$this->assertSame( 'Home', $events[0]['location_flag'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Team CSV layout should use at when the selected team is away.
|
||||
*/
|
||||
public function test_team_export_away_selected_team_uses_at_separator() {
|
||||
$home_id = $this->create_team( 'Home Team' );
|
||||
$away_id = $this->create_team( 'Away Team' );
|
||||
$this->create_event( $home_id, $away_id );
|
||||
|
||||
$events = tse_sp_event_export_get_events(
|
||||
array(
|
||||
'team_ids' => array( $away_id ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertCount( 1, $events );
|
||||
$this->assertSame( 'Away Team', $events[0]['team_name'] );
|
||||
$this->assertSame( 'Home Team', $events[0]['title'] );
|
||||
$this->assertSame( 'at', $events[0]['separator'] );
|
||||
$this->assertSame( 'Home Team', $events[0]['opponent_name'] );
|
||||
$this->assertSame( 'Away', $events[0]['location_flag'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Matchup title format should ignore selected-team perspective.
|
||||
*/
|
||||
public function test_team_export_matchup_title_format_uses_away_at_home() {
|
||||
$home_id = $this->create_team( 'Home Team' );
|
||||
$away_id = $this->create_team( 'Away Team' );
|
||||
$this->create_event( $home_id, $away_id );
|
||||
|
||||
$events = tse_sp_event_export_get_events(
|
||||
array(
|
||||
'team_ids' => array( $home_id ),
|
||||
'title_format' => 'matchup',
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertCount( 1, $events );
|
||||
$this->assertSame( 'Away Team at Home Team', $events[0]['title'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-team printable entries should use selected-team-first titles by default.
|
||||
*/
|
||||
public function test_printable_multi_team_entries_use_selected_first_titles() {
|
||||
$home_id = $this->create_team( 'Home Team' );
|
||||
$away_id = $this->create_team( 'Away Team' );
|
||||
$venue_id = self::factory()->term->create( array( 'taxonomy' => 'sp_venue', 'name' => 'North Field' ) );
|
||||
@@ -187,9 +273,10 @@ class Test_SP_Schedule_Exporter extends WP_UnitTestCase {
|
||||
$entries = $method->invoke( $printable, array( $home_id, $away_id ), 0, 0, array() );
|
||||
|
||||
$this->assertCount( 1, $entries );
|
||||
$this->assertTrue( $entries[0]['is_matchup'] );
|
||||
$this->assertSame( 'Away Team', $entries[0]['away_team_name'] );
|
||||
$this->assertSame( 'Home Team', $entries[0]['home_team_name'] );
|
||||
$this->assertFalse( $entries[0]['is_matchup'] );
|
||||
$this->assertSame( 'Away Team', $entries[0]['title_team_name'] );
|
||||
$this->assertSame( 'at', $entries[0]['title_separator'] );
|
||||
$this->assertSame( 'Home Team', $entries[0]['title_opponent_name'] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user