diff --git a/assets/print-calendar.css b/assets/print-calendar.css index 6dc7fb4..a0146ad 100644 --- a/assets/print-calendar.css +++ b/assets/print-calendar.css @@ -260,7 +260,7 @@ body { .event { --event-top-band: calc(var(--corner-badge-size, 11px) + var(--corner-badge-offset, 2px)); - --event-bottom-band: 14px; + --event-bottom-band: 26px; --event-logo-height: var(--pc-event-logo-height); position: relative; background: var(--event-bg, var(--team-primary, #1b76d1)); @@ -351,21 +351,50 @@ body { color: #111; } -.event-time { +.event-meta { position: absolute; left: 0; right: 0; bottom: 2px; z-index: 3; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-end; + gap: 1px; + padding: 0 2px; + overflow: hidden; +} + +.event-time { + order: 1; + max-width: 100%; font-size: calc(12px * var(--month-font-scale)); font-weight: 800; line-height: 1; text-transform: uppercase; text-align: center; color: currentColor; + white-space: nowrap; + overflow: hidden; + text-overflow: clip; opacity: 0.95; } +.event-venue { + order: 2; + max-width: 100%; + font-size: calc(8px * var(--month-font-scale)); + font-weight: 700; + line-height: 1; + text-align: center; + text-transform: uppercase; + white-space: nowrap; + overflow: hidden; + text-overflow: clip; + opacity: 0.88; +} + .empty { padding: 16px; border: 2px dashed #c8d2de; diff --git a/includes/sp-printable-calendars.php b/includes/sp-printable-calendars.php index 0d5d781..cbcb676 100644 --- a/includes/sp-printable-calendars.php +++ b/includes/sp-printable-calendars.php @@ -229,6 +229,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { 'sync_interval_minutes' => isset( $existing['sync_interval_minutes'] ) ? absint( (string) $existing['sync_interval_minutes'] ) : 60, 'venue_color_overrides' => $this->sanitize_venue_color_overrides( isset( $current['venue_color_overrides'] ) ? $current['venue_color_overrides'] : array() ), 'venue_use_team_primary' => $this->sanitize_venue_primary_flags( isset( $current['venue_use_team_primary'] ) ? $current['venue_use_team_primary'] : array() ), + 'printable_venue_label_mode' => $this->sanitize_venue_label_mode( isset( $current['printable_venue_label_mode'] ) ? $current['printable_venue_label_mode'] : '' ), ); } @@ -288,6 +289,17 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { echo ''; echo ''; echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '

' . esc_html__( 'Choose whether the printable schedule shows the venue full name, abbreviation, or short name below each game time.', 'tonys-sportspress-enhancements' ) . '

'; + echo ''; + echo ''; echo ''; echo '
'; @@ -562,6 +574,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { 'sync_interval_minutes' => 60, 'venue_color_overrides' => array(), 'venue_use_team_primary'=> array(), + 'printable_venue_label_mode' => 'full_name', ); } @@ -574,6 +587,32 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { return wp_parse_args( get_option( self::OPTION_KEY, array() ), $this->default_settings() ); } + /** + * Get supported venue label modes. + * + * @return array + */ + private function get_venue_label_mode_options() { + return array( + 'full_name' => __( 'Full Name', 'tonys-sportspress-enhancements' ), + 'abbreviation' => __( 'Abbreviation', 'tonys-sportspress-enhancements' ), + 'short_name' => __( 'Short Name', 'tonys-sportspress-enhancements' ), + ); + } + + /** + * Sanitize venue label mode. + * + * @param mixed $value Raw value. + * @return string + */ + private function sanitize_venue_label_mode( $value ) { + $mode = is_string( $value ) ? sanitize_key( $value ) : ''; + $allowed = array_keys( $this->get_venue_label_mode_options() ); + + return in_array( $mode, $allowed, true ) ? $mode : 'full_name'; + } + /** * Whether SportsPress is available. * @@ -784,6 +823,17 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { return isset( $settings['venue_use_team_primary'] ) && is_array( $settings['venue_use_team_primary'] ) ? $settings['venue_use_team_primary'] : array(); } + /** + * Get configured venue label mode. + * + * @return string + */ + private function get_venue_label_mode() { + $settings = $this->get_settings(); + + return $this->sanitize_venue_label_mode( isset( $settings['printable_venue_label_mode'] ) ? $settings['printable_venue_label_mode'] : '' ); + } + /** * Collect event entries for the calendar. * @@ -845,12 +895,14 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { } } - $venues = get_the_terms( $event_id, 'sp_venue' ); - $venue_name = ''; - $venue_id = 0; - if ( is_array( $venues ) && isset( $venues[0] ) && is_object( $venues[0] ) && isset( $venues[0]->name ) ) { - $venue_name = (string) $venues[0]->name; - $venue_id = isset( $venues[0]->term_id ) ? (int) $venues[0]->term_id : 0; + $venue = $this->get_event_venue_term( $event_id ); + $venue_name = ''; + $venue_id = 0; + $venue_label = ''; + if ( $venue ) { + $venue_name = (string) $venue->name; + $venue_id = (int) $venue->term_id; + $venue_label = $this->get_configured_venue_label( $venue ); } $entries[] = array( @@ -863,6 +915,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { 'opponent_name' => $opponent_id > 0 ? $this->get_team_label( $opponent_id ) : __( 'TBD', 'tonys-sportspress-enhancements' ), 'event_time' => function_exists( 'sp_get_time' ) ? sp_get_time( $event_id ) : get_post_time( get_option( 'time_format' ), false, $event_id, true ), 'venue_name' => $venue_name, + 'venue_label' => $venue_label, 'venue_id' => $venue_id, 'venue_key' => $venue_id > 0 ? 'v:' . $venue_id : 'n:' . strtolower( $venue_name ), ); @@ -983,7 +1036,12 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { } echo '
'; echo '' . esc_html( $is_home ? 'H' : 'A' ) . ''; + echo '
'; echo '
' . esc_html( isset( $entry['event_time'] ) ? (string) $entry['event_time'] : '' ) . '
'; + if ( ! empty( $entry['venue_label'] ) ) { + echo '
' . esc_html( (string) $entry['venue_label'] ) . '
'; + } + echo '
'; echo ''; } echo ''; @@ -1023,6 +1081,51 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) { return is_string( $title ) && '' !== $title ? $title : __( 'TBD', 'tonys-sportspress-enhancements' ); } + /** + * Get the first event venue term. + * + * @param int $event_id Event ID. + * @return WP_Term|null + */ + private function get_event_venue_term( $event_id ) { + $venues = get_the_terms( $event_id, 'sp_venue' ); + if ( ! is_array( $venues ) || ! isset( $venues[0] ) || ! is_object( $venues[0] ) || ! isset( $venues[0]->term_id, $venues[0]->name ) ) { + return null; + } + + return $venues[0]; + } + + /** + * Get the venue label for the current printable mode. + * + * Falls back to the full venue name when term meta is empty. + * + * @param WP_Term $venue Venue term. + * @return string + */ + private function get_configured_venue_label( $venue ) { + $full_name = isset( $venue->name ) ? trim( (string) $venue->name ) : ''; + if ( '' === $full_name || ! isset( $venue->term_id ) ) { + return ''; + } + + $term_id = (int) $venue->term_id; + $mode = $this->get_venue_label_mode(); + + if ( 'abbreviation' === $mode ) { + $abbreviation = trim( (string) get_term_meta( $term_id, 'tse_abbreviation', true ) ); + return '' !== $abbreviation ? $abbreviation : $full_name; + } + + if ( 'short_name' === $mode ) { + $short_name = trim( (string) get_term_meta( $term_id, 'tse_short_name', true ) ); + return '' !== $short_name ? $short_name : $full_name; + } + + return $full_name; + } + /** * Resolve venue color. * diff --git a/includes/sp-venue-meta.php b/includes/sp-venue-meta.php new file mode 100644 index 0000000..95ae76c --- /dev/null +++ b/includes/sp-venue-meta.php @@ -0,0 +1,116 @@ + 'string', + 'single' => true, + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + 'auth_callback' => static function() { + return current_user_can( 'manage_categories' ); + }, + ) + ); + + register_term_meta( + 'sp_venue', + 'tse_abbreviation', + array( + 'type' => 'string', + 'single' => true, + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + 'auth_callback' => static function() { + return current_user_can( 'manage_categories' ); + }, + ) + ); +} +add_action( 'init', 'tony_sportspress_register_venue_term_meta' ); + +/** + * Render add-form fields for venue metadata. + */ +function tony_sportspress_add_venue_meta_fields() { + ?> +
+ + +

+
+
+ + +

+
+ term_id, 'tse_short_name', true ); + $abbreviation = get_term_meta( $term->term_id, 'tse_abbreviation', true ); + ?> + + + + + + +

+ + + + + + + + +

+ + +