Merge branch 'feature/multi-team-schedule-exporter'
This commit is contained in:
@@ -27,10 +27,7 @@ body {
|
||||
|
||||
.print-shell {
|
||||
margin: 0;
|
||||
width: calc(100% / var(--sheet-scale));
|
||||
background: #fff;
|
||||
transform-origin: top left;
|
||||
transform: scale(var(--sheet-scale));
|
||||
}
|
||||
|
||||
.print-page {
|
||||
@@ -48,7 +45,10 @@ body {
|
||||
}
|
||||
|
||||
body.print-preview .print-shell {
|
||||
flex: 0 0 auto;
|
||||
box-shadow: 0 10px 30px rgba(17, 24, 39, 0.2);
|
||||
transform-origin: top left;
|
||||
transform: scale(var(--sheet-scale));
|
||||
}
|
||||
|
||||
body.print-preview .print-shell.letter {
|
||||
@@ -60,6 +60,104 @@ body {
|
||||
width: 11in;
|
||||
min-height: 17in;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .print-shell,
|
||||
body.print-preview.month-pages .print-shell.letter,
|
||||
body.print-preview.month-pages .print-shell.ledger {
|
||||
width: auto;
|
||||
min-height: auto;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .print-page {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .month-page {
|
||||
box-sizing: border-box;
|
||||
width: 8.5in;
|
||||
min-height: 11in;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding: var(--pc-page-padding);
|
||||
background: #fff;
|
||||
box-shadow: 0 10px 30px rgba(17, 24, 39, 0.2);
|
||||
}
|
||||
|
||||
body.print-preview.month-pages.ledger .month-page {
|
||||
width: 11in;
|
||||
min-height: 17in;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .month-page + .month-page {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .month-page .header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .month-page .footer-meta {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .sheet-grid {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.print-preview.month-pages .month {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.month-pages .month-title {
|
||||
font-size: calc(26px * var(--month-font-scale));
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
body.month-pages .dow span {
|
||||
font-size: calc(12px * var(--month-font-scale));
|
||||
padding: 4px 2px;
|
||||
}
|
||||
|
||||
body.month-pages .day-num {
|
||||
font-size: calc(14px * var(--month-font-scale));
|
||||
}
|
||||
|
||||
body.month-pages .event-name {
|
||||
font-size: calc(13px * var(--month-font-scale));
|
||||
line-height: 0.98;
|
||||
}
|
||||
|
||||
body.month-pages .matchup-name {
|
||||
font-size: calc(13px * var(--month-font-scale));
|
||||
line-height: 0.92;
|
||||
}
|
||||
|
||||
body.month-pages .event-time {
|
||||
font-size: calc(14px * var(--month-font-scale));
|
||||
}
|
||||
|
||||
body.month-pages .event.matchup .event-time {
|
||||
font-size: calc(11px * var(--month-font-scale));
|
||||
}
|
||||
|
||||
body.month-pages .event.matchup .event-venue {
|
||||
font-size: calc(10px * var(--month-font-scale));
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
body.print-preview {
|
||||
justify-content: flex-start;
|
||||
overflow-x: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -235,7 +333,7 @@ body {
|
||||
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;
|
||||
@@ -252,12 +350,46 @@ body {
|
||||
color: var(--day-num-color, #fff);
|
||||
}
|
||||
|
||||
.day.has-matchups {
|
||||
background: #fff;
|
||||
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;
|
||||
width: var(--corner-badge-size);
|
||||
height: var(--corner-badge-size);
|
||||
border-radius: 0;
|
||||
background: #fff;
|
||||
color: var(--team-ink, #111);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.events-stack {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: repeat(var(--event-count), minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.day.has-matchups .events-stack {
|
||||
box-sizing: border-box;
|
||||
grid-template-rows: repeat(var(--event-count), minmax(0, 1fr));
|
||||
gap: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.event {
|
||||
--event-top-band: calc(var(--corner-badge-size, 11px) + var(--corner-badge-offset, 2px));
|
||||
--event-bottom-band: 26px;
|
||||
@@ -275,6 +407,17 @@ body {
|
||||
--event-bg: var(--team-link-color, var(--team-secondary, #8b3f1f));
|
||||
}
|
||||
|
||||
.event.matchup {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
grid-template-rows: minmax(0, 1fr) auto;
|
||||
gap: 1px;
|
||||
min-height: 0;
|
||||
padding: 2px 3px;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.event-center {
|
||||
position: absolute;
|
||||
top: var(--event-top-band);
|
||||
@@ -293,6 +436,17 @@ body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.event.matchup .event-center {
|
||||
position: relative;
|
||||
top: auto;
|
||||
left: auto;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
min-height: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.event-center img {
|
||||
width: auto;
|
||||
height: var(--event-logo-height);
|
||||
@@ -315,6 +469,8 @@ body {
|
||||
hyphens: none;
|
||||
line-height: 1.05;
|
||||
font-weight: 700;
|
||||
font-stretch: condensed;
|
||||
font-variation-settings: "wdth" 42, "wght" 700;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
@@ -322,10 +478,38 @@ body {
|
||||
font-family: var(--pc-font-display);
|
||||
font-weight: 700;
|
||||
font-variation-settings: "wdth" 30, "wght" 700;
|
||||
letter-spacing: -0.01em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.matchup-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
font-size: calc(8.5px * var(--month-font-scale));
|
||||
line-height: 0.98;
|
||||
font-variation-settings: "wdth" 36, "wght" 800;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.matchup-vs {
|
||||
font-size: 0.66em;
|
||||
font-weight: 900;
|
||||
opacity: 0.78;
|
||||
}
|
||||
|
||||
.matchup-team {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
.ha-flag {
|
||||
position: absolute;
|
||||
top: var(--corner-badge-offset, 2px);
|
||||
@@ -341,7 +525,7 @@ body {
|
||||
font-weight: 900;
|
||||
font-variation-settings: "wdth" 84, "wght" 900;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.01em;
|
||||
letter-spacing: 0;
|
||||
background: #111;
|
||||
color: #fff;
|
||||
}
|
||||
@@ -366,11 +550,26 @@ body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.event.matchup .event-meta {
|
||||
position: relative;
|
||||
left: auto;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, auto) minmax(0, 1fr);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 3px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.event-time {
|
||||
order: 1;
|
||||
max-width: 100%;
|
||||
font-size: calc(12px * var(--month-font-scale));
|
||||
font-weight: 800;
|
||||
font-stretch: condensed;
|
||||
font-variation-settings: "wdth" 56, "wght" 800;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
@@ -381,11 +580,19 @@ body {
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.event.matchup .event-time {
|
||||
min-width: 0;
|
||||
font-size: calc(7.5px * var(--month-font-scale));
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.event-venue {
|
||||
order: 2;
|
||||
max-width: 100%;
|
||||
font-size: calc(8px * var(--month-font-scale));
|
||||
font-weight: 700;
|
||||
font-stretch: condensed;
|
||||
font-variation-settings: "wdth" 50, "wght" 700;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
@@ -395,6 +602,12 @@ body {
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.event.matchup .event-venue {
|
||||
min-width: 0;
|
||||
font-size: calc(7px * var(--month-font-scale));
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 16px;
|
||||
border: 2px dashed #c8d2de;
|
||||
@@ -472,6 +685,100 @@ body {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
body.black-white .header,
|
||||
body.black-white .month-title,
|
||||
body.black-white .dow span,
|
||||
body.black-white .day,
|
||||
body.black-white .event,
|
||||
body.black-white .empty,
|
||||
body.black-white .footer-meta,
|
||||
body.black-white .footer-qr-image {
|
||||
border-color: #2f3337 !important;
|
||||
}
|
||||
|
||||
body.black-white .month-title,
|
||||
body.black-white .ha-flag {
|
||||
background: #1f2328 !important;
|
||||
color: #fff !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .dow span,
|
||||
body.black-white .day,
|
||||
body.black-white .day.muted,
|
||||
body.black-white .day.no-events,
|
||||
body.black-white .day.has-matchups,
|
||||
body.black-white .empty,
|
||||
body.black-white .legend-item,
|
||||
body.black-white .event.a .ha-flag {
|
||||
background: #f7f7f7 !important;
|
||||
color: #111 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .dow span {
|
||||
background: #e4e7eb !important;
|
||||
}
|
||||
|
||||
body.black-white .day,
|
||||
body.black-white .day.has-matchups,
|
||||
body.black-white .legend-item {
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
body.black-white .event,
|
||||
body.black-white .event.h,
|
||||
body.black-white .event.a,
|
||||
body.black-white .event.matchup {
|
||||
background: #e4e7eb !important;
|
||||
color: #111 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .day.muted,
|
||||
body.black-white .day.no-events {
|
||||
background: #f2f3f5 !important;
|
||||
color: #4b5563 !important;
|
||||
}
|
||||
|
||||
body.black-white .month-title,
|
||||
body.black-white .dow span,
|
||||
body.black-white .day,
|
||||
body.black-white .event {
|
||||
border: 1px solid #2f3337;
|
||||
}
|
||||
|
||||
body.black-white .day-num,
|
||||
body.black-white .day.has-events .day-num,
|
||||
body.black-white .day.has-matchups .day-num,
|
||||
body.black-white.month-pages .day .day-num {
|
||||
background: #fff !important;
|
||||
color: #111 !important;
|
||||
box-shadow: 0 0 0 1px #2f3337 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .ha-flag,
|
||||
body.black-white .event.a .ha-flag {
|
||||
box-shadow: 0 0 0 1px #2f3337;
|
||||
}
|
||||
|
||||
body.black-white .event-name,
|
||||
body.black-white .event-time,
|
||||
body.black-white .event-venue,
|
||||
body.black-white .matchup-vs,
|
||||
body.black-white .footer-qr-label,
|
||||
body.black-white .footer-qr-link,
|
||||
body.black-white .meta {
|
||||
color: #111 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
body.black-white .meta,
|
||||
body.black-white .footer-qr-label {
|
||||
color: #374151 !important;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body,
|
||||
body.print-preview {
|
||||
@@ -487,6 +794,7 @@ body {
|
||||
width: auto;
|
||||
min-height: auto;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.print-page {
|
||||
@@ -500,4 +808,27 @@ body {
|
||||
.title {
|
||||
font-size: calc(26px * var(--month-font-scale));
|
||||
}
|
||||
|
||||
body.month-pages .sheet-grid {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.month-pages .month-page {
|
||||
break-after: page;
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
body.month-pages .month-page:last-child {
|
||||
break-after: auto;
|
||||
page-break-after: auto;
|
||||
}
|
||||
|
||||
body.month-pages .month {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.month-pages .grid {
|
||||
break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,33 @@ 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'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported event title formats.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function tse_sp_event_export_get_title_formats() {
|
||||
return array( 'selected_first', '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, tse_sp_event_export_get_title_formats(), true ) ? $format : 'selected_first';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize an export format.
|
||||
*
|
||||
@@ -173,24 +196,26 @@ function tse_sp_event_export_parse_id_list( $value ) {
|
||||
* @return array
|
||||
*/
|
||||
function tse_sp_event_export_normalize_request_args( $source = null ) {
|
||||
$source = is_array( $source ) ? $source : $_GET;
|
||||
$format = isset( $source['format'] ) ? tse_sp_event_export_sanitize_format( wp_unslash( $source['format'] ) ) : 'matchup';
|
||||
$team_ids = isset( $source['team_id'] ) ? tse_sp_event_export_parse_id_list( wp_unslash( $source['team_id'] ) ) : array();
|
||||
$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();
|
||||
$source = is_array( $source ) ? $source : $_GET;
|
||||
$format = isset( $source['format'] ) ? tse_sp_event_export_sanitize_format( wp_unslash( $source['format'] ) ) : 'matchup';
|
||||
$team_ids = isset( $source['team_id'] ) ? tse_sp_event_export_parse_id_list( wp_unslash( $source['team_id'] ) ) : array();
|
||||
$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,
|
||||
'team_ids' => $team_ids,
|
||||
'season_id' => isset( $season_ids[0] ) ? $season_ids[0] : 0,
|
||||
'season_ids'=> $season_ids,
|
||||
'league_id' => isset( $league_ids[0] ) ? $league_ids[0] : 0,
|
||||
'league_ids'=> $league_ids,
|
||||
'field_id' => isset( $field_ids[0] ) ? $field_ids[0] : 0,
|
||||
'field_ids' => $field_ids,
|
||||
'format' => $format,
|
||||
'columns' => isset( $source['columns'] ) ? tse_sp_event_export_sanitize_columns( $format, wp_unslash( $source['columns'] ) ) : tse_sp_event_export_get_default_columns( $format ),
|
||||
'team_id' => isset( $team_ids[0] ) ? $team_ids[0] : 0,
|
||||
'team_ids' => $team_ids,
|
||||
'season_id' => isset( $season_ids[0] ) ? $season_ids[0] : 0,
|
||||
'season_ids' => $season_ids,
|
||||
'league_id' => isset( $league_ids[0] ) ? $league_ids[0] : 0,
|
||||
'league_ids' => $league_ids,
|
||||
'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 +237,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 +316,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();
|
||||
$query_posts = tse_sp_event_export_query_posts( $filters );
|
||||
$events = array();
|
||||
$team_name = $team_id > 0 ? get_the_title( $team_id ) : '';
|
||||
$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();
|
||||
|
||||
foreach ( $query_posts as $event ) {
|
||||
$event_id = $event instanceof WP_Post ? (int) $event->ID : 0;
|
||||
@@ -314,21 +335,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 +374,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.
|
||||
*
|
||||
@@ -476,25 +592,22 @@ function tse_sp_event_export_fold_ical_line( $line ) {
|
||||
* @return string
|
||||
*/
|
||||
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();
|
||||
$team_id = isset( $team_ids[0] ) ? $team_ids[0] : 0;
|
||||
$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 );
|
||||
}
|
||||
@@ -915,13 +1028,14 @@ function tse_sp_event_export_get_feed_url( $args = array(), $feed_type = 'csv' )
|
||||
$filters = tse_sp_event_export_normalize_request_args( $args );
|
||||
$feed = 'ics' === sanitize_key( $feed_type ) ? 'sp-ics' : 'sp-csv';
|
||||
$query = array(
|
||||
'feed' => $feed,
|
||||
'format' => $filters['format'],
|
||||
'team_id' => ! empty( $filters['team_ids'] ) ? implode( ',', $filters['team_ids'] ) : '',
|
||||
'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'] ) : '',
|
||||
'columns' => implode( ',', $filters['columns'] ),
|
||||
'feed' => $feed,
|
||||
'format' => $filters['format'],
|
||||
'team_id' => ! empty( $filters['team_ids'] ) ? implode( ',', $filters['team_ids'] ) : '',
|
||||
'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'] ),
|
||||
);
|
||||
|
||||
return add_query_arg( array_filter( $query, 'strlen' ), home_url( '/' ) );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -86,11 +86,13 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
$seasons = tse_sp_schedule_exporter_get_seasons();
|
||||
$season_id = tse_sp_schedule_exporter_resolve_season_id( $seasons );
|
||||
$teams = tse_sp_schedule_exporter_get_teams( $league_id, $season_id );
|
||||
$team_id = tse_sp_schedule_exporter_resolve_team_id( $teams );
|
||||
$fields = tse_sp_schedule_exporter_get_fields();
|
||||
$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();
|
||||
$team_ids = tse_sp_schedule_exporter_resolve_team_ids( $teams );
|
||||
$fields = tse_sp_schedule_exporter_get_fields();
|
||||
$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();
|
||||
$title_format = tse_sp_schedule_exporter_resolve_title_format();
|
||||
$black_white = tse_sp_schedule_exporter_resolve_black_white();
|
||||
|
||||
if ( empty( $teams ) ) {
|
||||
return '<p>' . esc_html__( 'No SportsPress teams match the selected league and season.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
@@ -115,6 +117,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">
|
||||
@@ -124,7 +135,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;">
|
||||
@@ -152,14 +163,14 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
<label for="tse-public-team"><strong><?php esc_html_e( 'Team', 'tonys-sportspress-enhancements' ); ?></strong></label><br />
|
||||
<select id="tse-public-team" name="team_id">
|
||||
<option value="0"><?php esc_html_e( 'All teams', 'tonys-sportspress-enhancements' ); ?></option>
|
||||
<select id="tse-public-team" name="team_id[]" multiple="multiple" size="<?php echo esc_attr( (string) min( 8, max( 3, count( $teams ) ) ) ); ?>">
|
||||
<?php foreach ( $teams as $team ) : ?>
|
||||
<option value="<?php echo esc_attr( (string) $team->ID ); ?>" <?php selected( $team_id, (int) $team->ID ); ?>>
|
||||
<option value="<?php echo esc_attr( (string) $team->ID ); ?>" <?php selected( in_array( (int) $team->ID, $team_ids, true ) ); ?>>
|
||||
<?php echo esc_html( $team->post_title ); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<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;">
|
||||
@@ -174,15 +185,36 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
<label for="tse-public-month-pages" style="display:inline-flex;align-items:center;gap:6px;">
|
||||
<input id="tse-public-month-pages" type="checkbox" name="month_pages" value="1" <?php checked( isset( $_GET['month_pages'] ) && '1' === (string) wp_unslash( $_GET['month_pages'] ) ); ?> />
|
||||
<strong><?php esc_html_e( 'Print each month on its own page', 'tonys-sportspress-enhancements' ); ?></strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
<label for="tse-public-black-white" style="display:inline-flex;align-items:center;gap:6px;">
|
||||
<input id="tse-public-black-white" type="checkbox" name="black_white" value="1" <?php checked( $black_white ); ?> />
|
||||
<strong><?php esc_html_e( 'High-legibility greyscale printable calendar', 'tonys-sportspress-enhancements' ); ?></strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<?php tse_sp_schedule_exporter_render_column_picker( 'matchup', 'public', $subformat ); ?>
|
||||
<?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_id, '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_id, 'season_id' => $season_id, 'league_id' => $league_id, 'field_id' => $field_id ), 'ics' );
|
||||
$print_url = tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, 'letter', $league_id );
|
||||
$feed_args = array(
|
||||
'team_id' => $team_ids,
|
||||
'season_id' => $season_id,
|
||||
'league_id' => $league_id,
|
||||
'field_id' => $field_id,
|
||||
'title_format' => $title_format,
|
||||
);
|
||||
$csv_url = tse_sp_event_export_get_feed_url( array_merge( $feed_args, array( 'format' => $subformat ) ), 'csv' );
|
||||
$ics_url = tse_sp_event_export_get_feed_url( $feed_args, '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, $black_white );
|
||||
$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;">
|
||||
@@ -331,26 +363,34 @@ function tse_sp_schedule_exporter_get_teams( $league_id = 0, $season_id = 0 ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve selected team ID.
|
||||
* Resolve selected team IDs.
|
||||
*
|
||||
* @param WP_Post[] $teams Team posts.
|
||||
* @return int
|
||||
* @return int[]
|
||||
*/
|
||||
function tse_sp_schedule_exporter_resolve_team_id( $teams ) {
|
||||
$requested = isset( $_GET['team_id'] ) ? absint( wp_unslash( $_GET['team_id'] ) ) : 0;
|
||||
if ( $requested > 0 && 'sp_team' === get_post_type( $requested ) ) {
|
||||
foreach ( $teams as $team ) {
|
||||
if ( $team instanceof WP_Post && (int) $team->ID === $requested ) {
|
||||
return $requested;
|
||||
}
|
||||
function tse_sp_schedule_exporter_resolve_team_ids( $teams ) {
|
||||
$available = array();
|
||||
foreach ( $teams as $team ) {
|
||||
if ( $team instanceof WP_Post ) {
|
||||
$available[] = (int) $team->ID;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $teams[0] ) && $teams[0] instanceof WP_Post ) {
|
||||
return (int) $teams[0]->ID;
|
||||
$requested = array();
|
||||
if ( isset( $_GET['team_id'] ) ) {
|
||||
$requested = tse_sp_event_export_parse_id_list( wp_unslash( $_GET['team_id'] ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
$selected = array_values( array_intersect( $requested, $available ) );
|
||||
if ( ! empty( $selected ) ) {
|
||||
return $selected;
|
||||
}
|
||||
|
||||
if ( isset( $available[0] ) ) {
|
||||
return array( (int) $available[0] );
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -543,6 +583,38 @@ 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, tse_sp_event_export_get_title_formats(), true ) ? $value : 'selected_first';
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve whether printable URLs should use black-and-white styling.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function tse_sp_schedule_exporter_resolve_black_white() {
|
||||
return isset( $_GET['black_white'] ) && '1' === (string) wp_unslash( $_GET['black_white'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current output URL for the selected export type.
|
||||
*
|
||||
@@ -700,17 +772,29 @@ function tse_sp_schedule_exporter_get_primary_venue( $event_id ) {
|
||||
* @param int $season_id Season ID.
|
||||
* @param string $paper Paper size.
|
||||
* @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.
|
||||
* @param bool $black_white Whether to use black-and-white printable styling.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $paper, $league_id = 0, $autoprint = false ) {
|
||||
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', $black_white = false ) {
|
||||
$team_ids = is_array( $team_id ) ? array_values( array_filter( array_map( 'absint', $team_id ) ) ) : array( absint( $team_id ) );
|
||||
|
||||
return add_query_arg(
|
||||
array(
|
||||
Tony_Sportspress_Printable_Calendars::QUERY_FLAG => '1',
|
||||
'sp_team' => (string) absint( $team_id ),
|
||||
'sp_team' => implode( ',', $team_ids ),
|
||||
'sp_season' => $season_id > 0 ? (string) absint( $season_id ) : '',
|
||||
'sp_league' => $league_id > 0 ? (string) absint( $league_id ) : '',
|
||||
'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' : '',
|
||||
'black_white' => $black_white ? '1' : '',
|
||||
),
|
||||
home_url( '/' )
|
||||
);
|
||||
@@ -758,17 +842,28 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
|
||||
var league = form.querySelector('[name="league_id"]');
|
||||
var season = form.querySelector('[name="season_id"]');
|
||||
var team = form.querySelector('[name="team_id"]');
|
||||
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 blackWhite = form.querySelector('[name="black_white"]');
|
||||
var outputUrl = scope.querySelector('.tse-output-url');
|
||||
var openButton = scope.querySelector('.tse-open-link');
|
||||
var iosButton = scope.querySelector('.tse-ics-ios-link');
|
||||
var androidButton = scope.querySelector('.tse-ics-android-link');
|
||||
var outputNote = scope.querySelector('.tse-output-note');
|
||||
var copyButton = scope.querySelector('.tse-copy-link');
|
||||
var teamValue = team ? (team.value || '0') : '0';
|
||||
var teamValues = team ? Array.prototype.slice.call(team.selectedOptions || []).map(function(option){
|
||||
return option.value;
|
||||
}).filter(function(value){
|
||||
return value && value !== '0';
|
||||
}) : [];
|
||||
if (!teamValues.length && team && team.value && team.value !== '0') {
|
||||
teamValues = [team.value];
|
||||
}
|
||||
var teamValue = teamValues.length ? teamValues.join(',') : '0';
|
||||
var activeSubformat = subformat ? (subformat.value || 'matchup') : 'matchup';
|
||||
var selectedExportType = exportType ? (exportType.value || 'csv') : 'csv';
|
||||
|
||||
@@ -792,6 +887,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;
|
||||
@@ -808,6 +904,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');
|
||||
}
|
||||
@@ -816,6 +913,18 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
if (league) printUrl.searchParams.set('sp_league', league.value || '0');
|
||||
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 {
|
||||
printUrl.searchParams.delete('month_pages');
|
||||
}
|
||||
if (blackWhite && blackWhite.checked) {
|
||||
printUrl.searchParams.set('black_white', '1');
|
||||
} else {
|
||||
printUrl.searchParams.delete('black_white');
|
||||
}
|
||||
printUrl.searchParams.set('paper', 'letter');
|
||||
}
|
||||
|
||||
@@ -833,11 +942,11 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
resolvedUrl = printUrl.toString();
|
||||
if (teamValue === '0') {
|
||||
disabled = true;
|
||||
note = 'Printable requires a specific team. All teams is not supported.';
|
||||
note = 'Printable requires at least one selected team.';
|
||||
}
|
||||
} else if (selectedExportType === 'csv' && activeSubformat === 'team' && teamValue === '0') {
|
||||
disabled = true;
|
||||
note = 'CSV team layout requires a specific team. All teams is not supported.';
|
||||
note = 'CSV team layout requires at least one selected team.';
|
||||
}
|
||||
|
||||
if (outputUrl) {
|
||||
@@ -885,10 +994,10 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
|
||||
syncLinks(scope);
|
||||
|
||||
scope.querySelectorAll('.tse-schedule-exporter-form select').forEach(function(select){
|
||||
select.addEventListener('change', function(){
|
||||
if (select.dataset.autoSubmit === '1') {
|
||||
select.form.submit();
|
||||
scope.querySelectorAll('.tse-schedule-exporter-form select, .tse-schedule-exporter-form input[type="checkbox"]').forEach(function(input){
|
||||
input.addEventListener('change', function(){
|
||||
if (input.dataset.autoSubmit === '1') {
|
||||
input.form.submit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
341
tests/test-sp-schedule-exporter.php
Normal file
341
tests/test-sp-schedule-exporter.php
Normal file
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for schedule exporter and printable schedule helpers.
|
||||
*
|
||||
* @package Tonys_Sportspress_Enhancements
|
||||
*/
|
||||
|
||||
/**
|
||||
* Schedule exporter tests.
|
||||
*/
|
||||
class Test_SP_Schedule_Exporter extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Original request globals.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $original_get = array();
|
||||
|
||||
/**
|
||||
* Set up shared test fixtures.
|
||||
*/
|
||||
public function set_up() {
|
||||
parent::set_up();
|
||||
|
||||
$this->original_get = $_GET;
|
||||
|
||||
foreach ( array( 'sp_venue', 'sp_league', 'sp_season' ) as $taxonomy ) {
|
||||
if ( ! taxonomy_exists( $taxonomy ) ) {
|
||||
register_taxonomy( $taxonomy, 'sp_event' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore request globals.
|
||||
*/
|
||||
public function tear_down() {
|
||||
$_GET = $this->original_get;
|
||||
|
||||
parent::tear_down();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SportsPress team post.
|
||||
*
|
||||
* @param string $name Team name.
|
||||
* @return int
|
||||
*/
|
||||
private function create_team( $name ) {
|
||||
return self::factory()->post->create(
|
||||
array(
|
||||
'post_type' => 'sp_team',
|
||||
'post_status' => 'publish',
|
||||
'post_title' => $name,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SportsPress event with ordered teams.
|
||||
*
|
||||
* @param int $home_id Home team ID.
|
||||
* @param int $away_id Away team ID.
|
||||
* @param int[] $venue_ids Venue IDs.
|
||||
* @return int
|
||||
*/
|
||||
private function create_event( $home_id, $away_id, $venue_ids = array() ) {
|
||||
$event_id = self::factory()->post->create(
|
||||
array(
|
||||
'post_type' => 'sp_event',
|
||||
'post_status' => 'publish',
|
||||
'post_title' => 'Game',
|
||||
'post_date' => '2026-05-20 18:00:00',
|
||||
'post_date_gmt' => '2026-05-20 23:00:00',
|
||||
)
|
||||
);
|
||||
|
||||
add_post_meta( $event_id, 'sp_team', (string) $home_id );
|
||||
add_post_meta( $event_id, 'sp_team', (string) $away_id );
|
||||
|
||||
if ( ! empty( $venue_ids ) ) {
|
||||
wp_set_object_terms( $event_id, $venue_ids, 'sp_venue' );
|
||||
}
|
||||
|
||||
return $event_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple selected team IDs should be retained in request order.
|
||||
*/
|
||||
public function test_resolve_team_ids_accepts_multiple_request_values() {
|
||||
$team_one = $this->create_team( 'Blue' );
|
||||
$team_two = $this->create_team( 'Red' );
|
||||
$teams = array( get_post( $team_one ), get_post( $team_two ) );
|
||||
|
||||
$_GET['team_id'] = array( (string) $team_one, (string) $team_two );
|
||||
|
||||
$this->assertSame( array( $team_one, $team_two ), tse_sp_schedule_exporter_resolve_team_ids( $teams ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Printable URLs should carry multiple team IDs and the selected field.
|
||||
*/
|
||||
public function test_printable_url_accepts_multiple_teams_and_field() {
|
||||
$url = tse_sp_schedule_exporter_get_printable_url( array( 12, 34 ), 56, 'letter', 78, false, 90, true );
|
||||
$query = array();
|
||||
|
||||
wp_parse_str( (string) wp_parse_url( $url, PHP_URL_QUERY ), $query );
|
||||
|
||||
$this->assertSame( '12,34', $query['sp_team'] );
|
||||
$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'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Printable URLs should carry selected team and field label modes.
|
||||
*/
|
||||
public function test_printable_url_accepts_label_modes() {
|
||||
$url = tse_sp_schedule_exporter_get_printable_url( 12, 56, 'letter', 78, false, 90, false, 'shortname', 'abbreviation' );
|
||||
$query = array();
|
||||
|
||||
wp_parse_str( (string) wp_parse_url( $url, PHP_URL_QUERY ), $query );
|
||||
|
||||
$this->assertSame( 'shortname', $query['team_label'] );
|
||||
$this->assertSame( 'abbreviation', $query['field_label'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Printable URLs should carry black-and-white mode when requested.
|
||||
*/
|
||||
public function test_printable_url_accepts_black_white_mode() {
|
||||
$url = tse_sp_schedule_exporter_get_printable_url( 12, 56, 'letter', 78, false, 90, false, 'name', 'name', 'selected_first', true );
|
||||
$query = array();
|
||||
|
||||
wp_parse_str( (string) wp_parse_url( $url, PHP_URL_QUERY ), $query );
|
||||
|
||||
$this->assertSame( '1', $query['black_white'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Single-team printable entries should keep the existing opponent perspective.
|
||||
*/
|
||||
public function test_printable_single_team_entries_keep_opponent_perspective() {
|
||||
$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' ) );
|
||||
$this->create_event( $home_id, $away_id, array( $venue_id ) );
|
||||
|
||||
$printable = Tony_Sportspress_Printable_Calendars::instance();
|
||||
$method = new ReflectionMethod( $printable, 'get_schedule_entries' );
|
||||
$method->setAccessible( true );
|
||||
|
||||
$entries = $method->invoke( $printable, $home_id, 0, 0, array() );
|
||||
|
||||
$this->assertCount( 1, $entries );
|
||||
$this->assertFalse( $entries[0]['is_matchup'] );
|
||||
$this->assertTrue( $entries[0]['is_home'] );
|
||||
$this->assertSame( 'Away Team', $entries[0]['opponent_name'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Printable entries should honor requested team and field labels.
|
||||
*/
|
||||
public function test_printable_entries_honor_label_modes() {
|
||||
$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' ) );
|
||||
update_post_meta( $away_id, 'sp_abbreviation', 'AWY' );
|
||||
update_term_meta( $venue_id, 'tse_abbreviation', 'NF' );
|
||||
$this->create_event( $home_id, $away_id, array( $venue_id ) );
|
||||
|
||||
$printable = Tony_Sportspress_Printable_Calendars::instance();
|
||||
$method = new ReflectionMethod( $printable, 'get_schedule_entries' );
|
||||
$method->setAccessible( true );
|
||||
|
||||
$entries = $method->invoke( $printable, $home_id, 0, 0, array(), 'abbreviation', 'abbreviation' );
|
||||
|
||||
$this->assertCount( 1, $entries );
|
||||
$this->assertSame( 'AWY', $entries[0]['opponent_name'] );
|
||||
$this->assertSame( 'NF', $entries[0]['venue_label'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Team CSV layout should support multiple selected teams with away-first context.
|
||||
*/
|
||||
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' ) );
|
||||
$this->create_event( $home_id, $away_id, array( $venue_id ) );
|
||||
|
||||
$printable = Tony_Sportspress_Printable_Calendars::instance();
|
||||
$method = new ReflectionMethod( $printable, 'get_schedule_entries' );
|
||||
$method->setAccessible( true );
|
||||
|
||||
$entries = $method->invoke( $printable, array( $home_id, $away_id ), 0, 0, array() );
|
||||
|
||||
$this->assertCount( 1, $entries );
|
||||
$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'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Exactly one selected field should suppress per-event venue labels.
|
||||
*/
|
||||
public function test_render_month_grid_can_suppress_event_venue_label() {
|
||||
$printable = Tony_Sportspress_Printable_Calendars::instance();
|
||||
$method = new ReflectionMethod( $printable, 'render_month_grid' );
|
||||
$method->setAccessible( true );
|
||||
|
||||
$entries = array(
|
||||
'2026-05-20' => array(
|
||||
array(
|
||||
'day_key' => '2026-05-20',
|
||||
'month_key' => '2026-05',
|
||||
'timestamp' => strtotime( '2026-05-20 18:00:00' ),
|
||||
'is_matchup' => true,
|
||||
'away_team_name' => 'Away',
|
||||
'home_team_name' => 'Home',
|
||||
'event_time' => '6:00 PM',
|
||||
'venue_label' => 'North',
|
||||
'venue_name' => 'North Field',
|
||||
'venue_key' => 'v:1',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
ob_start();
|
||||
$method->invoke(
|
||||
$printable,
|
||||
'2026-05',
|
||||
$entries,
|
||||
array( 'v:1' => array( 'name' => 'North Field', 'color' => '#1D4ED8' ) ),
|
||||
array(
|
||||
'primary' => '#1D4ED8',
|
||||
'secondary' => '#DC2626',
|
||||
'accent' => '#1D4ED8',
|
||||
'ink' => '#111827',
|
||||
'muted_ink' => '#334155',
|
||||
),
|
||||
true,
|
||||
true
|
||||
);
|
||||
$output = ob_get_clean();
|
||||
|
||||
$this->assertStringContainsString( 'Away', $output );
|
||||
$this->assertStringContainsString( 'Home', $output );
|
||||
$this->assertStringNotContainsString( 'class="event-venue"', $output );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user