Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f38ceccdb3
|
|||
|
94b51c3959
|
|||
|
8f1a819a2d
|
|||
|
5a5bf5acdb
|
|||
|
dbe3048af7
|
|||
|
4ed968a045
|
|||
|
360b971880
|
@@ -8,6 +8,18 @@ Author: Your Name
|
|||||||
|
|
||||||
add_action('wp_head', 'custom_open_graph_tags_with_sportspress_integration');
|
add_action('wp_head', 'custom_open_graph_tags_with_sportspress_integration');
|
||||||
|
|
||||||
|
function asc_sp_event_matchup_image_url( $post ) {
|
||||||
|
if ( is_numeric( $post ) ) {
|
||||||
|
$post = get_post( $post );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $post || 'sp_event' !== $post->post_type ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_site_url() . '/head-to-head?post=' . $post->ID;
|
||||||
|
}
|
||||||
|
|
||||||
function asc_generate_sp_event_title( $post ) {
|
function asc_generate_sp_event_title( $post ) {
|
||||||
// See https://github.com/ThemeBoy/SportsPress/blob/770fa8c6654d7d6648791e877709c2428677635b/includes/admin/post-types/class-sp-admin-cpt-event.php#L99C40-L99C55
|
// See https://github.com/ThemeBoy/SportsPress/blob/770fa8c6654d7d6648791e877709c2428677635b/includes/admin/post-types/class-sp-admin-cpt-event.php#L99C40-L99C55
|
||||||
if ( is_numeric( $post ) ) {
|
if ( is_numeric( $post ) ) {
|
||||||
@@ -175,7 +187,7 @@ function custom_open_graph_tags_with_sportspress_integration() {
|
|||||||
$description .= " " . "{$teams_result_array[0]['team_name']} ({$teams_result_array[0]['outcome']}), {$teams_result_array[1]['team_name']} ({$teams_result_array[1]['outcome']})." ;
|
$description .= " " . "{$teams_result_array[0]['team_name']} ({$teams_result_array[0]['outcome']}), {$teams_result_array[1]['team_name']} ({$teams_result_array[1]['outcome']})." ;
|
||||||
}
|
}
|
||||||
$description .= " " . $post->post_content;
|
$description .= " " . $post->post_content;
|
||||||
$image = get_site_url() . "/head-to-head?post={$post->ID}";
|
$image = asc_sp_event_matchup_image_url( $post );
|
||||||
echo '<meta property="og:type" content="article" />' . "\n";
|
echo '<meta property="og:type" content="article" />' . "\n";
|
||||||
echo '<meta property="og:image" content="'. $image . '" />' . "\n";
|
echo '<meta property="og:image" content="'. $image . '" />' . "\n";
|
||||||
echo '<meta property="og:title" content="' . $title . '" />' . "\n";
|
echo '<meta property="og:title" content="' . $title . '" />' . "\n";
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ function tse_sp_event_export_get_column_definitions() {
|
|||||||
'away_team' => __( 'Away Team', 'tonys-sportspress-enhancements' ),
|
'away_team' => __( 'Away Team', 'tonys-sportspress-enhancements' ),
|
||||||
'home_team' => __( 'Home Team', 'tonys-sportspress-enhancements' ),
|
'home_team' => __( 'Home Team', 'tonys-sportspress-enhancements' ),
|
||||||
'field_name' => __( 'Field Name', 'tonys-sportspress-enhancements' ),
|
'field_name' => __( 'Field Name', 'tonys-sportspress-enhancements' ),
|
||||||
|
'field_address' => __( 'Field Address', 'tonys-sportspress-enhancements' ),
|
||||||
'officials' => __( 'Officials', 'tonys-sportspress-enhancements' ),
|
'officials' => __( 'Officials', 'tonys-sportspress-enhancements' ),
|
||||||
),
|
),
|
||||||
'team' => array(
|
'team' => array(
|
||||||
@@ -65,6 +66,7 @@ function tse_sp_event_export_get_column_definitions() {
|
|||||||
'opponent_name' => __( 'Opponent', 'tonys-sportspress-enhancements' ),
|
'opponent_name' => __( 'Opponent', 'tonys-sportspress-enhancements' ),
|
||||||
'location_flag' => __( 'Home/Away', 'tonys-sportspress-enhancements' ),
|
'location_flag' => __( 'Home/Away', 'tonys-sportspress-enhancements' ),
|
||||||
'field_name' => __( 'Field Name', 'tonys-sportspress-enhancements' ),
|
'field_name' => __( 'Field Name', 'tonys-sportspress-enhancements' ),
|
||||||
|
'field_address' => __( 'Field Address', 'tonys-sportspress-enhancements' ),
|
||||||
'field_abbreviation' => __( 'Field Abbreviation', 'tonys-sportspress-enhancements' ),
|
'field_abbreviation' => __( 'Field Abbreviation', 'tonys-sportspress-enhancements' ),
|
||||||
'field_short_name' => __( 'Field Short Name', 'tonys-sportspress-enhancements' ),
|
'field_short_name' => __( 'Field Short Name', 'tonys-sportspress-enhancements' ),
|
||||||
'officials' => __( 'Officials', 'tonys-sportspress-enhancements' ),
|
'officials' => __( 'Officials', 'tonys-sportspress-enhancements' ),
|
||||||
@@ -332,6 +334,7 @@ function tse_sp_event_export_get_events( $filters ) {
|
|||||||
'home_team' => $home_id > 0 ? get_the_title( $home_id ) : '',
|
'home_team' => $home_id > 0 ? get_the_title( $home_id ) : '',
|
||||||
'away_team' => $away_id > 0 ? get_the_title( $away_id ) : '',
|
'away_team' => $away_id > 0 ? get_the_title( $away_id ) : '',
|
||||||
'field_name' => isset( $venue['name'] ) ? $venue['name'] : '',
|
'field_name' => isset( $venue['name'] ) ? $venue['name'] : '',
|
||||||
|
'field_address' => isset( $venue['address'] ) ? $venue['address'] : '',
|
||||||
'field_abbreviation' => isset( $venue['abbreviation'] ) ? $venue['abbreviation'] : '',
|
'field_abbreviation' => isset( $venue['abbreviation'] ) ? $venue['abbreviation'] : '',
|
||||||
'field_short_name' => isset( $venue['short_name'] ) ? $venue['short_name'] : '',
|
'field_short_name' => isset( $venue['short_name'] ) ? $venue['short_name'] : '',
|
||||||
'season' => tse_sp_event_export_get_event_term_names( $event_id, 'sp_season' ),
|
'season' => tse_sp_event_export_get_event_term_names( $event_id, 'sp_season' ),
|
||||||
@@ -380,15 +383,18 @@ function tse_sp_event_export_get_primary_field( $event_id ) {
|
|||||||
if ( ! is_array( $venues ) || ! isset( $venues[0] ) || ! $venues[0] instanceof WP_Term ) {
|
if ( ! is_array( $venues ) || ! isset( $venues[0] ) || ! $venues[0] instanceof WP_Term ) {
|
||||||
return array(
|
return array(
|
||||||
'name' => '',
|
'name' => '',
|
||||||
|
'address' => '',
|
||||||
'abbreviation' => '',
|
'abbreviation' => '',
|
||||||
'short_name' => '',
|
'short_name' => '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$venue = $venues[0];
|
$venue = $venues[0];
|
||||||
|
$meta = get_option( 'taxonomy_' . $venue->term_id );
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'name' => isset( $venue->name ) ? (string) $venue->name : '',
|
'name' => isset( $venue->name ) ? (string) $venue->name : '',
|
||||||
|
'address' => is_array( $meta ) && isset( $meta['sp_address'] ) ? trim( (string) $meta['sp_address'] ) : '',
|
||||||
'abbreviation' => trim( (string) get_term_meta( $venue->term_id, 'tse_abbreviation', true ) ),
|
'abbreviation' => trim( (string) get_term_meta( $venue->term_id, 'tse_abbreviation', true ) ),
|
||||||
'short_name' => trim( (string) get_term_meta( $venue->term_id, 'tse_short_name', true ) ),
|
'short_name' => trim( (string) get_term_meta( $venue->term_id, 'tse_short_name', true ) ),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -83,11 +83,7 @@ if ( ! class_exists( 'Tony_Sportspress_GitHub_Updater' ) ) {
|
|||||||
$remote_version = $this->normalize_version( $release['version'] );
|
$remote_version = $this->normalize_version( $release['version'] );
|
||||||
$current_version = $this->normalize_version( TONY_SPORTSPRESS_ENHANCEMENTS_VERSION );
|
$current_version = $this->normalize_version( TONY_SPORTSPRESS_ENHANCEMENTS_VERSION );
|
||||||
|
|
||||||
if ( version_compare( $remote_version, $current_version, '<=' ) ) {
|
$plugin_data = (object) array(
|
||||||
return $transient;
|
|
||||||
}
|
|
||||||
|
|
||||||
$transient->response[ $this->plugin_basename ] = (object) array(
|
|
||||||
'id' => $release['url'],
|
'id' => $release['url'],
|
||||||
'slug' => $this->plugin_slug,
|
'slug' => $this->plugin_slug,
|
||||||
'plugin' => $this->plugin_basename,
|
'plugin' => $this->plugin_basename,
|
||||||
@@ -102,6 +98,16 @@ if ( ! class_exists( 'Tony_Sportspress_GitHub_Updater' ) ) {
|
|||||||
'translations' => array(),
|
'translations' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( version_compare( $remote_version, $current_version, '<=' ) ) {
|
||||||
|
unset( $transient->response[ $this->plugin_basename ] );
|
||||||
|
$transient->no_update[ $this->plugin_basename ] = $plugin_data;
|
||||||
|
|
||||||
|
return $transient;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset( $transient->no_update[ $this->plugin_basename ] );
|
||||||
|
$transient->response[ $this->plugin_basename ] = $plugin_data;
|
||||||
|
|
||||||
return $transient;
|
return $transient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* SportsPress schedule exporter admin page.
|
* SportsPress schedule exporter frontend and shared helpers.
|
||||||
*
|
*
|
||||||
* @package Tonys_Sportspress_Enhancements
|
* @package Tonys_Sportspress_Enhancements
|
||||||
*/
|
*/
|
||||||
@@ -9,22 +9,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the schedule exporter admin page.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function tse_sp_schedule_exporter_add_admin_page() {
|
|
||||||
add_submenu_page(
|
|
||||||
'sportspress',
|
|
||||||
__( 'Schedule Exporter', 'tonys-sportspress-enhancements' ),
|
|
||||||
__( 'Schedule Exporter', 'tonys-sportspress-enhancements' ),
|
|
||||||
'manage_sportspress',
|
|
||||||
'tse-schedule-exporter',
|
|
||||||
'tse_sp_schedule_exporter_render_admin_page'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
add_action( 'admin_menu', 'tse_sp_schedule_exporter_add_admin_page' );
|
|
||||||
add_shortcode( 'tse_schedule_exporter', 'tse_sp_schedule_exporter_render_shortcode' );
|
add_shortcode( 'tse_schedule_exporter', 'tse_sp_schedule_exporter_render_shortcode' );
|
||||||
add_action( 'init', 'tse_sp_schedule_exporter_register_block' );
|
add_action( 'init', 'tse_sp_schedule_exporter_register_block' );
|
||||||
|
|
||||||
@@ -91,175 +75,6 @@ function tse_sp_schedule_exporter_register_block() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
$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();
|
|
||||||
|
|
||||||
echo '<div class="wrap">';
|
|
||||||
echo '<h1>' . esc_html__( 'Schedule Exporter', 'tonys-sportspress-enhancements' ) . '</h1>';
|
|
||||||
echo '<p>' . esc_html__( 'Choose filters once, then generate the CSV feed, iCal link, or printable page URL from the same controls.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
|
|
||||||
echo '<form method="get" action="' . esc_url( admin_url( 'admin.php' ) ) . '" class="tse-schedule-exporter-form" style="max-width:720px;margin:20px 0 28px;">';
|
|
||||||
echo '<input type="hidden" name="page" value="tse-schedule-exporter" />';
|
|
||||||
echo '<div>';
|
|
||||||
|
|
||||||
echo '<div style="margin-bottom:16px;">';
|
|
||||||
echo '<label for="tse-schedule-exporter-export-type"><strong>' . esc_html__( 'Format', 'tonys-sportspress-enhancements' ) . '</strong></label><br />';
|
|
||||||
echo '<select id="tse-schedule-exporter-export-type" name="export_type">';
|
|
||||||
foreach ( tse_sp_schedule_exporter_get_export_types() as $type_key => $type_label ) {
|
|
||||||
printf(
|
|
||||||
'<option value="%1$s" %2$s>%3$s</option>',
|
|
||||||
esc_attr( $type_key ),
|
|
||||||
selected( $export_type, $type_key, false ),
|
|
||||||
esc_html( $type_label )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
echo '</select>';
|
|
||||||
echo '<p class="description">' . esc_html__( 'CSV builds a feed URL, iCal Link builds a subscription URL, and Printable opens the printable page.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
echo '</div>';
|
|
||||||
|
|
||||||
echo '<div data-subformat-wrap="1" style="margin-bottom:16px;">';
|
|
||||||
echo '<label for="tse-schedule-exporter-subformat"><strong>' . esc_html__( 'CSV Layout', 'tonys-sportspress-enhancements' ) . '</strong></label><br />';
|
|
||||||
echo '<select id="tse-schedule-exporter-subformat" name="subformat">';
|
|
||||||
foreach ( tse_sp_event_export_get_formats() as $format_key => $format_definition ) {
|
|
||||||
printf(
|
|
||||||
'<option value="%1$s" %2$s>%3$s</option>',
|
|
||||||
esc_attr( $format_key ),
|
|
||||||
selected( $subformat, $format_key, false ),
|
|
||||||
esc_html( $format_definition['label'] )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
echo '</select>';
|
|
||||||
echo '<p class="description">' . esc_html__( 'Matchup is away vs home. Team is opponent-based and requires one specific team.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
echo '</div>';
|
|
||||||
|
|
||||||
echo '<div style="margin-bottom:16px;">';
|
|
||||||
echo '<label for="tse-schedule-exporter-league"><strong>' . esc_html__( 'League', 'tonys-sportspress-enhancements' ) . '</strong></label><br />';
|
|
||||||
echo '<select id="tse-schedule-exporter-league" name="league_id" data-auto-submit="1">';
|
|
||||||
foreach ( $leagues as $league ) {
|
|
||||||
printf(
|
|
||||||
'<option value="%1$s" %2$s>%3$s</option>',
|
|
||||||
esc_attr( (string) $league->term_id ),
|
|
||||||
selected( $league_id, (int) $league->term_id, false ),
|
|
||||||
esc_html( $league->name )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
echo '</select>';
|
|
||||||
echo '</div>';
|
|
||||||
|
|
||||||
echo '<div style="margin-bottom:16px;">';
|
|
||||||
echo '<label for="tse-schedule-exporter-season"><strong>' . esc_html__( 'Season', 'tonys-sportspress-enhancements' ) . '</strong></label><br />';
|
|
||||||
echo '<select id="tse-schedule-exporter-season" name="season_id" data-auto-submit="1">';
|
|
||||||
echo '<option value="0">' . esc_html__( 'Current / All matching events', 'tonys-sportspress-enhancements' ) . '</option>';
|
|
||||||
foreach ( $seasons as $season ) {
|
|
||||||
printf(
|
|
||||||
'<option value="%1$s" %2$s>%3$s</option>',
|
|
||||||
esc_attr( (string) $season->term_id ),
|
|
||||||
selected( $season_id, (int) $season->term_id, false ),
|
|
||||||
esc_html( $season->name )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
echo '</select>';
|
|
||||||
echo '</div>';
|
|
||||||
|
|
||||||
echo '<div style="margin-bottom:16px;">';
|
|
||||||
echo '<label for="tse-schedule-exporter-team"><strong>' . esc_html__( 'Team', 'tonys-sportspress-enhancements' ) . '</strong></label><br />';
|
|
||||||
echo '<select id="tse-schedule-exporter-team" name="team_id">';
|
|
||||||
echo '<option value="0">' . esc_html__( 'All teams', 'tonys-sportspress-enhancements' ) . '</option>';
|
|
||||||
foreach ( $teams as $team ) {
|
|
||||||
printf(
|
|
||||||
'<option value="%1$s" %2$s>%3$s</option>',
|
|
||||||
esc_attr( (string) $team->ID ),
|
|
||||||
selected( $team_id, (int) $team->ID, false ),
|
|
||||||
esc_html( $team->post_title )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
echo '</select>';
|
|
||||||
echo '<p class="description">' . esc_html__( 'Teams are filtered by the selected league and season.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
echo '</div>';
|
|
||||||
|
|
||||||
echo '<div style="margin-bottom:16px;">';
|
|
||||||
echo '<label for="tse-schedule-exporter-field"><strong>' . esc_html__( 'Field', 'tonys-sportspress-enhancements' ) . '</strong></label><br />';
|
|
||||||
echo '<select id="tse-schedule-exporter-field" name="field_id">';
|
|
||||||
echo '<option value="0">' . esc_html__( 'All fields', 'tonys-sportspress-enhancements' ) . '</option>';
|
|
||||||
foreach ( $fields as $field ) {
|
|
||||||
printf(
|
|
||||||
'<option value="%1$s" %2$s>%3$s</option>',
|
|
||||||
esc_attr( (string) $field->term_id ),
|
|
||||||
selected( $field_id, (int) $field->term_id, false ),
|
|
||||||
esc_html( $field->name )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
echo '</select>';
|
|
||||||
echo '<p class="description">' . esc_html__( 'Use the field filter to narrow the feed to a specific venue.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
echo '</div>';
|
|
||||||
|
|
||||||
echo '</div>';
|
|
||||||
echo '</form>';
|
|
||||||
|
|
||||||
if ( empty( $teams ) ) {
|
|
||||||
echo '<div class="notice notice-warning inline"><p>' . esc_html__( 'No SportsPress teams match the selected league and season.', 'tonys-sportspress-enhancements' ) . '</p></div>';
|
|
||||||
echo '</div>';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '<div style="max-width:960px;padding:20px 24px;border:1px solid #dcdcde;background:#fff;">';
|
|
||||||
echo '<h2 style="margin-top:0;">' . esc_html__( 'Output URL', 'tonys-sportspress-enhancements' ) . '</h2>';
|
|
||||||
echo '<p>' . esc_html__( 'The generated URL below updates from the shared controls above.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
|
|
||||||
tse_sp_schedule_exporter_render_column_picker( 'matchup', 'admin', $subformat );
|
|
||||||
tse_sp_schedule_exporter_render_column_picker( 'team', 'admin', $subformat );
|
|
||||||
|
|
||||||
$base_args = array(
|
|
||||||
'league_id' => $league_id,
|
|
||||||
'team_id' => $team_id,
|
|
||||||
'season_id' => $season_id,
|
|
||||||
'field_id' => $field_id,
|
|
||||||
'format' => $subformat,
|
|
||||||
);
|
|
||||||
$csv_url = tse_sp_event_export_get_feed_url( $base_args, 'csv' );
|
|
||||||
$ics_url = tse_sp_event_export_get_feed_url(
|
|
||||||
array(
|
|
||||||
'league_id' => $league_id,
|
|
||||||
'team_id' => $team_id,
|
|
||||||
'season_id' => $season_id,
|
|
||||||
'field_id' => $field_id,
|
|
||||||
),
|
|
||||||
'ics'
|
|
||||||
);
|
|
||||||
$print_url = tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, 'letter', $league_id );
|
|
||||||
$current_url = tse_sp_schedule_exporter_get_output_url( $export_type, $csv_url, $ics_url, $print_url );
|
|
||||||
|
|
||||||
echo '<div style="display:flex;align-items:center;gap:8px;max-width:100%;margin-top:16px;">';
|
|
||||||
echo '<input type="text" class="large-text code tse-output-url" readonly="readonly" value="' . esc_attr( $current_url ) . '" />';
|
|
||||||
echo '<button type="button" class="button tse-copy-link" title="' . esc_attr__( 'Copy URL', 'tonys-sportspress-enhancements' ) . '">' . esc_html__( 'Copy URL', 'tonys-sportspress-enhancements' ) . '</button>';
|
|
||||||
echo '<button type="button" class="button button-primary tse-open-link" data-csv-url="' . esc_url( $csv_url ) . '" data-ics-url="' . esc_url( $ics_url ) . '" data-print-url="' . esc_url( $print_url ) . '" title="' . esc_attr__( 'Open URL in new tab', 'tonys-sportspress-enhancements' ) . '">' . esc_html__( 'Open URL in New Tab', 'tonys-sportspress-enhancements' ) . '</button>';
|
|
||||||
echo '<button type="button" class="button button-primary tse-ics-ios-link" data-ics-url="' . esc_url( $ics_url ) . '" title="' . esc_attr__( 'Subscribe on iPhone or iPad', 'tonys-sportspress-enhancements' ) . '" style="display:none;">' . esc_html__( 'Subscribe on iPhone/iPad', 'tonys-sportspress-enhancements' ) . '</button>';
|
|
||||||
echo '<button type="button" class="button tse-ics-android-link" data-ics-url="' . esc_url( $ics_url ) . '" title="' . esc_attr__( 'Subscribe on Android', 'tonys-sportspress-enhancements' ) . '" style="display:none;">' . esc_html__( 'Subscribe on Android', 'tonys-sportspress-enhancements' ) . '</button>';
|
|
||||||
echo '</div>';
|
|
||||||
echo '<p class="description tse-output-note">' . esc_html__( 'Use the buttons to copy the generated URL or open the right destination for this export type.', 'tonys-sportspress-enhancements' ) . '</p>';
|
|
||||||
tse_sp_schedule_exporter_render_link_sync_script( true );
|
|
||||||
echo '</div>';
|
|
||||||
echo '</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the public shortcode.
|
* Render the public shortcode.
|
||||||
*
|
*
|
||||||
|
|||||||
2679
includes/sp-webhooks.php
Normal file
2679
includes/sp-webhooks.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"name": "tonys-sportspress-enhancements",
|
"name": "tonys-sportspress-enhancements",
|
||||||
"version": "0.1.5",
|
"version": "0.1.11",
|
||||||
"main": "Gruntfile.js",
|
"main": "Gruntfile.js",
|
||||||
"author": "YOUR NAME HERE",
|
"author": "YOUR NAME HERE",
|
||||||
"scripts" : {
|
"scripts" : {
|
||||||
|
|||||||
408
tests/test-sp-webhooks.php
Normal file
408
tests/test-sp-webhooks.php
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Tests for configurable SportsPress webhooks.
|
||||||
|
*
|
||||||
|
* @package Tonys_Sportspress_Enhancements
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webhook feature tests.
|
||||||
|
*/
|
||||||
|
class Test_SP_Webhooks extends WP_UnitTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template placeholders should resolve nested values and JSON serialization.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_dot_paths_and_tojson() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Trigger={{ trigger.key }} Team={{ event.teams.0.name }} Image={{ event.image }} Payload={{ event|tojson }}';
|
||||||
|
$context = array(
|
||||||
|
'trigger' => array(
|
||||||
|
'key' => 'event_results_updated',
|
||||||
|
),
|
||||||
|
'event' => array(
|
||||||
|
'id' => 55,
|
||||||
|
'image' => 'https://example.com/head-to-head?post=55',
|
||||||
|
'teams' => array(
|
||||||
|
array(
|
||||||
|
'name' => 'Blue Team',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertStringContainsString( 'Trigger=event_results_updated', $rendered );
|
||||||
|
$this->assertStringContainsString( 'Team=Blue Team', $rendered );
|
||||||
|
$this->assertStringContainsString( 'Image=https://example.com/head-to-head?post=55', $rendered );
|
||||||
|
$this->assertStringContainsString( '"id":55', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Venue aliases and split schedule fields should render from the context.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_field_alias_and_schedule_parts() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Field={{ event.field.short_name }} Venue={{ event.venue.abbreviation }} Time={{ event.scheduled.time }} {{ event.scheduled.timezone }}';
|
||||||
|
$context = array(
|
||||||
|
'event' => array(
|
||||||
|
'field' => array(
|
||||||
|
'short_name' => 'North',
|
||||||
|
),
|
||||||
|
'venue' => array(
|
||||||
|
'abbreviation' => 'NF',
|
||||||
|
),
|
||||||
|
'scheduled' => array(
|
||||||
|
'time' => '7:30 PM',
|
||||||
|
'timezone' => 'CDT',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Field=North Venue=NF Time=7:30 PM CDT', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event context should expose home and away team aliases.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_event_team_aliases() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Home={{ event.home_team.name }} Away={{ event.away_team.name }}';
|
||||||
|
$context = array(
|
||||||
|
'event' => array(
|
||||||
|
'home_team' => array(
|
||||||
|
'name' => 'Home Team',
|
||||||
|
),
|
||||||
|
'away_team' => array(
|
||||||
|
'name' => 'Away Team',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Home=Home Team Away=Away Team', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event context should expose the current SportsPress schedule status.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_event_status_alias() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Status={{ event.status }}';
|
||||||
|
$context = array(
|
||||||
|
'event' => array(
|
||||||
|
'status' => 'Postponed',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Status=Postponed', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date filter should accept PHP date format strings for schedule values.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_date_filter() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Time={{ event.scheduled.timestamp|date("g:i A") }} ISO={{ event.scheduled.local_iso|date("m/d g:i A") }}';
|
||||||
|
$context = array(
|
||||||
|
'event' => array(
|
||||||
|
'scheduled' => array(
|
||||||
|
'timestamp' => 1714005000,
|
||||||
|
'local_iso' => '2024-04-24T19:30:00-05:00',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Time=7:30 PM ISO=04/24 7:30 PM', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change notifications should expose before and after venue/time values.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_before_after_venue_and_time() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Venue {{ changes.previous.venue.name }} -> {{ changes.current.venue.name }} Time {{ changes.previous.time }} -> {{ changes.current.time }}';
|
||||||
|
$context = array(
|
||||||
|
'changes' => array(
|
||||||
|
'previous' => array(
|
||||||
|
'time' => '6:00 PM',
|
||||||
|
'venue' => array(
|
||||||
|
'name' => 'North Field',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'current' => array(
|
||||||
|
'time' => '7:30 PM',
|
||||||
|
'venue' => array(
|
||||||
|
'name' => 'South Field',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Venue North Field -> South Field Time 6:00 PM -> 7:30 PM', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change notifications should expose before and after home/away team values.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_before_after_teams() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Home {{ changes.previous.home_team.name }} -> {{ changes.current.home_team.name }} Away {{ changes.previous.away_team.name }} -> {{ changes.current.away_team.name }}';
|
||||||
|
$context = array(
|
||||||
|
'changes' => array(
|
||||||
|
'previous' => array(
|
||||||
|
'home_team' => array(
|
||||||
|
'name' => 'Old Home',
|
||||||
|
),
|
||||||
|
'away_team' => array(
|
||||||
|
'name' => 'Old Away',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'current' => array(
|
||||||
|
'home_team' => array(
|
||||||
|
'name' => 'New Home',
|
||||||
|
),
|
||||||
|
'away_team' => array(
|
||||||
|
'name' => 'New Away',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Home Old Home -> New Home Away Old Away -> New Away', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change notifications should expose before and after status values.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_before_after_status() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = 'Status {{ changes.previous.status }} -> {{ changes.current.status }}';
|
||||||
|
$context = array(
|
||||||
|
'changes' => array(
|
||||||
|
'previous' => array(
|
||||||
|
'status' => 'On time',
|
||||||
|
),
|
||||||
|
'current' => array(
|
||||||
|
'status' => 'Postponed',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Status On time -> Postponed', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule snapshots should treat status changes as meaningful changes.
|
||||||
|
*/
|
||||||
|
public function test_schedule_snapshot_signature_changes_when_status_changes() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$method = new ReflectionMethod( $webhooks, 'schedule_snapshots_match' );
|
||||||
|
$method->setAccessible( true );
|
||||||
|
|
||||||
|
$left = array(
|
||||||
|
'local_iso' => '2026-05-02T10:30:00-05:00',
|
||||||
|
'gmt_iso' => '2026-05-02T15:30:00+00:00',
|
||||||
|
'status' => 'On time',
|
||||||
|
'venue' => array(
|
||||||
|
'name' => 'Winnemac Park',
|
||||||
|
),
|
||||||
|
'teams' => array(
|
||||||
|
array( 'name' => 'Hawks' ),
|
||||||
|
array( 'name' => 'Electrons' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$right = $left;
|
||||||
|
$right['status'] = 'Canceled';
|
||||||
|
|
||||||
|
$this->assertFalse( $method->invoke( $webhooks, $left, $right ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status snapshots should expose a display label and keep the raw SportsPress key.
|
||||||
|
*/
|
||||||
|
public function test_build_change_snapshot_normalizes_status_label_and_slug() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$method = new ReflectionMethod( $webhooks, 'build_change_snapshot' );
|
||||||
|
$method->setAccessible( true );
|
||||||
|
|
||||||
|
$snapshot = $method->invoke( $webhooks, array(), array(), array(), 'cancelled' );
|
||||||
|
|
||||||
|
$this->assertSame( 'Canceled', $snapshot['status'] );
|
||||||
|
$this->assertSame( 'cancelled', $snapshot['sp_status'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conditionals should support simple comparisons and else branches.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_conditionals() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = "{% if changes.previous.time != changes.current.time %}Time changed: {{ changes.previous.time }} -> {{ changes.current.time }}\n{% endif %}{% if changes.previous.field.name == changes.current.field.name %}Field unchanged{% else %}Field changed: {{ changes.previous.field.name }} -> {{ changes.current.field.name }}{% endif %}";
|
||||||
|
$context = array(
|
||||||
|
'changes' => array(
|
||||||
|
'previous' => array(
|
||||||
|
'time' => '6:00 PM',
|
||||||
|
'field' => array(
|
||||||
|
'name' => 'North Field',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'current' => array(
|
||||||
|
'time' => '7:30 PM',
|
||||||
|
'field' => array(
|
||||||
|
'name' => 'South Field',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( "Time changed: 6:00 PM -> 7:30 PM\nField changed: North Field -> South Field", $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truthy conditionals should render when the referenced value exists.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_truthy_conditionals() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = '{% if changes.current.home_team.name %}Home: {{ changes.current.home_team.name }}{% endif %}';
|
||||||
|
$context = array(
|
||||||
|
'changes' => array(
|
||||||
|
'current' => array(
|
||||||
|
'home_team' => array(
|
||||||
|
'name' => 'Home Team',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Home: Home Team', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Team change conditionals should stay false when only schedule fields changed.
|
||||||
|
*/
|
||||||
|
public function test_team_conditionals_do_not_fire_for_schedule_only_changes() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = '{% if changes.previous.away_team.name != changes.current.away_team.name %}Away changed{% else %}Away unchanged{% endif %}';
|
||||||
|
$context = array(
|
||||||
|
'changes' => array(
|
||||||
|
'previous' => array(
|
||||||
|
'time' => '6:00 PM',
|
||||||
|
'away_team' => array(
|
||||||
|
'name' => 'Away Team',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'current' => array(
|
||||||
|
'time' => '7:30 PM',
|
||||||
|
'away_team' => array(
|
||||||
|
'name' => 'Away Team',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Away unchanged', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conditionals should support simple or expressions with else branches.
|
||||||
|
*/
|
||||||
|
public function test_render_template_supports_or_conditionals() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$template = '{% if event.status == "Postponed" or event.status == "Canceled" %}Delayed{% else %}Normal{% endif %}';
|
||||||
|
$context = array(
|
||||||
|
'event' => array(
|
||||||
|
'status' => 'Canceled',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $webhooks->render_template( $template, $context );
|
||||||
|
|
||||||
|
$this->assertSame( 'Delayed', $rendered );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test webhook AJAX should honor the submitted row index.
|
||||||
|
*/
|
||||||
|
public function test_get_submitted_test_webhook_row_uses_matching_index() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$method = new ReflectionMethod( $webhooks, 'get_submitted_test_webhook_row' );
|
||||||
|
$method->setAccessible( true );
|
||||||
|
|
||||||
|
$result = $method->invoke(
|
||||||
|
$webhooks,
|
||||||
|
array(
|
||||||
|
'2' => array(
|
||||||
|
'name' => 'Second Row',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'2' => '123',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertSame( 'Second Row', $result['row']['name'] );
|
||||||
|
$this->assertSame( 123, $result['event_id'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitization should keep only complete provider-specific webhook rows.
|
||||||
|
*/
|
||||||
|
public function test_sanitize_settings_keeps_only_valid_webhooks() {
|
||||||
|
$webhooks = Tony_Sportspress_Webhooks::instance();
|
||||||
|
$sanitized = $webhooks->sanitize_settings(
|
||||||
|
array(
|
||||||
|
'webhooks' => array(
|
||||||
|
array(
|
||||||
|
'name' => 'Results',
|
||||||
|
'enabled' => '1',
|
||||||
|
'provider' => 'google_chat',
|
||||||
|
'url' => 'https://chat.googleapis.com/v1/spaces/AAA/messages?key=test&token=test',
|
||||||
|
'triggers' => array( 'event_results_updated' ),
|
||||||
|
'template' => '{"summary":"{{ results.summary }}"}',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Invalid',
|
||||||
|
'enabled' => '1',
|
||||||
|
'provider' => 'groupme_bot',
|
||||||
|
'url' => 'invalid bot id',
|
||||||
|
'triggers' => array( 'event_datetime_changed' ),
|
||||||
|
'template' => 'ignored',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Missing trigger',
|
||||||
|
'enabled' => '1',
|
||||||
|
'provider' => 'generic_json',
|
||||||
|
'url' => 'https://example.com/missing-trigger',
|
||||||
|
'template' => 'ignored',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertCount( 1, $sanitized['webhooks'] );
|
||||||
|
$this->assertSame( 'Results', $sanitized['webhooks'][0]['name'] );
|
||||||
|
$this->assertSame( 'google_chat', $sanitized['webhooks'][0]['provider'] );
|
||||||
|
$this->assertSame( 'https://chat.googleapis.com/v1/spaces/AAA/messages?key=test&token=test', $sanitized['webhooks'][0]['url'] );
|
||||||
|
$this->assertSame( array( 'event_results_updated' ), $sanitized['webhooks'][0]['triggers'] );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
* Text Domain: tonys-sportspress-enhancements
|
* Text Domain: tonys-sportspress-enhancements
|
||||||
* Domain Path: /languages
|
* Domain Path: /languages
|
||||||
* Update URI: https://github.com/anthonyscorrea/tonys-sportspress-enhancements
|
* Update URI: https://github.com/anthonyscorrea/tonys-sportspress-enhancements
|
||||||
* Version: 0.1.8
|
* Version: 0.1.11
|
||||||
*
|
*
|
||||||
* @package Tonys_Sportspress_Enhancements
|
* @package Tonys_Sportspress_Enhancements
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( ! defined( 'TONY_SPORTSPRESS_ENHANCEMENTS_VERSION' ) ) {
|
if ( ! defined( 'TONY_SPORTSPRESS_ENHANCEMENTS_VERSION' ) ) {
|
||||||
define( 'TONY_SPORTSPRESS_ENHANCEMENTS_VERSION', '0.1.8' );
|
define( 'TONY_SPORTSPRESS_ENHANCEMENTS_VERSION', '0.1.11' );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! defined( 'TONY_SPORTSPRESS_ENHANCEMENTS_FILE' ) ) {
|
if ( ! defined( 'TONY_SPORTSPRESS_ENHANCEMENTS_FILE' ) ) {
|
||||||
@@ -46,6 +46,7 @@ require_once plugin_dir_path(__FILE__) . 'includes/sp-event-quick-edit-officials
|
|||||||
require_once plugin_dir_path(__FILE__) . 'includes/sp-event-team-ordering.php';
|
require_once plugin_dir_path(__FILE__) . 'includes/sp-event-team-ordering.php';
|
||||||
require_once plugin_dir_path(__FILE__) . 'includes/sp-printable-calendars.php';
|
require_once plugin_dir_path(__FILE__) . 'includes/sp-printable-calendars.php';
|
||||||
require_once plugin_dir_path(__FILE__) . 'includes/sp-url-builder.php';
|
require_once plugin_dir_path(__FILE__) . 'includes/sp-url-builder.php';
|
||||||
|
require_once plugin_dir_path(__FILE__) . 'includes/sp-webhooks.php';
|
||||||
require_once plugin_dir_path(__FILE__) . 'includes/sp-schedule-exporter.php';
|
require_once plugin_dir_path(__FILE__) . 'includes/sp-schedule-exporter.php';
|
||||||
require_once plugin_dir_path(__FILE__) . 'includes/sp-venue-meta.php';
|
require_once plugin_dir_path(__FILE__) . 'includes/sp-venue-meta.php';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user