466 lines
22 KiB
PHP
466 lines
22 KiB
PHP
<?php
|
|
|
|
class Swi_Foot_Admin
|
|
{
|
|
|
|
public function __construct()
|
|
{
|
|
add_action('admin_menu', array($this, 'add_admin_menu'));
|
|
add_action('admin_init', array($this, 'settings_init'));
|
|
add_action('admin_enqueue_scripts', array($this, 'admin_scripts'));
|
|
add_action('add_meta_boxes', array($this, 'add_match_meta_boxes'));
|
|
// Finished-match deletion moved to REST endpoints (see includes/class-swi-foot-rest.php)
|
|
}
|
|
|
|
public function add_admin_menu()
|
|
{
|
|
add_options_page(
|
|
__('Swiss Football Matchdata Settings', 'swi_foot_matchdata'),
|
|
__('Swiss Football', 'swi_foot_matchdata'),
|
|
'manage_options',
|
|
'swiss-football-matchdata',
|
|
array($this, 'options_page')
|
|
);
|
|
}
|
|
|
|
public function settings_init()
|
|
{
|
|
register_setting('swi_foot_settings', 'swi_foot_api_base_url');
|
|
register_setting('swi_foot_settings', 'swi_foot_api_username');
|
|
register_setting('swi_foot_settings', 'swi_foot_api_password');
|
|
register_setting('swi_foot_settings', 'swi_foot_verein_id');
|
|
register_setting('swi_foot_settings', 'swi_foot_season_id');
|
|
register_setting('swi_foot_settings', 'swi_foot_match_cache_duration');
|
|
|
|
add_settings_section(
|
|
'swi_foot_api_section',
|
|
__('API Configuration', 'swi_foot_matchdata'),
|
|
array($this, 'api_section_callback'),
|
|
'swi_foot_settings'
|
|
);
|
|
|
|
add_settings_field('swi_foot_api_base_url', __('API Base URL', 'swi_foot_matchdata'), array($this, 'base_url_render'), 'swi_foot_settings', 'swi_foot_api_section');
|
|
add_settings_field('swi_foot_api_username', __('API Username (Application Key)', 'swi_foot_matchdata'), array($this, 'username_render'), 'swi_foot_settings', 'swi_foot_api_section');
|
|
add_settings_field('swi_foot_api_password', __('API Password (Application Pass)', 'swi_foot_matchdata'), array($this, 'password_render'), 'swi_foot_settings', 'swi_foot_api_section');
|
|
add_settings_field('swi_foot_verein_id', __('Verein ID (Club ID)', 'swi_foot_matchdata'), array($this, 'verein_id_render'), 'swi_foot_settings', 'swi_foot_api_section');
|
|
add_settings_field('swi_foot_season_id', __('Season ID', 'swi_foot_matchdata'), array($this, 'season_id_render'), 'swi_foot_settings', 'swi_foot_api_section');
|
|
|
|
add_settings_section(
|
|
'swi_foot_cache_section',
|
|
__('Cache Settings', 'swi_foot_matchdata'),
|
|
array($this, 'cache_section_callback'),
|
|
'swi_foot_settings'
|
|
);
|
|
|
|
add_settings_field('swi_foot_match_cache_duration', __('Match Data Cache Duration (seconds)', 'swi_foot_matchdata'), array($this, 'cache_duration_render'), 'swi_foot_settings', 'swi_foot_cache_section');
|
|
}
|
|
|
|
public function api_section_callback()
|
|
{
|
|
echo '<p>' . __('Configure your Swiss Football API credentials here.', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function cache_section_callback()
|
|
{
|
|
echo '<p>' . __('Configure caching settings for match data.', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function base_url_render()
|
|
{
|
|
$base_url = get_option('swi_foot_api_base_url', 'https://stg-club-api-services.football.ch');
|
|
echo '<input type="url" name="swi_foot_api_base_url" value="' . esc_attr($base_url) . '" class="regular-text" />';
|
|
echo '<p class="description">' . __('The base URL for the Swiss Football API', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function username_render()
|
|
{
|
|
$username = get_option('swi_foot_api_username');
|
|
echo '<input type="text" name="swi_foot_api_username" value="' . esc_attr($username) . '" class="regular-text" />';
|
|
echo '<p class="description">' . __('Your API application key', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function password_render()
|
|
{
|
|
$password = get_option('swi_foot_api_password');
|
|
echo '<input type="password" name="swi_foot_api_password" value="' . esc_attr($password) . '" class="regular-text" />';
|
|
echo '<p class="description">' . __('Your API application password', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function verein_id_render()
|
|
{
|
|
$verein_id = get_option('swi_foot_verein_id');
|
|
echo '<input type="number" name="swi_foot_verein_id" value="' . esc_attr($verein_id) . '" class="regular-text" />';
|
|
echo '<p class="description">' . __('Enter your club\'s Verein ID (Club ID)', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function season_id_render()
|
|
{
|
|
$season_id = get_option('swi_foot_season_id', date('Y'));
|
|
echo '<input type="number" name="swi_foot_season_id" value="' . esc_attr($season_id) . '" class="regular-text" min="2020" max="2030" />';
|
|
echo '<p class="description">' . __('Current season ID (usually the year)', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function cache_duration_render()
|
|
{
|
|
$duration = get_option('swi_foot_match_cache_duration', 30);
|
|
echo '<input type="number" name="swi_foot_match_cache_duration" value="' . esc_attr($duration) . '" min="10" max="300" />';
|
|
echo '<p class="description">' . __('How long to cache match data in seconds (10-300)', 'swi_foot_matchdata') . '</p>';
|
|
}
|
|
|
|
public function admin_scripts($hook)
|
|
{
|
|
if ($hook === 'settings_page_swiss-football-matchdata') {
|
|
wp_enqueue_script('swi-foot-admin', SWI_FOOT_PLUGIN_URL . 'assets/admin.js', array('jquery'), SWI_FOOT_PLUGIN_VERSION, true);
|
|
wp_localize_script('swi-foot-admin', 'swi_foot_ajax', array(
|
|
'ajax_url' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('swi_foot_nonce'),
|
|
'rest_url' => esc_url_raw(rest_url('swi-foot/v1')),
|
|
'rest_nonce' => wp_create_nonce('wp_rest')
|
|
));
|
|
wp_enqueue_style('swi-foot-admin', SWI_FOOT_PLUGIN_URL . 'assets/admin.css', array(), SWI_FOOT_PLUGIN_VERSION);
|
|
}
|
|
|
|
// Add shortcode help to post/page editors
|
|
global $pagenow;
|
|
if (in_array($pagenow, array('post.php', 'post-new.php', 'edit.php'))) {
|
|
// Enqueue the registered editor bundle so WordPress picks the built asset when available.
|
|
// The script handle `swi-foot-editor-blocks` is registered in `register_blocks()`.
|
|
wp_enqueue_script('swi-foot-editor-blocks');
|
|
|
|
// Add admin footer debug output to help diagnose missing script tags.
|
|
add_action('admin_footer', array($this, 'print_editor_script_debug'));
|
|
// Post context editor panel: allow editor to set per-post season/team/match
|
|
wp_enqueue_script('swi-foot-post-context', SWI_FOOT_PLUGIN_URL . 'assets/post-context.js', array('wp-plugins','wp-edit-post','wp-element','wp-data','wp-components'), SWI_FOOT_PLUGIN_VERSION, true);
|
|
wp_localize_script('swi-foot-post-context', 'swi_foot_post_context', array(
|
|
'rest_url' => esc_url_raw(rest_url('swi-foot/v1')),
|
|
'rest_nonce' => wp_create_nonce('wp_rest'),
|
|
'default_season' => get_option('swi_foot_season_id', date('Y'))
|
|
));
|
|
wp_enqueue_style('swi-foot-admin', SWI_FOOT_PLUGIN_URL . 'assets/admin.css', array(), SWI_FOOT_PLUGIN_VERSION);
|
|
}
|
|
}
|
|
|
|
public function print_editor_script_debug()
|
|
{
|
|
// Only show on post editor pages
|
|
$pagenow = isset($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : '';
|
|
if (!in_array($pagenow, array('post.php', 'post-new.php', 'edit.php'))) return;
|
|
|
|
// Check registration/enqueue status and attempt to find the resolved src
|
|
$registered = false;
|
|
$enqueued = false;
|
|
$src = '';
|
|
global $wp_scripts;
|
|
if (isset($wp_scripts) && is_object($wp_scripts)) {
|
|
$registered = wp_script_is('swi-foot-editor-blocks', 'registered');
|
|
$enqueued = wp_script_is('swi-foot-editor-blocks', 'enqueued');
|
|
$handle = $wp_scripts->query('swi-foot-editor-blocks', 'registered');
|
|
if ($handle && isset($wp_scripts->registered['swi-foot-editor-blocks']->src)) {
|
|
$src = $wp_scripts->registered['swi-foot-editor-blocks']->src;
|
|
}
|
|
}
|
|
|
|
$msg = array(
|
|
'registered' => $registered ? 'yes' : 'no',
|
|
'enqueued' => $enqueued ? 'yes' : 'no',
|
|
'src' => $src
|
|
);
|
|
echo "<script>console.debug('swi-foot: editor script debug', ". json_encode($msg) .");</script>";
|
|
}
|
|
|
|
public function add_match_meta_boxes()
|
|
{
|
|
add_meta_box(
|
|
'swi-foot-shortcodes',
|
|
__('Swiss Football Shortcodes', 'swi_foot_matchdata'),
|
|
array($this, 'shortcodes_meta_box'),
|
|
array('post', 'page'),
|
|
'side',
|
|
'default'
|
|
);
|
|
}
|
|
|
|
public function shortcodes_meta_box($post)
|
|
{
|
|
?>
|
|
<div class="swi-foot-shortcodes-help">
|
|
<h4><?php _e('Available Shortcodes:', 'swi_foot_matchdata'); ?></h4>
|
|
|
|
<div class="shortcode-group">
|
|
<strong><?php _e('Full Match Display:', 'swi_foot_matchdata'); ?></strong>
|
|
<code data-shortcode="[swi_foot_match match_id="12345"]">[swi_foot_match match_id="12345"]</code>
|
|
<code data-shortcode="[swi_foot_match team_id="67" show_next="true"]">[swi_foot_match team_id="67" show_next="true"]</code>
|
|
</div>
|
|
|
|
<div class="shortcode-group">
|
|
<strong><?php _e('Individual Match Elements:', 'swi_foot_matchdata'); ?></strong>
|
|
<code data-shortcode="[swi_foot_match_home_team match_id="12345"]">[swi_foot_match_home_team match_id="12345"]</code>
|
|
<code data-shortcode="[swi_foot_match_away_team match_id="12345"]">[swi_foot_match_away_team match_id="12345"]</code>
|
|
<code data-shortcode="[swi_foot_match_date match_id="12345" format="d.m.Y"]">[swi_foot_match_date match_id="12345" format="d.m.Y"]</code>
|
|
<code data-shortcode="[swi_foot_match_time match_id="12345" format="H:i"]">[swi_foot_match_time match_id="12345" format="H:i"]</code>
|
|
<code data-shortcode="[swi_foot_match_venue match_id="12345"]">[swi_foot_match_venue match_id="12345"]</code>
|
|
<code data-shortcode="[swi_foot_match_score match_id="12345" separator=":"]">[swi_foot_match_score match_id="12345" separator=":"]</code>
|
|
<code data-shortcode="[swi_foot_match_status match_id="12345"]">[swi_foot_match_status match_id="12345"]</code>
|
|
<code data-shortcode="[swi_foot_match_league match_id="12345"]">[swi_foot_match_league match_id="12345"]</code>
|
|
<code data-shortcode="[swi_foot_match_round match_id="12345"]">[swi_foot_match_round match_id="12345"]</code>
|
|
</div>
|
|
|
|
<div class="shortcode-group">
|
|
<strong><?php _e('Parameters:', 'swi_foot_matchdata'); ?></strong>
|
|
<ul>
|
|
<li><code>match_id</code> - Specific match ID</li>
|
|
<li><code>team_id</code> - Team ID (for next match)</li>
|
|
<li><code>show_next</code> - Show next match (true/false)</li>
|
|
<li><code>format</code> - Date/time format</li>
|
|
<li><code>separator</code> - Score separator</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<p><em><?php _e('Click any shortcode above to copy it to clipboard', 'swi_foot_matchdata'); ?></em></p>
|
|
</div>
|
|
<script>
|
|
jQuery(document).ready(function($) {
|
|
$('.swi-foot-shortcodes-help code[data-shortcode]').css('cursor', 'pointer').on('click', function() {
|
|
var shortcode = $(this).data('shortcode');
|
|
if (navigator.clipboard) {
|
|
navigator.clipboard.writeText(shortcode).then(function() {
|
|
alert('<?php _e('Shortcode copied to clipboard!', 'swi_foot_matchdata'); ?>');
|
|
});
|
|
} else {
|
|
// Use native clipboard API
|
|
var textArea = document.createElement('textarea');
|
|
textArea.value = shortcode;
|
|
document.body.appendChild(textArea);
|
|
textArea.select();
|
|
document.execCommand('copy');
|
|
document.body.removeChild(textArea);
|
|
alert('<?php _e('Shortcode copied to clipboard!', 'swi_foot_matchdata'); ?>');
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
public function options_page()
|
|
{
|
|
?>
|
|
<div class="wrap">
|
|
<h1><?php _e('Swiss Football Matchdata Settings', 'swi_foot_matchdata'); ?></h1>
|
|
|
|
<form action="options.php" method="post">
|
|
<?php
|
|
settings_fields('swi_foot_settings');
|
|
do_settings_sections('swi_foot_settings');
|
|
submit_button();
|
|
?>
|
|
</form>
|
|
|
|
<div class="swi-foot-admin-section">
|
|
<h2><?php _e('Connection Test', 'swi_foot_matchdata'); ?></h2>
|
|
<p>
|
|
<button type="button" id="test-connection" class="button">
|
|
<?php _e('Test API Connection', 'swi_foot_matchdata'); ?>
|
|
</button>
|
|
<span id="connection-status"></span>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="swi-foot-admin-section">
|
|
<h2><?php _e('Team Management', 'swi_foot_matchdata'); ?></h2>
|
|
<p>
|
|
<button type="button" id="refresh-teams" class="button">
|
|
<?php _e('Refresh Teams List', 'swi_foot_matchdata'); ?>
|
|
</button>
|
|
<span id="refresh-status"></span>
|
|
</p>
|
|
|
|
<div id="teams-list">
|
|
<?php $this->display_teams(); ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="swi-foot-admin-section">
|
|
<h2><?php _e('Cache Management', 'swi_foot_matchdata'); ?></h2>
|
|
<p>
|
|
<button type="button" id="clear-cache" class="button">
|
|
<?php _e('Clear Match Data Cache', 'swi_foot_matchdata'); ?>
|
|
</button>
|
|
<span id="cache-status"></span>
|
|
</p>
|
|
<?php $this->display_cache_info(); ?>
|
|
</div>
|
|
|
|
<div class="swi-foot-admin-section">
|
|
<h2><?php _e('Finished Matches Data', 'swi_foot_matchdata'); ?></h2>
|
|
<?php $this->display_finished_matches(); ?>
|
|
</div>
|
|
|
|
<div class="swi-foot-admin-section">
|
|
<h2><?php _e('Quick Shortcode Reference', 'swi_foot_matchdata'); ?></h2>
|
|
<div class="shortcode-quick-ref">
|
|
<div class="shortcode-examples">
|
|
<h4><?php _e('Common Examples:', 'swi_foot_matchdata'); ?></h4>
|
|
<p><strong><?php _e('Display full match info:', 'swi_foot_matchdata'); ?></strong><br>
|
|
<code>[swi_foot_match match_id="12345"]</code>
|
|
</p>
|
|
|
|
<p><strong><?php _e('Show next match for a team:', 'swi_foot_matchdata'); ?></strong><br>
|
|
<code>[swi_foot_match team_id="67" show_next="true"]</code>
|
|
</p>
|
|
|
|
<p><strong><?php _e('Individual elements in text:', 'swi_foot_matchdata'); ?></strong><br>
|
|
<?php _e('The match between', 'swi_foot_matchdata'); ?> <code>[swi_foot_match_home_team match_id="12345"]</code> <?php _e('and', 'swi_foot_matchdata'); ?> <code>[swi_foot_match_away_team match_id="12345"]</code> <?php _e('is on', 'swi_foot_matchdata'); ?> <code>[swi_foot_match_date match_id="12345"]</code></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
private function display_teams()
|
|
{
|
|
$api = new Swi_Foot_API();
|
|
$teams = $api->get_teams();
|
|
|
|
if (is_wp_error($teams)) {
|
|
echo '<p class="notice notice-error">' .
|
|
sprintf(__('Error loading teams: %s', 'swi_foot_matchdata'), $teams->get_error_message()) .
|
|
'</p>';
|
|
return;
|
|
}
|
|
|
|
if (empty($teams)) {
|
|
echo '<p class="notice notice-warning">' .
|
|
__('No teams found. Please check your API configuration.', 'swi_foot_matchdata') .
|
|
'</p>';
|
|
return;
|
|
}
|
|
|
|
echo '<h3>' . __('Available Teams:', 'swi_foot_matchdata') . '</h3>';
|
|
echo '<div class="swi-foot-teams-grid">';
|
|
foreach ($teams as $team) {
|
|
echo '<div class="team-card">';
|
|
echo '<strong>' . esc_html($team['teamName'] ?? 'Unknown Team') . '</strong><br>';
|
|
echo '<small>ID: ' . esc_html($team['teamId'] ?? 'N/A') . '</small><br>';
|
|
if (!empty($team['teamLeagueName'])) {
|
|
echo '<small>' . esc_html($team['teamLeagueName']) . '</small>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
private function display_cache_info()
|
|
{
|
|
$keys = get_transient('swi_foot_match_keys');
|
|
$cache_count = is_array($keys) ? count($keys) : 0;
|
|
$cache_duration = get_option('swi_foot_match_cache_duration', 30);
|
|
|
|
echo '<p>' . sprintf(__('Currently caching %d match records with %d second cache duration.', 'swi_foot_matchdata'), $cache_count, $cache_duration) . '</p>';
|
|
|
|
if ($cache_count > 0) {
|
|
$timestamps = array();
|
|
foreach ($keys as $k) {
|
|
$payload = get_transient('swi_foot_match_' . $k);
|
|
if (is_array($payload) && isset($payload['cached_at'])) {
|
|
$timestamps[] = (int) $payload['cached_at'];
|
|
}
|
|
}
|
|
|
|
if (!empty($timestamps)) {
|
|
$oldest_timestamp = min($timestamps);
|
|
$newest_timestamp = max($timestamps);
|
|
|
|
echo '<p><strong>' . __('Cache Range:', 'swi_foot_matchdata') . '</strong><br>';
|
|
echo __('Oldest:', 'swi_foot_matchdata') . ' ' . date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $oldest_timestamp) . '<br>';
|
|
echo __('Newest:', 'swi_foot_matchdata') . ' ' . date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $newest_timestamp) . '</p>';
|
|
}
|
|
}
|
|
}
|
|
|
|
private function display_finished_matches()
|
|
{
|
|
$finished = get_option('swi_foot_finished_matches', array());
|
|
if (empty($finished)) {
|
|
echo '<p>' . __('No finished match data stored.', 'swi_foot_matchdata') . '</p>';
|
|
return;
|
|
}
|
|
|
|
echo '<table class="widefat fixed striped">';
|
|
echo '<thead>
|
|
<tr>
|
|
<th>' . __('Match ID', 'swi_foot_matchdata') . '</th>
|
|
<th>' . __('Saved At', 'swi_foot_matchdata') . '</th>
|
|
<th>' . __('Players', 'swi_foot_matchdata') . '</th>
|
|
<th>' . __('Bench', 'swi_foot_matchdata') . '</th>
|
|
<th>' . __('Events', 'swi_foot_matchdata') . '</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead><tbody>';
|
|
|
|
foreach ($finished as $mid => $item) {
|
|
$players = count($item['roster']['players'] ?? array());
|
|
$bench = count($item['roster']['bench'] ?? array());
|
|
$events = count($item['events'] ?? array());
|
|
$saved = !empty($item['saved_at']) ? date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $item['saved_at']) : '-';
|
|
|
|
echo '<tr>
|
|
<td>' . esc_html($mid) . '</td>
|
|
<td>' . esc_html($saved) . '</td>
|
|
<td>' . esc_html($players) . '</td>
|
|
<td>' . esc_html($bench) . '</td>
|
|
<td>' . esc_html($events) . '</td>
|
|
<td>
|
|
<button class="button swi-foot-clear-finished" data-id="' . esc_attr($mid) . '">' . __('Delete', 'swi_foot_matchdata') . '</button>
|
|
</td>
|
|
</tr>';
|
|
}
|
|
|
|
echo '</tbody></table>';
|
|
echo '<p><button id="swi-foot-clear-all-finished" class="button button-secondary">' . __('Clear All Finished Matches', 'swi_foot_matchdata') . '</button></p>';
|
|
|
|
// Include inline JS for actions
|
|
?>
|
|
<script>
|
|
jQuery(function($) {
|
|
$('.swi-foot-clear-finished').on('click', function() {
|
|
if (!confirm('<?php _e('Delete this finished match data?', 'swi_foot_matchdata'); ?>')) return;
|
|
var btn = $(this);
|
|
var matchId = btn.data('id');
|
|
fetch(swi_foot_ajax.rest_url.replace(/\/$/, '') + '/admin/finished/' + encodeURIComponent(matchId), {
|
|
method: 'DELETE',
|
|
credentials: 'same-origin',
|
|
headers: { 'X-WP-Nonce': swi_foot_ajax.rest_nonce }
|
|
}).then(function(resp) { return resp.json(); }).then(function(resp) {
|
|
if (resp && resp.success) {
|
|
btn.closest('tr').fadeOut();
|
|
} else {
|
|
alert(resp.error || 'Error');
|
|
}
|
|
}).catch(function() { alert('Network error'); });
|
|
});
|
|
|
|
$('#swi-foot-clear-all-finished').on('click', function() {
|
|
if (!confirm('<?php _e('Clear all finished match data?', 'swi_foot_matchdata'); ?>')) return;
|
|
fetch(swi_foot_ajax.rest_url.replace(/\/$/, '') + '/admin/finished', {
|
|
method: 'DELETE',
|
|
credentials: 'same-origin',
|
|
headers: { 'X-WP-Nonce': swi_foot_ajax.rest_nonce }
|
|
}).then(function(resp) { return resp.json(); }).then(function(resp) {
|
|
if (resp && resp.success) {
|
|
location.reload();
|
|
} else {
|
|
alert(resp.error || 'Error');
|
|
}
|
|
}).catch(function() { alert('Network error'); });
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
|
|
|
|
}
|
|
?>
|