1272 lines
53 KiB
PHP
1272 lines
53 KiB
PHP
<?php
|
||
|
||
class Swi_Foot_Shortcodes
|
||
{
|
||
|
||
private $api;
|
||
|
||
public function __construct()
|
||
{
|
||
$this->api = new Swi_Foot_API();
|
||
|
||
// Register shortcodes
|
||
add_shortcode('swi_foot_match', array($this, 'match_shortcode'));
|
||
add_shortcode('swi_foot_match_home_team', array($this, 'match_home_team_shortcode'));
|
||
add_shortcode('swi_foot_match_away_team', array($this, 'match_away_team_shortcode'));
|
||
add_shortcode('swi_foot_match_date', array($this, 'match_date_shortcode'));
|
||
add_shortcode('swi_foot_match_time', array($this, 'match_time_shortcode'));
|
||
add_shortcode('swi_foot_match_venue', array($this, 'match_venue_shortcode'));
|
||
add_shortcode('swi_foot_match_score', array($this, 'match_score_shortcode'));
|
||
add_shortcode('swi_foot_match_status', array($this, 'match_status_shortcode'));
|
||
add_shortcode('swi_foot_match_league', array($this, 'match_league_shortcode'));
|
||
add_shortcode('swi_foot_match_round', array($this, 'match_round_shortcode'));
|
||
add_shortcode('swi_foot_standings', array($this, 'standings_shortcode'));
|
||
add_shortcode('swi_foot_roster', array($this, 'roster_shortcode'));
|
||
add_shortcode('swi_foot_bench', array($this, 'bench_shortcode'));
|
||
add_shortcode('swi_foot_referees', array($this, 'referees_shortcode'));
|
||
add_shortcode('swi_foot_events', array($this, 'events_shortcode'));
|
||
add_shortcode('swi_foot_match_data', array($this, 'match_data_shortcode'));
|
||
add_shortcode('swi_foot_match_home_team_logo', array($this, 'match_home_team_logo_shortcode'));
|
||
add_shortcode('swi_foot_match_away_team_logo', array($this, 'match_away_team_logo_shortcode'));
|
||
add_shortcode('swi_foot_match_home_team_logo_url', array($this, 'match_home_team_logo_url_shortcode'));
|
||
add_shortcode('swi_foot_match_away_team_logo_url', array($this, 'match_away_team_logo_url_shortcode'));
|
||
|
||
// Register query variable for team logo requests and handle image serving
|
||
add_filter('query_vars', array($this, 'register_query_vars'));
|
||
add_action('template_redirect', array($this, 'handle_team_logo_request'));
|
||
}
|
||
|
||
/**
|
||
* Register custom query variables
|
||
*/
|
||
public function register_query_vars($vars)
|
||
{
|
||
$vars[] = 'swi_foot_team_logo';
|
||
$vars[] = 'position';
|
||
return $vars;
|
||
}
|
||
|
||
/**
|
||
* Render error message, distinguishing between "data not available" (406) and other errors
|
||
* @param WP_Error $error The error object
|
||
* @return string HTML-formatted error message
|
||
*/
|
||
private function render_error_message($error)
|
||
{
|
||
if (!is_wp_error($error)) {
|
||
return '';
|
||
}
|
||
|
||
// Check if this is a "data not yet available" error (HTTP 406)
|
||
if ($error->get_error_code() === 'data_not_available') {
|
||
return '<div class="swi-foot-data-warning">⏳ ' . __('Data not yet available', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
// For other errors, show grey "no data available" message
|
||
return '<div class="swi-foot-data-unavailable">ℹ️ ' . __('No data available', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
/**
|
||
* Handle internal requests for team logo images
|
||
* URL format: /?swi_foot_team_logo=team_id&position=home|away|event
|
||
* Uses template_redirect hook which fires after WordPress determines the query
|
||
* but before loading the template/theme
|
||
*/
|
||
public function handle_team_logo_request()
|
||
{
|
||
$team_logo_id = get_query_var('swi_foot_team_logo');
|
||
|
||
error_log('Swiss Football: handle_team_logo_request() called, team_logo_id from get_query_var: ' . var_export($team_logo_id, true));
|
||
|
||
if (empty($team_logo_id)) {
|
||
error_log('Swiss Football: team_logo_id is empty, skipping image serving');
|
||
return; // Not a team logo request, continue normal WordPress flow
|
||
}
|
||
|
||
error_log('Swiss Football: Processing team logo request for team_id: ' . $team_logo_id);
|
||
|
||
// This is a team logo request, serve the image and exit
|
||
$this->serve_team_logo_image($team_logo_id);
|
||
exit; // Never reached, but for clarity
|
||
}
|
||
|
||
/**
|
||
* Serve team logo image from API base64 data
|
||
*/
|
||
private function serve_team_logo_image($team_id)
|
||
{
|
||
error_log('Swiss Football: serve_team_logo_image() called with team_id: ' . $team_id . ', type: ' . gettype($team_id));
|
||
|
||
// Validate team_id is numeric
|
||
if (!ctype_digit((string)$team_id) || empty($team_id)) {
|
||
error_log('Swiss Football: Invalid team ID provided: ' . var_export($team_id, true));
|
||
wp_die('Invalid team ID', 'Invalid Request', array('response' => 400));
|
||
}
|
||
|
||
error_log('Swiss Football: team_id validation passed, team_id: ' . $team_id);
|
||
error_log('Swiss Football: Attempting to fetch team picture for team_id: ' . $team_id);
|
||
|
||
// Fetch image from API
|
||
$image_data = $this->api->get_team_picture($team_id);
|
||
|
||
error_log('Swiss Football: API response type: ' . gettype($image_data));
|
||
if (is_wp_error($image_data)) {
|
||
error_log('Swiss Football: API returned WP_Error: ' . $image_data->get_error_message());
|
||
} else {
|
||
error_log('Swiss Football: API response length: ' . strlen(var_export($image_data, true)) . ', is_array: ' . (is_array($image_data) ? 'yes' : 'no') . ', is_string: ' . (is_string($image_data) ? 'yes' : 'no'));
|
||
if (is_string($image_data)) {
|
||
error_log('Swiss Football: String response first 200 chars: ' . substr($image_data, 0, 200));
|
||
}
|
||
}
|
||
|
||
if (is_wp_error($image_data)) {
|
||
error_log('Swiss Football: API error fetching team picture: ' . $image_data->get_error_message());
|
||
wp_die('Image not found', 'Not Found', array('response' => 404));
|
||
}
|
||
|
||
if (empty($image_data)) {
|
||
error_log('Swiss Football: Team picture returned empty for team_id: ' . $team_id);
|
||
wp_die('Image not found', 'Not Found', array('response' => 404));
|
||
}
|
||
|
||
error_log('Swiss Football: Successfully fetched image data for team_id: ' . $team_id . ', length: ' . strlen($image_data));
|
||
|
||
// Handle API response that may be an array (if JSON returned a structure)
|
||
// or a string (if JSON returned a plain string)
|
||
if (is_array($image_data)) {
|
||
error_log('Swiss Football: Image data is array, attempting to extract base64 from common fields');
|
||
// Try to find the base64 data in common field names
|
||
$potential_fields = array('picture', 'logo', 'image', 'data', 'url', 'href');
|
||
$found_data = null;
|
||
foreach ($potential_fields as $field) {
|
||
if (isset($image_data[$field]) && !empty($image_data[$field])) {
|
||
$found_data = $image_data[$field];
|
||
error_log('Swiss Football: Found image data in array field: ' . $field);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!$found_data) {
|
||
error_log('Swiss Football: Could not find image data in array, array keys: ' . implode(', ', array_keys($image_data)));
|
||
wp_die('Image not found', 'Not Found', array('response' => 404));
|
||
}
|
||
|
||
$image_data = $found_data;
|
||
error_log('Swiss Football: Extracted base64 from array, length: ' . strlen($image_data));
|
||
}
|
||
|
||
// At this point, $image_data should be a string (base64 encoded)
|
||
|
||
// The API returns base64 encoded image data
|
||
// Detect image format from the data or default to PNG
|
||
$mime_type = 'image/png';
|
||
if (strpos($image_data, 'data:image/') === 0) {
|
||
// Already has data URI format, extract mime type
|
||
preg_match('/data:([^;]+)/', $image_data, $matches);
|
||
if (isset($matches[1])) {
|
||
$mime_type = $matches[1];
|
||
// Remove data URI prefix to get just base64
|
||
$image_data = preg_replace('/^data:[^;]+;base64,/', '', $image_data);
|
||
}
|
||
} elseif (strpos($image_data, '/') === false && strlen($image_data) > 100) {
|
||
// Looks like raw base64, assume PNG
|
||
$mime_type = 'image/png';
|
||
}
|
||
|
||
// Decode base64
|
||
$decoded = base64_decode(trim($image_data), true);
|
||
if ($decoded === false) {
|
||
error_log('Swiss Football: Failed to decode base64 image data for team_id: ' . $team_id);
|
||
wp_die('Invalid image data', 'Bad Request', array('response' => 400));
|
||
}
|
||
|
||
error_log('Swiss Football: Successfully decoded image, size: ' . strlen($decoded) . ' bytes, mime: ' . $mime_type);
|
||
|
||
// Set headers for image serving
|
||
header('Content-Type: ' . $mime_type);
|
||
header('Content-Length: ' . strlen($decoded));
|
||
header('Cache-Control: public, max-age=2592000'); // 30 days
|
||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 2592000) . ' GMT');
|
||
header('Access-Control-Allow-Origin: *');
|
||
|
||
// Output image and exit
|
||
echo $decoded;
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Generate internal URL for serving team logo image
|
||
*
|
||
* @param string $team_id The team ID
|
||
* @param string $position 'home' or 'away'
|
||
* @return string URL to internal team logo endpoint
|
||
*/
|
||
private function get_team_logo_url($team_id, $position = 'home')
|
||
{
|
||
return add_query_arg(array(
|
||
'swi_foot_team_logo' => $team_id,
|
||
'position' => $position
|
||
), home_url('/'));
|
||
}
|
||
|
||
public function match_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_next' => 'false'
|
||
), $atts);
|
||
|
||
$match_data = $this->get_match_data($atts);
|
||
|
||
if (!$match_data) {
|
||
return '<div class="swi-foot-error">' . __('Match data not available', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
ob_start();
|
||
?>
|
||
<div class="swi-foot-match-container" data-match-id="<?php echo esc_attr($match_data['matchId']); ?>">
|
||
<div class="match-teams">
|
||
<?php if (!empty($match_data['teams'])): ?>
|
||
<?php
|
||
$home_team = '';
|
||
$away_team = '';
|
||
foreach ($match_data['teams'] as $team) {
|
||
if ($team['isHomeTeam']) {
|
||
$home_team = $team['teamName'];
|
||
} else {
|
||
$away_team = $team['teamName'];
|
||
}
|
||
}
|
||
?>
|
||
<span class="home-team"><?php echo esc_html($home_team); ?></span>
|
||
<span class="vs"> vs </span>
|
||
<span class="away-team"><?php echo esc_html($away_team); ?></span>
|
||
<?php endif; ?>
|
||
</div>
|
||
<div class="match-details">
|
||
<div class="match-date">
|
||
<?php echo date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($match_data['matchDate'])); ?>
|
||
</div>
|
||
<?php if (!empty($match_data['stadiumFieldName'])): ?>
|
||
<div class="match-venue"><?php echo esc_html($match_data['stadiumFieldName']); ?></div>
|
||
<?php endif; ?>
|
||
<?php if ($match_data['hasMatchStarted'] || $match_data['hasMatchEnded']): ?>
|
||
<div class="match-score">
|
||
<?php echo esc_html($match_data['scoreTeamA']); ?> : <?php echo esc_html($match_data['scoreTeamB']); ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if (!empty($match_data['matchStateName'])): ?>
|
||
<div class="match-status"><?php echo esc_html($match_data['matchStateName']); ?></div>
|
||
<?php endif; ?>
|
||
<?php if (!empty($match_data['leagueName'])): ?>
|
||
<div class="match-league"><?php echo esc_html($match_data['leagueName']); ?></div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
public function match_home_team_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data || empty($match_data['teams'])) {
|
||
return '';
|
||
}
|
||
|
||
foreach ($match_data['teams'] as $team) {
|
||
if ($team['isHomeTeam']) {
|
||
return '<span class="swi-foot-inline home-team">' . esc_html($team['teamName']) . '</span>';
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public function match_away_team_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data || empty($match_data['teams'])) {
|
||
return '';
|
||
}
|
||
|
||
foreach ($match_data['teams'] as $team) {
|
||
if (!$team['isHomeTeam']) {
|
||
return '<span class="swi-foot-inline away-team">' . esc_html($team['teamName']) . '</span>';
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public function match_date_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_next' => 'false',
|
||
'format' => get_option('date_format', 'd.m.Y')
|
||
), $atts);
|
||
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data || empty($match_data['matchDate'])) {
|
||
return '';
|
||
}
|
||
|
||
return '<span class="swi-foot-inline date">' . date_i18n($atts['format'], strtotime($match_data['matchDate'])) . '</span>';
|
||
}
|
||
|
||
public function match_time_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_next' => 'false',
|
||
'format' => get_option('time_format', 'H:i')
|
||
), $atts);
|
||
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data || empty($match_data['matchDate'])) {
|
||
return '';
|
||
}
|
||
|
||
return '<span class="swi-foot-inline time">' . date_i18n($atts['format'], strtotime($match_data['matchDate'])) . '</span>';
|
||
}
|
||
|
||
public function match_venue_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data) {
|
||
return '';
|
||
}
|
||
|
||
$venue = $match_data['stadiumFieldName'] ?? '';
|
||
if ($venue) {
|
||
return '<span class="swi-foot-inline venue">' . esc_html($venue) . '</span>';
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public function match_score_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_next' => 'false',
|
||
'separator' => ':'
|
||
), $atts);
|
||
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data) {
|
||
return '';
|
||
}
|
||
|
||
if ($match_data['hasMatchStarted'] || $match_data['hasMatchEnded']) {
|
||
$score = esc_html($match_data['scoreTeamA']) . ' ' . $atts['separator'] . ' ' . esc_html($match_data['scoreTeamB']);
|
||
return '<span class="swi-foot-inline score">' . $score . '</span>';
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
public function match_status_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data) {
|
||
return '';
|
||
}
|
||
|
||
$status = $match_data['matchStateName'] ?? '';
|
||
if ($status) {
|
||
return '<span class="swi-foot-inline status">' . esc_html($status) . '</span>';
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public function match_league_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data) {
|
||
return '';
|
||
}
|
||
|
||
$league = $match_data['leagueName'] ?? '';
|
||
if ($league) {
|
||
return '<span class="swi-foot-inline league">' . esc_html($league) . '</span>';
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public function match_round_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data) {
|
||
return '';
|
||
}
|
||
|
||
$round = $match_data['roundNbr'] ?? '';
|
||
if ($round) {
|
||
return '<span class="swi-foot-inline round">' . esc_html($round) . '</span>';
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* Render match bench (team staff) list
|
||
* Usage: [swi_foot_bench match_id="12345"]
|
||
* Lists staff members (name and role) for both home and away teams
|
||
*/
|
||
public function bench_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'side' => '' // 'home' or 'away', shows both if not specified
|
||
), $atts);
|
||
|
||
$match_id = $atts['match_id'];
|
||
if (empty($match_id)) {
|
||
return '<div class="swi-foot-error">' . __('Match ID required', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
$bench = $this->api->get_match_bench($match_id);
|
||
|
||
if (is_wp_error($bench)) {
|
||
return $this->render_error_message($bench);
|
||
}
|
||
|
||
if (empty($bench)) {
|
||
return '<div class="swi-foot-notice">' . __('No bench data available', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
// Normalize side parameter
|
||
$side = strtolower(trim($atts['side']));
|
||
$show_side_filter = !empty($side) && in_array($side, array('home', 'away'), true);
|
||
|
||
ob_start();
|
||
?>
|
||
<div class="swi-foot-bench-container" data-match-id="<?php echo esc_attr($match_id); ?>">
|
||
<?php
|
||
// Group bench players by team
|
||
$home_staff = array_filter($bench, function($person) {
|
||
return isset($person['isHomeTeam']) && $person['isHomeTeam'] === true;
|
||
});
|
||
$away_staff = array_filter($bench, function($person) {
|
||
return isset($person['isHomeTeam']) && $person['isHomeTeam'] === false;
|
||
});
|
||
|
||
// If side is specified, filter to only that side
|
||
if ($show_side_filter) {
|
||
if ($side === 'home') {
|
||
$away_staff = array();
|
||
} else {
|
||
$home_staff = array();
|
||
}
|
||
}
|
||
?>
|
||
<?php if (!empty($home_staff)): ?>
|
||
<div class="bench-team bench-home">
|
||
<?php if (!$show_side_filter): ?>
|
||
<h3><?php echo esc_html($home_staff[array_key_first($home_staff)]['teamName'] ?? __('Home Team', 'swi_foot_matchdata')); ?></h3>
|
||
<?php endif; ?>
|
||
<ul class="bench-list">
|
||
<?php foreach ($home_staff as $person): ?>
|
||
<li class="bench-person">
|
||
<?php echo esc_html($person['personName'] ?? ''); ?>
|
||
<?php if (!empty($person['roleCategoryName'])): ?>
|
||
<span class="swi-foot-role">(<?php echo esc_html($person['roleCategoryName']); ?>)</span>
|
||
<?php endif; ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if (!empty($away_staff)): ?>
|
||
<div class="bench-team bench-away">
|
||
<?php if (!$show_side_filter): ?>
|
||
<h3><?php echo esc_html($away_staff[array_key_first($away_staff)]['teamName'] ?? __('Away Team', 'swi_foot_matchdata')); ?></h3>
|
||
<?php endif; ?>
|
||
<ul class="bench-list">
|
||
<?php foreach ($away_staff as $person): ?>
|
||
<li class="bench-person">
|
||
<?php echo esc_html($person['personName'] ?? ''); ?>
|
||
<?php if (!empty($person['roleCategoryName'])): ?>
|
||
<span class="swi-foot-role">(<?php echo esc_html($person['roleCategoryName']); ?>)</span>
|
||
<?php endif; ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
/**
|
||
* Render referees list for a match
|
||
* Usage: [swi_foot_referees match_id="12345"]
|
||
* Lists referees with their role and name formatted as: "Role: Firstname Name" (name in bold)
|
||
*/
|
||
public function referees_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => ''
|
||
), $atts);
|
||
|
||
$match_id = $atts['match_id'];
|
||
if (empty($match_id)) {
|
||
return '<div class="swi-foot-error">✗ ' . __('Match ID required', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
$referees = $this->api->get_match_referees($match_id);
|
||
|
||
if (is_wp_error($referees)) {
|
||
return $this->render_error_message($referees);
|
||
}
|
||
|
||
if (empty($referees)) {
|
||
return '<div class="swi-foot-data-unavailable">ℹ️ ' . __('No data available', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
ob_start();
|
||
?>
|
||
<div class="swi-foot-referees-container" data-match-id="<?php echo esc_attr($match_id); ?>">
|
||
<ul class="referees-list">
|
||
<?php foreach ($referees as $referee): ?>
|
||
<li class="referee-item">
|
||
<span class="referee-role"><?php echo esc_html($referee['refereeRoleName'] ?? ''); ?>:</span>
|
||
<strong><?php echo esc_html(($referee['firstname'] ?? '') . ' ' . ($referee['name'] ?? '')); ?></strong>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
/**
|
||
* Generic inline data point shortcode
|
||
* Extracts a specific field from match data and displays it inline
|
||
* Usage: [swi_foot_match_data data_point="teamNameA"]
|
||
* Match ID is automatically picked up from container context if not specified
|
||
* Special data points: matchDate_date and matchDate_time (formatted per WordPress locale)
|
||
*/
|
||
public function match_data_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'data_point' => '',
|
||
), $atts);
|
||
|
||
// If match_id not provided, get it from post context
|
||
if (empty($atts['match_id'])) {
|
||
$context = function_exists('swi_foot_resolve_context') ? swi_foot_resolve_context(get_the_ID()) : array();
|
||
$atts['match_id'] = $context['match_id'] ?? '';
|
||
}
|
||
|
||
if (empty($atts['match_id']) || empty($atts['data_point'])) {
|
||
return '';
|
||
}
|
||
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data) {
|
||
return '';
|
||
}
|
||
|
||
// Normalize match data to ensure consistent field names
|
||
$match_data = $this->normalize_shortcode_match_data($match_data);
|
||
|
||
// Handle special date/time formatting
|
||
if ($atts['data_point'] === 'matchDate_date') {
|
||
$value = $this->format_match_date($match_data);
|
||
} elseif ($atts['data_point'] === 'matchDate_time') {
|
||
$value = $this->format_match_time($match_data);
|
||
} else {
|
||
// Support nested data points like "intermediateResults/scoreTeamA"
|
||
$value = $this->get_nested_value($match_data, $atts['data_point']);
|
||
}
|
||
|
||
if ($value === null || $value === '') {
|
||
return '';
|
||
}
|
||
|
||
// Convert boolean values to readable text
|
||
if (is_bool($value)) {
|
||
$value = $value ? __('Ja', 'swi_foot_matchdata') : __('Nein', 'swi_foot_matchdata');
|
||
}
|
||
|
||
return '<span class="swi-foot-inline swi-foot-data-point" data-field="' . esc_attr($atts['data_point']) . '">' . esc_html($value) . '</span>';
|
||
}
|
||
|
||
/**
|
||
* Normalize match data to ensure consistent field names
|
||
* Extracts team names from teams array if not present as direct fields
|
||
* @param array $match Raw match data
|
||
* @return array Normalized match data
|
||
*/
|
||
private function normalize_shortcode_match_data($match)
|
||
{
|
||
// If already has teamNameA/teamNameB as direct fields, return as-is
|
||
if (!empty($match['teamNameA']) || !empty($match['teamNameB'])) {
|
||
return $match;
|
||
}
|
||
|
||
// Extract team names from teams array if not present as direct fields
|
||
if (!empty($match['teams']) && is_array($match['teams'])) {
|
||
foreach ($match['teams'] as $team) {
|
||
if (!empty($team['isHomeTeam']) && !empty($team['teamName'])) {
|
||
$match['teamNameA'] = $team['teamName'];
|
||
} elseif (empty($team['isHomeTeam']) && !empty($team['teamName'])) {
|
||
$match['teamNameB'] = $team['teamName'];
|
||
}
|
||
}
|
||
}
|
||
|
||
// Normalize stadium field name
|
||
if (empty($match['stadiumFieldName']) && !empty($match['stadiumPlaygroundName'])) {
|
||
$match['stadiumFieldName'] = $match['stadiumPlaygroundName'];
|
||
}
|
||
|
||
return $match;
|
||
}
|
||
|
||
/**
|
||
* Helper to get nested array values using dot/slash notation
|
||
* @param array $array
|
||
* @param string $path e.g. "intermediateResults/scoreTeamA"
|
||
* @return mixed
|
||
*/
|
||
private function get_nested_value($array, $path)
|
||
{
|
||
if (!is_array($array) || empty($path)) {
|
||
return null;
|
||
}
|
||
|
||
$keys = explode('/', $path);
|
||
$current = $array;
|
||
|
||
foreach ($keys as $key) {
|
||
if (!is_array($current) || !isset($current[$key])) {
|
||
return null;
|
||
}
|
||
$current = $current[$key];
|
||
}
|
||
|
||
return $current;
|
||
}
|
||
|
||
/**
|
||
* Format match date according to WordPress locale settings
|
||
* Extracts date part from matchDate and formats using WordPress date format
|
||
* @param array $match Match data array
|
||
* @return string|null Formatted date or null if matchDate not available
|
||
*/
|
||
private function format_match_date($match)
|
||
{
|
||
if (empty($match['matchDate'])) {
|
||
return null;
|
||
}
|
||
|
||
// Extract date part from ISO datetime string (e.g., "2026-03-27T19:30:00" -> "2026-03-27")
|
||
// API provides date in Swiss time, use as-is without any timezone conversion
|
||
$date_part = substr($match['matchDate'], 0, 10);
|
||
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_part)) {
|
||
return null;
|
||
}
|
||
|
||
// Convert date string to WordPress format
|
||
$date_format = get_option('date_format');
|
||
return date_i18n($date_format, strtotime($date_part));
|
||
}
|
||
|
||
/**
|
||
* Format match time according to WordPress locale settings
|
||
* Extracts time part from matchDate and formats using WordPress time format
|
||
* @param array $match Match data array
|
||
* @return string|null Formatted time or null if matchDate not available
|
||
*/
|
||
private function format_match_time($match)
|
||
{
|
||
if (empty($match['matchDate'])) {
|
||
return null;
|
||
}
|
||
|
||
// Extract time part from ISO datetime string (e.g., "2026-03-27T19:30:00" -> "19:30:00")
|
||
// API provides time in Swiss time, use as-is without any timezone conversion
|
||
if (strpos($match['matchDate'], 'T') === false) {
|
||
return null;
|
||
}
|
||
|
||
$time_part = substr($match['matchDate'], 11, 8);
|
||
if (!preg_match('/^\d{2}:\d{2}:\d{2}$/', $time_part)) {
|
||
return null;
|
||
}
|
||
|
||
// Format time string with WordPress time format setting
|
||
$time_format = get_option('time_format');
|
||
return date_i18n($time_format, strtotime('2000-01-01 ' . $time_part));
|
||
}
|
||
|
||
private function get_match_data($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_next' => 'false'
|
||
), $atts);
|
||
|
||
$match_id = $atts['match_id'];
|
||
|
||
// If no match_id provided explicitly, try to resolve it from the post/page context
|
||
if (empty($match_id)) {
|
||
if (function_exists('swi_foot_resolve_context')) {
|
||
$ctx = swi_foot_resolve_context();
|
||
if (!empty($ctx['match_id'])) {
|
||
$match_id = $ctx['match_id'];
|
||
} elseif (empty($match_id) && !empty($ctx['team_id']) && $atts['show_next'] === 'true') {
|
||
// Use schedule to find next match for the team when show_next requested
|
||
$schedule = $this->api->get_schedule($ctx['team_id']);
|
||
if (!is_wp_error($schedule) && !empty($schedule)) {
|
||
foreach ($schedule as $match) {
|
||
if (strtotime($match['matchDate']) >= time()) {
|
||
$match_id = $match['matchId'];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// If no match_id but show_next is true, try to find next match for team
|
||
if (empty($match_id) && $atts['show_next'] === 'true' && !empty($atts['team_id'])) {
|
||
$schedule = $this->api->get_schedule($atts['team_id']);
|
||
if (!is_wp_error($schedule) && !empty($schedule)) {
|
||
// Find next upcoming match
|
||
foreach ($schedule as $match) {
|
||
if (strtotime($match['matchDate']) >= time()) {
|
||
$match_id = $match['matchId'];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (empty($match_id)) {
|
||
return null;
|
||
}
|
||
|
||
// Try to get cached data first
|
||
$match_data = $this->api->get_cached_match_data($match_id);
|
||
|
||
// If no cached data, fetch from API
|
||
if (!$match_data) {
|
||
$match_data = $this->api->get_match_details($match_id);
|
||
if (is_wp_error($match_data)) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
return $match_data;
|
||
}
|
||
|
||
public function standings_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'team_id' => ''
|
||
), $atts);
|
||
|
||
if (empty($atts['team_id'])) {
|
||
return '<div class="swi-foot-error">' . __('Team ID required', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
$standings = $this->api->get_standings($atts['team_id']);
|
||
|
||
if (is_wp_error($standings) || empty($standings)) {
|
||
return '<div class="swi-foot-error">' . __('Standings data not available', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
ob_start();
|
||
?>
|
||
<div class="swi-foot-standings">
|
||
<h3><?php _e('Current Standings', 'swi_foot_matchdata'); ?></h3>
|
||
<table class="swi-foot-table">
|
||
<thead>
|
||
<tr>
|
||
<th><?php _e('Pos', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('Team', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('P', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('W', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('D', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('L', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('GF', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('GA', 'swi_foot_matchdata'); ?></th>
|
||
<th><?php _e('Pts', 'swi_foot_matchdata'); ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($standings as $team): ?>
|
||
<tr<?php echo ($team['teamId'] == $atts['team_id']) ? ' class="highlight"' : ''; ?>>
|
||
<td><?php echo esc_html($team['position']); ?></td>
|
||
<td><?php echo esc_html($team['teamName']); ?></td>
|
||
<td><?php echo esc_html($team['matches']); ?></td>
|
||
<td><?php echo esc_html($team['wins']); ?></td>
|
||
<td><?php echo esc_html($team['draws']); ?></td>
|
||
<td><?php echo esc_html($team['losses']); ?></td>
|
||
<td><?php echo esc_html($team['goalsFor']); ?></td>
|
||
<td><?php echo esc_html($team['goalsAgainst']); ?></td>
|
||
<td><strong><?php echo esc_html($team['points']); ?></strong></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
public function roster_shortcode($atts)
|
||
{
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_current' => 'false',
|
||
'side' => '',
|
||
'show_starting' => 'true',
|
||
'show_bench' => 'false',
|
||
'with_bench' => 'false' // Legacy support
|
||
), $atts);
|
||
|
||
$side = strtolower(trim($atts['side']));
|
||
if (!in_array($side, array('home', 'away'), true)) {
|
||
return '<div class="swi-foot-error">' . __('Parameter "side" must be "home" or "away"', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
$match_id = $atts['match_id'];
|
||
if ($atts['show_current'] === 'true' && !empty($atts['team_id'])) {
|
||
$current_match = $this->api->get_current_match($atts['team_id']);
|
||
if ($current_match) {
|
||
$match_id = $current_match['matchId'];
|
||
}
|
||
}
|
||
|
||
if (empty($match_id)) {
|
||
return '<div class="swi-foot-error">' . __('Match ID required', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
// Parse show_starting and show_bench attributes (handle legacy with_bench)
|
||
$show_starting = strtolower($atts['show_starting']) === 'true';
|
||
$show_bench = strtolower($atts['show_bench']) === 'true';
|
||
|
||
// Legacy support: if with_bench is true and show_starting is default, show both
|
||
if (strtolower($atts['with_bench']) === 'true' && !$show_bench) {
|
||
$show_bench = true;
|
||
}
|
||
|
||
// First check if we have saved final data
|
||
$saved = $this->api->get_finished_match_data($match_id);
|
||
if ($saved) {
|
||
$players = $saved['roster']['players'] ?? array();
|
||
} else {
|
||
// Live fetch
|
||
$players = $this->api->get_match_players($match_id);
|
||
if (is_wp_error($players)) {
|
||
return $this->render_error_message($players);
|
||
}
|
||
|
||
// Check match ended & possibly save events + roster together
|
||
$match_details = $this->api->get_match_details($match_id);
|
||
if (!is_wp_error($match_details) && !empty($match_details['hasMatchEnded'])) {
|
||
$events = $this->api->get_match_events($match_id);
|
||
if (is_wp_error($events)) {
|
||
$events = array();
|
||
}
|
||
// Only save if we have valid player data (not a WP_Error)
|
||
if (is_array($players)) {
|
||
$this->api->save_finished_match_data(
|
||
$match_id,
|
||
array('players' => $players),
|
||
$events
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Filter players by team side
|
||
$team_players = array_filter($players, function ($p) use ($side) {
|
||
return $side === 'home' ? !empty($p['isHomeTeam']) : empty($p['isHomeTeam']);
|
||
});
|
||
|
||
// Split players into starting (assignmentRoleId = 0 or 1 for captain) and bench (assignmentRoleId > 1)
|
||
$starting_players = array_filter($team_players, function ($p) {
|
||
return isset($p['assignmentRoleId']) && ((int)$p['assignmentRoleId'] === 0 || (int)$p['assignmentRoleId'] === 1);
|
||
});
|
||
$bench_players = array_filter($team_players, function ($p) {
|
||
return !isset($p['assignmentRoleId']) || ((int)$p['assignmentRoleId'] > 1);
|
||
});
|
||
|
||
// If neither option is checked, return empty div
|
||
if (!$show_starting && !$show_bench) {
|
||
return '<div class="swi-foot-error">' . __('No roster display options selected', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
ob_start();
|
||
?>
|
||
<div class="swi-foot-roster" data-match-id="<?php echo esc_attr($match_id); ?>">
|
||
<h3><?php echo esc_html(ucfirst($side) . ' ' . __('Team Roster', 'swi_foot_matchdata')); ?></h3>
|
||
|
||
<?php if ($show_starting && !empty($starting_players)): ?>
|
||
<div class="swi-foot-roster-starting">
|
||
<h4><?php _e('Starting Squad', 'swi_foot_matchdata'); ?></h4>
|
||
<ul class="roster-list">
|
||
<?php foreach ($starting_players as $pl): ?>
|
||
<li class="roster-player<?php echo isset($pl['assignmentRoleId']) && (int)$pl['assignmentRoleId'] === 1 ? ' roster-player-captain' : ''; ?>">
|
||
<?php
|
||
$jersey = $pl['jerseyNumber'] ?? '';
|
||
$firstname = $pl['firstname'] ?? '';
|
||
$name = $pl['name'] ?? '';
|
||
$secondName = $pl['secondName'] ?? '';
|
||
$positionName = $pl['positionName'] ?? $pl['position'] ?? '';
|
||
$isCaptain = isset($pl['assignmentRoleId']) && (int)$pl['assignmentRoleId'] === 1;
|
||
$displayName = trim($firstname . ' ' . $name . ' ' . $secondName);
|
||
|
||
// Captain badge
|
||
if ($isCaptain) {
|
||
echo '<span class="swi-foot-captain-badge" title="' . esc_attr(__('Captain', 'swi_foot_matchdata')) . '">C</span> ';
|
||
}
|
||
|
||
echo esc_html($jersey . ' – ' . $displayName);
|
||
|
||
if (!empty($positionName)) {
|
||
echo ' <span class="swi-foot-position">(' . esc_html($positionName) . ')</span>';
|
||
}
|
||
?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($show_starting && !empty($starting_players) && $show_bench && !empty($bench_players)): ?>
|
||
<hr class="swi-foot-roster-divider" />
|
||
<?php endif; ?>
|
||
|
||
<?php if ($show_bench && !empty($bench_players)): ?>
|
||
<div class="swi-foot-roster-bench">
|
||
<h4><?php _e('Bench', 'swi_foot_matchdata'); ?></h4>
|
||
<ul class="roster-bench-list">
|
||
<?php foreach ($bench_players as $pl): ?>
|
||
<li class="roster-player">
|
||
<?php
|
||
$jersey = $pl['jerseyNumber'] ?? '';
|
||
$firstname = $pl['firstname'] ?? '';
|
||
$name = $pl['name'] ?? '';
|
||
$secondName = $pl['secondName'] ?? '';
|
||
$positionName = $pl['positionName'] ?? $pl['position'] ?? '';
|
||
$displayName = trim($firstname . ' ' . $name . ' ' . $secondName);
|
||
echo esc_html($jersey . ' – ' . $displayName);
|
||
if (!empty($positionName)) {
|
||
echo ' <span class="swi-foot-position">(' . esc_html($positionName) . ')</span>';
|
||
}
|
||
?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!$show_starting && !empty($bench_players) && !$show_bench): ?>
|
||
<p><?php _e('No roster data to display.', 'swi_foot_matchdata'); ?></p>
|
||
<?php elseif ($show_starting && empty($starting_players) && empty($bench_players)): ?>
|
||
<p><?php _e('No roster data available.', 'swi_foot_matchdata'); ?></p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
public function events_shortcode($atts)
|
||
{
|
||
error_log('[SWI_FOOT_EVENTS_DEBUG] RAW SHORTCODE ATTRIBUTES: ' . json_encode($atts, JSON_UNESCAPED_SLASHES));
|
||
|
||
$atts = shortcode_atts(array(
|
||
'match_id' => '',
|
||
'team_id' => '',
|
||
'show_current' => 'false',
|
||
'refresh_interval' => '30',
|
||
'event_order' => 'dynamic'
|
||
), $atts);
|
||
|
||
error_log('[SWI_FOOT_EVENTS_DEBUG] PARSED ATTRIBUTES: ' . json_encode($atts, JSON_UNESCAPED_SLASHES));
|
||
error_log('[SWI_FOOT_EVENTS_DEBUG] EVENT_ORDER VALUE: ' . var_export($atts['event_order'], true));
|
||
|
||
$match_id = $atts['match_id'];
|
||
if ($atts['show_current'] === 'true' && !empty($atts['team_id'])) {
|
||
$current_match = $this->api->get_current_match($atts['team_id']);
|
||
if ($current_match) {
|
||
$match_id = $current_match['matchId'];
|
||
}
|
||
}
|
||
|
||
if (empty($match_id)) {
|
||
return '<div class="swi-foot-error">' . __('Match ID required', 'swi_foot_matchdata') . '</div>';
|
||
}
|
||
|
||
// Try saved first
|
||
$saved = $this->api->get_finished_match_data($match_id);
|
||
if ($saved) {
|
||
$events = $saved['events'] ?? array();
|
||
} else {
|
||
$events = $this->api->get_match_events($match_id);
|
||
if (is_wp_error($events)) {
|
||
return $this->render_error_message($events);
|
||
}
|
||
|
||
// Check if match ended and store both data sets
|
||
$match_details = $this->api->get_match_details($match_id);
|
||
if (!is_wp_error($match_details) && !empty($match_details['hasMatchEnded'])) {
|
||
$players = $this->api->get_match_players($match_id);
|
||
$bench = $this->api->get_match_bench($match_id);
|
||
if (is_wp_error($players)) $players = array();
|
||
if (is_wp_error($bench)) $bench = array();
|
||
|
||
$this->api->save_finished_match_data(
|
||
$match_id,
|
||
array('players' => $players, 'bench' => $bench),
|
||
$events
|
||
);
|
||
}
|
||
}
|
||
|
||
// Determine event sort order based on setting and match status
|
||
$event_order = $atts['event_order'] ?? 'dynamic';
|
||
|
||
// Convert exactEventTime to timestamps for sorting
|
||
if (!empty($events)) {
|
||
foreach ($events as &$event) {
|
||
// Convert ISO 8601 format (2026-03-14T17:03:50.437) to timestamp
|
||
$event['_timestamp'] = strtotime(substr($event['exactEventTime'], 0, 19));
|
||
}
|
||
unset($event);
|
||
|
||
// Sort by timestamp
|
||
if ($event_order === 'dynamic') {
|
||
// Dynamic: newest first while match is live, chronological after match ends
|
||
$match_details = $this->api->get_match_details($match_id);
|
||
$match_has_ended = !is_wp_error($match_details) && !empty($match_details['hasMatchEnded']);
|
||
|
||
usort($events, function ($a, $b) use ($match_has_ended) {
|
||
if ($match_has_ended) {
|
||
// Chronological (ascending): oldest first
|
||
return $a['_timestamp'] - $b['_timestamp'];
|
||
} else {
|
||
// Descending: newest first
|
||
return $b['_timestamp'] - $a['_timestamp'];
|
||
}
|
||
});
|
||
} elseif ($event_order === 'newest_first') {
|
||
// Always newest first (descending)
|
||
usort($events, function ($a, $b) {
|
||
return $b['_timestamp'] - $a['_timestamp'];
|
||
});
|
||
} elseif ($event_order === 'oldest_first') {
|
||
// Always oldest first (ascending)
|
||
usort($events, function ($a, $b) {
|
||
return $a['_timestamp'] - $b['_timestamp'];
|
||
});
|
||
}
|
||
}
|
||
|
||
ob_start();
|
||
?>
|
||
<div class="swi-foot-events" data-match-id="<?php echo esc_attr($match_id); ?>" data-refresh="<?php echo esc_attr($atts['refresh_interval']); ?>" data-event-order="<?php echo esc_attr($event_order); ?>" aria-live="polite" role="status" aria-label="<?php echo esc_attr(__('Live match events', 'swi_foot_matchdata')); ?>">
|
||
<h3><?php _e('Match Events', 'swi_foot_matchdata'); ?></h3>
|
||
<div class="events-timeline">
|
||
<?php if (!empty($events)): ?>
|
||
<?php foreach ($events as $event): ?>
|
||
<div class="event-item">
|
||
<div class="event-minute">
|
||
<span class="minute-time" title="<?php echo esc_attr(__('Match minute', 'swi_foot_matchdata')); ?>">
|
||
⏱ <?php
|
||
$minute = $event['minute'] ?? '';
|
||
$additionalMinute = $event['additionalMinute'] ?? 0;
|
||
if (!empty($minute)) {
|
||
echo esc_html($minute) . "'";
|
||
if ($additionalMinute > 0) {
|
||
echo '+' . esc_html($additionalMinute);
|
||
}
|
||
}
|
||
?>
|
||
</span>
|
||
</div>
|
||
<div class="event-main">
|
||
<div class="event-header">
|
||
<div class="event-type-info">
|
||
<strong class="event-type"><?php
|
||
$eventTypeName = $event['eventTypeName'] ?? '';
|
||
$eventSubTypeName = $event['eventSubTypeName'] ?? '';
|
||
if (!empty($eventTypeName)) {
|
||
echo esc_html($eventTypeName);
|
||
}
|
||
if (!empty($eventSubTypeName) && $eventSubTypeName !== '-') {
|
||
echo ' <span class="event-subtype">(' . esc_html($eventSubTypeName) . ')</span>';
|
||
}
|
||
?></strong>
|
||
</div>
|
||
<?php if (!empty($event['teamId'])): ?>
|
||
<div class="team-logo">
|
||
<?php
|
||
$team_id = $event['teamId'];
|
||
$logo_url = $this->get_team_logo_url($team_id, 'event');
|
||
echo '<img src="' . esc_url($logo_url) . '" alt="' . esc_attr($event['teamName'] ?? '') . '" title="' . esc_attr($event['teamName'] ?? '') . '" />';
|
||
?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<div class="event-details">
|
||
<?php
|
||
$jerseyNumber = $event['jerseyNumber'] ?? '';
|
||
$personName = $event['personName'] ?? $event['playerName'] ?? '';
|
||
$eventTypeId = $event['eventTypeId'] ?? 0;
|
||
|
||
if (!empty($jerseyNumber) || !empty($personName)) {
|
||
echo '<span class="player-info">👤 ' . esc_html($jerseyNumber . ' ' . $personName) . '</span>';
|
||
}
|
||
|
||
// If event type is exchange (2), show substitute player
|
||
if ($eventTypeId == 2) {
|
||
$subJersey = $event['substitutePlayerJerseyNumber'] ?? '';
|
||
$subName = $event['substitutePlayerName'] ?? '';
|
||
if (!empty($subJersey) || !empty($subName)) {
|
||
echo ' <span class="substitute-info">⇄ ' . esc_html($subJersey . ' ' . $subName) . '</span>';
|
||
}
|
||
}
|
||
?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<p><?php _e('No events recorded yet.', 'swi_foot_matchdata'); ?></p>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
public function match_home_team_logo_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data || empty($match_data['teams']) || empty($match_data['teams'][0])) {
|
||
return '';
|
||
}
|
||
|
||
$home_team_id = $match_data['teams'][0]['teamId'] ?? '';
|
||
if (empty($home_team_id)) {
|
||
return '';
|
||
}
|
||
|
||
$logo_url = $this->get_team_logo_url($home_team_id, 'home');
|
||
$team_name = esc_attr($match_data['teams'][0]['teamName'] ?? 'Home Team');
|
||
return '<img src="' . esc_url($logo_url) . '" alt="' . $team_name . '" class="swi-foot-team-logo home-team" />';
|
||
}
|
||
|
||
public function match_away_team_logo_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (!$match_data || empty($match_data['teams']) || empty($match_data['teams'][1])) {
|
||
return '';
|
||
}
|
||
|
||
$away_team_id = $match_data['teams'][1]['teamId'] ?? '';
|
||
if (empty($away_team_id)) {
|
||
return '';
|
||
}
|
||
|
||
$logo_url = $this->get_team_logo_url($away_team_id, 'away');
|
||
$team_name = esc_attr($match_data['teams'][1]['teamName'] ?? 'Away Team');
|
||
return '<img src="' . esc_url($logo_url) . '" alt="' . $team_name . '" class="swi-foot-team-logo away-team" />';
|
||
}
|
||
|
||
/**
|
||
* Shortcode: Display home team logo URL only (for use in image blocks)
|
||
* Usage: [swi_foot_match_home_team_logo_url]
|
||
* Returns: Internal URL that serves the team logo image
|
||
*/
|
||
public function match_home_team_logo_url_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (empty($match_data)) {
|
||
return '';
|
||
}
|
||
|
||
$home_team_id = $match_data['teams'][0]['teamId'] ?? '';
|
||
if (empty($home_team_id)) {
|
||
return '';
|
||
}
|
||
|
||
return $this->get_team_logo_url($home_team_id, 'home');
|
||
}
|
||
|
||
/**
|
||
* Shortcode: Display away team logo URL only (for use in image blocks)
|
||
* Usage: [swi_foot_match_away_team_logo_url]
|
||
* Returns: Internal URL that serves the team logo image
|
||
*/
|
||
public function match_away_team_logo_url_shortcode($atts)
|
||
{
|
||
$match_data = $this->get_match_data($atts);
|
||
if (empty($match_data)) {
|
||
return '';
|
||
}
|
||
|
||
$away_team_id = $match_data['teams'][1]['teamId'] ?? '';
|
||
if (empty($away_team_id)) {
|
||
return '';
|
||
}
|
||
|
||
return $this->get_team_logo_url($away_team_id, 'away');
|
||
}
|
||
|
||
|
||
|
||
public function enqueue_editor_assets()
|
||
{
|
||
wp_enqueue_script(
|
||
'swi-foot-editor-blocks',
|
||
SWI_FOOT_PLUGIN_URL . 'assets/editor-blocks.js',
|
||
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-data', 'jquery'),
|
||
SWI_FOOT_PLUGIN_VERSION,
|
||
true
|
||
);
|
||
|
||
wp_localize_script('swi-foot-editor-blocks', 'swiFootEditorData', array(
|
||
'rest_url' => esc_url_raw(rest_url('swi-foot/v1')),
|
||
'rest_nonce' => wp_create_nonce('wp_rest')
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Replace saved inline shortcode spans with their rendered shortcode output on the front-end.
|
||
* Spans are inserted by the editor format and contain a `data-shortcode` attribute.
|
||
*/
|
||
function swi_foot_render_inline_shortcodes($content)
|
||
{
|
||
if (stripos($content, 'swi-foot-inline-shortcode') === false) {
|
||
return $content;
|
||
}
|
||
|
||
return preg_replace_callback(
|
||
'/<span[^>]*class=["\']?[^"\'>]*swi-foot-inline-shortcode[^"\'>]*["\']?[^>]*data-shortcode=["\']([^"\']+)["\'][^>]*>.*?<\/span>/is',
|
||
function ($m) {
|
||
$sc = html_entity_decode($m[1]);
|
||
return do_shortcode($sc);
|
||
},
|
||
$content
|
||
);
|
||
}
|
||
|
||
add_filter('the_content', 'swi_foot_render_inline_shortcodes', 11);
|
||
?>
|