diff --git a/assets/schedule-exporter-block.js b/assets/schedule-exporter-block.js new file mode 100644 index 0000000..246a26d --- /dev/null +++ b/assets/schedule-exporter-block.js @@ -0,0 +1,27 @@ +( function ( blocks, blockEditor, element, i18n ) { + var el = element.createElement; + var useBlockProps = blockEditor.useBlockProps; + var __ = i18n.__; + + blocks.registerBlockType( 'tse/schedule-exporter', { + edit: function () { + var blockProps = useBlockProps( { + className: 'tse-schedule-exporter-block-placeholder', + } ); + + return el( + 'div', + blockProps, + el( 'strong', null, __( 'Schedule Exporter', 'tonys-sportspress-enhancements' ) ), + el( + 'p', + null, + __( 'This block renders the public schedule exporter on the frontend.', 'tonys-sportspress-enhancements' ) + ) + ); + }, + save: function () { + return null; + }, + } ); +} )( window.wp.blocks, window.wp.blockEditor, window.wp.element, window.wp.i18n ); diff --git a/includes/sp-printable-calendars.php b/includes/sp-printable-calendars.php index cbcb676..db4eecb 100644 --- a/includes/sp-printable-calendars.php +++ b/includes/sp-printable-calendars.php @@ -55,7 +55,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { * * @var string[] */ - private $allowed_paper_sizes = array( 'letter', 'ledger' ); + private $allowed_paper_sizes = array( 'letter', 'ledger', '11x17' ); /** * Allowed refresh intervals. @@ -145,7 +145,9 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { $vars[] = self::QUERY_FLAG; $vars[] = 'sp_team'; $vars[] = 'sp_season'; + $vars[] = 'sp_league'; $vars[] = 'paper'; + $vars[] = 'autoprint'; return $vars; } @@ -160,7 +162,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { } $season_id = absint( (string) get_option( 'sportspress_season', '0' ) ); - $link = $this->build_url( $team_id, $season_id, 'letter' ); + $link = $this->build_url( $team_id, $season_id, '11x17' ); echo '
';
echo '';
@@ -407,11 +409,10 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
if ( $season_id <= 0 ) {
$season_id = absint( (string) get_option( 'sportspress_season', '0' ) );
}
+ $league_id = absint( (string) get_query_var( 'sp_league' ) );
- $paper = strtolower( (string) get_query_var( 'paper' ) );
- if ( ! in_array( $paper, $this->allowed_paper_sizes, true ) ) {
- $paper = 'letter';
- }
+ $paper = $this->normalize_paper_size( (string) get_query_var( 'paper' ) );
+ $autoprint = '1' === (string) get_query_var( 'autoprint' );
$team_name = get_the_title( $team_id );
$team_logo = get_the_post_thumbnail( $team_id, array( 72, 72 ), array( 'class' => 'team-logo-img' ) );
@@ -419,7 +420,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
$site_url = home_url( '/' );
$qr_url = 'https://api.qrserver.com/v1/create-qr-code/?size=144x144&data=' . rawurlencode( $site_url );
$season_name = '';
- $entries = $this->get_schedule_entries( $team_id, $season_id );
+ $entries = $this->get_schedule_entries( $team_id, $season_id, $league_id );
$team_palette = $this->get_team_color_palette( $team_id );
$team_primary_for_fields = $this->get_strict_team_primary_color( $team_id );
$entries_by_day = array();
@@ -462,6 +463,9 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
echo '';
+ if ( $autoprint ) {
+ echo '';
+ }
echo '';
echo '';
@@ -551,12 +555,15 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
* @param string $paper Paper size.
* @return string
*/
- private function build_url( $team_id, $season_id, $paper ) {
+ private function build_url( $team_id, $season_id, $paper, $league_id = 0 ) {
+ $paper = $this->normalize_paper_size( $paper );
+
return add_query_arg(
array(
self::QUERY_FLAG => '1',
'sp_team' => (string) absint( $team_id ),
'sp_season' => $season_id > 0 ? (string) absint( $season_id ) : '',
+ 'sp_league' => $league_id > 0 ? (string) absint( $league_id ) : '',
'paper' => (string) $paper,
),
home_url( '/' )
@@ -587,6 +594,26 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
return wp_parse_args( get_option( self::OPTION_KEY, array() ), $this->default_settings() );
}
+ /**
+ * Normalize paper-size input to the internal sheet key.
+ *
+ * @param string $paper Raw paper-size value.
+ * @return string
+ */
+ private function normalize_paper_size( $paper ) {
+ $paper = strtolower( trim( (string) $paper ) );
+
+ if ( '11x17' === $paper ) {
+ return 'ledger';
+ }
+
+ if ( ! in_array( $paper, $this->allowed_paper_sizes, true ) ) {
+ return 'letter';
+ }
+
+ return $paper;
+ }
+
/**
* Get supported venue label modes.
*
@@ -839,9 +866,10 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
*
* @param int $team_id Team ID.
* @param int $season_id Season ID.
+ * @param int $league_id League ID.
* @return array
*/
- private function get_schedule_entries( $team_id, $season_id ) {
+ private function get_schedule_entries( $team_id, $season_id, $league_id = 0 ) {
$args = array(
'post_type' => 'sp_event',
'post_status' => array( 'publish', 'future' ),
@@ -858,16 +886,32 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
),
);
+ $tax_query = array();
+
if ( $season_id > 0 ) {
- $args['tax_query'] = array(
- array(
- 'taxonomy' => 'sp_season',
- 'field' => 'term_id',
- 'terms' => array( $season_id ),
- ),
+ $tax_query[] = array(
+ 'taxonomy' => 'sp_season',
+ 'field' => 'term_id',
+ 'terms' => array( $season_id ),
);
}
+ if ( $league_id > 0 ) {
+ $tax_query[] = array(
+ 'taxonomy' => 'sp_league',
+ 'field' => 'term_id',
+ 'terms' => array( $league_id ),
+ );
+ }
+
+ if ( ! empty( $tax_query ) ) {
+ if ( count( $tax_query ) > 1 ) {
+ $tax_query['relation'] = 'AND';
+ }
+
+ $args['tax_query'] = $tax_query;
+ }
+
$query = new WP_Query( $args );
$entries = array();
diff --git a/includes/sp-schedule-exporter.php b/includes/sp-schedule-exporter.php
new file mode 100644
index 0000000..ad031f1
--- /dev/null
+++ b/includes/sp-schedule-exporter.php
@@ -0,0 +1,879 @@
+ 403 ) );
+ }
+
+ check_admin_referer( 'tse_schedule_export' );
+
+ $team_id = isset( $_GET['team_id'] ) ? absint( wp_unslash( $_GET['team_id'] ) ) : 0;
+ $season_id = isset( $_GET['season_id'] ) ? absint( wp_unslash( $_GET['season_id'] ) ) : 0;
+ $league_id = isset( $_GET['league_id'] ) ? absint( wp_unslash( $_GET['league_id'] ) ) : 0;
+ $format = isset( $_GET['format'] ) ? sanitize_key( wp_unslash( $_GET['format'] ) ) : '';
+
+ if ( $team_id <= 0 || 'sp_team' !== get_post_type( $team_id ) ) {
+ wp_die( esc_html__( 'Choose a valid team before exporting.', 'tonys-sportspress-enhancements' ), '', array( 'response' => 400 ) );
+ }
+
+ if ( ! in_array( $format, array( 'matchup', 'team' ), true ) ) {
+ wp_die( esc_html__( 'Choose a valid export format.', 'tonys-sportspress-enhancements' ), '', array( 'response' => 400 ) );
+ }
+
+ $events = tse_sp_schedule_exporter_get_events( $team_id, $season_id, $league_id );
+ $team = get_post( $team_id );
+
+ if ( ! $team instanceof WP_Post ) {
+ wp_die( esc_html__( 'The selected team could not be loaded.', 'tonys-sportspress-enhancements' ), '', array( 'response' => 404 ) );
+ }
+
+ $filename = sanitize_title( $team->post_name ? $team->post_name : $team->post_title );
+ if ( '' === $filename ) {
+ $filename = 'schedule';
+ }
+
+ if ( $season_id > 0 ) {
+ $season = get_term( $season_id, 'sp_season' );
+ if ( $season && ! is_wp_error( $season ) && ! empty( $season->slug ) ) {
+ $filename .= '-' . sanitize_title( $season->slug );
+ }
+ }
+
+ $filename .= '-' . $format . '.csv';
+
+ header( 'Content-Type: text/csv; charset=utf-8' );
+ header( 'Content-Disposition: attachment; filename=' . $filename );
+
+ $output = fopen( 'php://output', 'w' );
+ if ( false === $output ) {
+ wp_die( esc_html__( 'Unable to start the CSV export.', 'tonys-sportspress-enhancements' ), '', array( 'response' => 500 ) );
+ }
+
+ fwrite( $output, "\xEF\xBB\xBF" );
+
+ if ( 'matchup' === $format ) {
+ fputcsv(
+ $output,
+ array(
+ 'Date',
+ 'Time',
+ 'Away Team',
+ 'Home Team',
+ 'Field Name',
+ )
+ );
+
+ foreach ( $events as $event ) {
+ fputcsv(
+ $output,
+ array(
+ $event['date'],
+ $event['time'],
+ $event['away_team'],
+ $event['home_team'],
+ $event['venue_name'],
+ )
+ );
+ }
+ } else {
+ fputcsv(
+ $output,
+ array(
+ 'Extra Label',
+ 'Date',
+ 'Time',
+ 'Opponent',
+ 'Home/Away',
+ 'Venue',
+ )
+ );
+
+ foreach ( $events as $event ) {
+ fputcsv(
+ $output,
+ array(
+ $event['label'],
+ $event['date'],
+ $event['time'],
+ $event['opponent_name'],
+ $event['location_flag'],
+ $event['venue_name'],
+ )
+ );
+ }
+ }
+
+ fclose( $output );
+ exit;
+}
+add_action( 'admin_post_tse_schedule_export', 'tse_sp_schedule_exporter_handle_download' );
+add_action( 'admin_post_nopriv_tse_schedule_export', 'tse_sp_schedule_exporter_handle_download' );
+
+/**
+ * Register the schedule exporter block.
+ *
+ * @return void
+ */
+function tse_sp_schedule_exporter_register_block() {
+ if ( ! function_exists( 'register_block_type' ) ) {
+ return;
+ }
+
+ wp_register_script(
+ 'tse-schedule-exporter-block',
+ TONY_SPORTSPRESS_ENHANCEMENTS_URL . 'assets/schedule-exporter-block.js',
+ array( 'wp-blocks', 'wp-block-editor', 'wp-element', 'wp-i18n' ),
+ TONY_SPORTSPRESS_ENHANCEMENTS_VERSION,
+ true
+ );
+
+ register_block_type(
+ 'tse/schedule-exporter',
+ array(
+ 'api_version' => 3,
+ 'title' => __( 'Schedule Exporter', 'tonys-sportspress-enhancements' ),
+ 'description' => __( 'Shows the public schedule exporter with CSV and printable PDF options.', 'tonys-sportspress-enhancements' ),
+ 'category' => 'widgets',
+ 'icon' => 'calendar-alt',
+ 'editor_script' => 'tse-schedule-exporter-block',
+ 'render_callback' => 'tse_sp_schedule_exporter_render_block',
+ 'supports' => array(
+ 'html' => false,
+ ),
+ )
+ );
+}
+
+/**
+ * Render the schedule exporter page.
+ *
+ * @return void
+ */
+function tse_sp_schedule_exporter_render_admin_page() {
+ if ( ! current_user_can( 'manage_sportspress' ) ) {
+ return;
+ }
+
+ $leagues = tse_sp_schedule_exporter_get_leagues();
+ $league_id = tse_sp_schedule_exporter_resolve_league_id( $leagues );
+ $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 );
+ $paper = tse_sp_schedule_exporter_resolve_paper_size();
+
+ echo ' ' . esc_html__( 'Choose a team and season, then export the schedule as CSV or open the printable schedule in a PDF-ready print view.', 'tonys-sportspress-enhancements' ) . ' ' . esc_html__( 'No SportsPress teams match the selected league and season.', 'tonys-sportspress-enhancements' ) . ' ' . esc_html__( 'No SportsPress teams match the selected league and season.', 'tonys-sportspress-enhancements' ) . ' ' . esc_html__( 'The schedule exporter renders on the frontend.', 'tonys-sportspress-enhancements' ) . '' . esc_html__( 'Schedule Exporter', 'tonys-sportspress-enhancements' ) . '
';
+ echo '' . esc_html__( 'Exports', 'tonys-sportspress-enhancements' ) . '
';
+
+ echo '';
+ foreach ( array(
+ array(
+ 'format' => 'matchup',
+ 'label' => __( 'Download Matchup CSV', 'tonys-sportspress-enhancements' ),
+ 'description' => __( 'Date, time, away team, home team, and field name.', 'tonys-sportspress-enhancements' ),
+ ),
+ array(
+ 'format' => 'team',
+ 'label' => __( 'Download Team CSV', 'tonys-sportspress-enhancements' ),
+ 'description' => __( 'TeamSnap-compatible layout with game label, opponent, home/away flag, and venue.', 'tonys-sportspress-enhancements' ),
+ ),
+ ) as $export_option ) {
+ $url = wp_nonce_url(
+ add_query_arg(
+ array(
+ 'action' => 'tse_schedule_export',
+ 'league_id' => $league_id,
+ 'team_id' => $team_id,
+ 'season_id' => $season_id,
+ 'format' => $export_option['format'],
+ ),
+ admin_url( 'admin-post.php' )
+ ),
+ 'tse_schedule_export'
+ );
+
+ echo '
';
+ tse_sp_schedule_exporter_render_link_sync_script( true );
+ echo '';
+ echo ' ';
+ }
+
+ $pdf_url = tse_sp_schedule_exporter_get_pdf_url( $team_id, $season_id, $paper, $league_id );
+ echo '' . esc_html( $export_option['label'] ) . ' ';
+ echo '' . esc_html( $export_option['description'] ) . ' ';
+ echo '';
+ echo ' ';
+ echo '' . esc_html__( 'Open Printable PDF View', 'tonys-sportspress-enhancements' ) . ' ';
+ echo '' . esc_html__( 'Opens the printable schedule and launches the browser print dialog so you can save a PDF.', 'tonys-sportspress-enhancements' ) . ' ';
+ echo '