Plugin Directory

Changeset 3065987


Ignore:
Timestamp:
04/06/2024 12:15:48 PM (23 months ago)
Author:
mtreherne
Message:

Release of Version 3.13

Location:
eh-gms-feed
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • eh-gms-feed/tags/3.13/eh-gms-feed.php

    r3064521 r3065987  
    44 * Plugin URI: https://wordpress.org/plugins/eh-gms-feed/
    55 * Description: Show fixtures, results and tables from England Hockey GMS
    6  * Version: 3.12
     6 * Version: 3.13
    77 * Author: Matthew Treherne
    88 * Author URI: https://profiles.wordpress.org/mtreherne
  • eh-gms-feed/tags/3.13/includes/main-class.php

    r3064521 r3065987  
    77
    88include_once 'settings.php';
     9include_once 'coreAPI.php';
    910
    10 class EH_GMS_Feed {
     11class EH_GMS_Feed extends coreAPI {
    1112
    12     private $basename, $settings, $atts_show, $not_valid, $filter_match, $table_name, $fixture_data, $display_name, $show_gender, $show_list, $show_cal, $cal_summary, $id, $show_detail, $directions, $multiple_teams = [], $isLaravel = false, $teamlimit = 12;
    13     private $club_link, $team_link, $comp_link, $team_comps, $comp_name;
    14     private $args = ['method','show','team','comp_id','club_id','whatson','link','sort_by','options'];
    15     private $api = [
    16         'table' => ['transient' => 'COMPETITION LEAGUE', 'keys' => ['competitions'], 'error_bag' => null, 'expiry' => 'default'],
    17         'fixturesandresults' => ['transient' => 'TEAM', 'keys' => ['teams'], 'error_bag' => null, 'expiry' => 'default'],
    18         'matchdays' => ['transient' => 'CLUB MATCHDAYS', 'keys' => ['clubs'], 'error_bag' => null, 'expiry' => 'default'],
    19         'matchday' => ['suffix' => '', 'transient' => 'CLUB MATCHDAY', 'keys' => ['clubs', 'matchdays'], 'error_bag' => null, 'expiry' => 'static'],
    20         'teamsinclub' => ['suffix' => 'teams', 'transient' => 'CLUB TEAMS', 'keys' => ['clubs'], 'error_bag' => 'teamselected', 'expiry' => 'static'],
    21         'teamslist' => ['suffix' => 'teams', 'transient' => 'CLUB TEAMS', 'keys' => ['clubs'], 'error_bag' => null, 'expiry' => 'static'],
    22         'compsinfixtures' => ['suffix' => 'fixturesandresults', 'transient' => 'TEAM', 'keys' => ['teams'], 'error_bag' => 'competition', 'expiry' => 'default'],
    23         'competition' => ['suffix' => '', 'transient' => 'COMPETITION SUMMARY', 'keys' => ['competitions'], 'error_bag' => null, 'expiry' => 'default'],
    24         'fixture' => ['suffix' => '', 'transient' => 'FIXTURE', 'keys' => ['fixtures'], 'error_bag' => null, 'expiry' => 'default'],
    25     ];
     13    private $basename, $not_valid;
    2614
    2715    public function __construct () {
    2816        $this->basename = $GLOBALS['EH_GMS_Feed_basename'];
    2917        $this->settings = new Settings($this->basename);
    30         $this->settings->static_transient_expiry = '86400';
    3118        add_shortcode( 'gms', array( $this, 'gms_shortcode' ) );
    3219        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
    3320        add_action( 'wp_ajax_get_gms_table', array( $this, 'ajax_handler' ) );
    3421        add_action( 'wp_ajax_nopriv_get_gms_table', array( $this, 'ajax_handler' ) );
    35     }
    36 
    37     private function get_comp_list () {
    38         if (is_null($this->team_comps)) $this->team_comps = $this->is_team() ? $this->get_json('compsinfixtures', $this->atts_show['team']) : [];
    39         $comp_count = count($this->team_comps);
    40         $html = '<div'.(($comp_count == 0) ? ' style="display: none" ': '').'><label><span class="gms-nomobile">Competition </span><select name="comp_id"><option value="">- All Competitions -</option>';
    41         foreach ($this->team_comps as $key => $competition) $html .= '<option value="'.$key.'"'.(($this->is_competition() && $this->atts_show['comp_id'] == $key) || ($comp_count == 1) ? ' selected' : '').'>'.esc_html($competition['name']).'</option>';
    42         if ($this->is_competition() && !array_key_exists($this->atts_show['comp_id'], $this->team_comps)) {
    43             $html .= '<option value="'.$this->atts_show['comp_id'].'" selected>Previous Season</option>';
    44         }
    45         $html .= '</select></label></div>';
    46         return $html;
    47     }
    48 
    49     private function get_filter () {
    50         $html = '<div class="gms-filter"><div'.($this->is_team() ? ' style="display: none" ': '').'><label><span class="gms-nomobile">Team </span><select name="team"><option value="">- All Club Teams -</option>';
    51         $teams = $this->get_json('teamsinclub', $this->atts_show['club_id']);
    52         foreach ($teams as $key => $team) $html .= '<option value="'.$key.'"'.(($this->is_team() && $this->atts_show['team'] == $key) ? ' selected' : '').'>'.esc_html($team['teamName']).' ('.esc_html($team['gender']).')</option>';
    53         $html .= '</select></label></div>'.$this->get_comp_list().'<div><label><span class="gms-nomobile">What`s On </span><select name="whatson">';
    54         $whatson = $this->atts_show['whatson'];
    55         $options = ($whatson && !in_array($whatson,[7, 14, 31])) ? ['Days ('.$whatson.')' => $whatson] : [];
    56         $options = array_merge($options, [$this->is_team () ? '- All Match Days -' : '- Next Match Day -' => '', 'Week' => 7, 'Fortnight' => 14, 'Month' => 31]);
    57         foreach ($options as $key => $value) $html .= '<option value="'.$value.'"'.($whatson == $value ? ' selected' : '').'>'.$key.'</option>';
    58         $html .= '</select></label></div><div><fieldset><legend class="gms-nomobile">Show</legend>';
    59         foreach (['league' => 'League', 'results' => 'Results', 'fixtures' => 'Fixtures'] as $key => $value) {
    60             $html .= '<div><label><input type="checkbox" name="show" value="'.$key.'" '.(str_contains($this->atts_show['show'], $key) ? ' checked' : '').'> '.$value.'</label></div>';
    61         }
    62         $html .= '</fieldset></div><button type="button" class="gms-button">Refresh</button></div>';
    63         return $html;
    64     }
    65 
    66     private function get_json($key, $keys=[], $raw=false) {
    67     $keys = (array) $keys; $valid_json = true;
    68         $headers = ['headers' => ['Content-Type' => 'application/json;charset=UTF-8', 'x-functions-key' => $this->settings->gms_api_key]];
    69         $transient_name = 'eh_gms_feed '.$this->api[$key]['transient'];
    70         $gms_api_url = $this->settings->gms_api_url;
    71         foreach ($keys as $index => $value) {
    72             $transient_name .= ' '.$value;
    73             $gms_api_url .= ($this->api[$key]['keys'][$index] ?? '').'/'.$value.'/';
    74         }
    75         $gms_api_url .= $this->api[$key]['suffix'] ?? $key;
    76         $body = get_transient($transient_name);
    77         if ($body === false) {
    78             $response = wp_remote_get($gms_api_url, $headers);
    79             $http_code = wp_remote_retrieve_response_code($response);
    80             if ($http_code == 200) {
    81                 $body = wp_remote_retrieve_body($response);
    82                 if (strlen($transient_name) <= 172) {
    83                     switch ($this->api[$key]['expiry']) {
    84                         case 'static' : $expiry = $this->settings->static_transient_expiry; break;
    85                         case 'weekly' : $expiry = '604800'; break;
    86                         default : $expiry = $this->settings->default_transient_expiry;
    87                     }
    88                     set_transient($transient_name, $body, $expiry);
    89                 }
    90             }
    91             else {
    92                 $valid_json = false;
    93                 if ($http_code) $message = sprintf(esc_html__( 'Failed to get data with HTTP error code = %s', 'eh-gms-feed' ), $http_code);
    94                 else {
    95                     $error_message = is_wp_error($response) ? $response->get_error_message() : 'unknown';
    96                     $message = sprintf(esc_html__( 'Failed to get data with error: %s', 'eh-gms-feed' ), $error_message);
    97                 }
    98             }
    99         }
    100         if ($raw) return $valid_json ? $body : null;
    101         if ($valid_json) {
    102             $data = json_decode($body);
    103             if (json_last_error() === JSON_ERROR_NONE) {
    104                 if (!empty($data)) {
    105                     return($this->{'process_'.$key}($data));
    106                 }
    107                 else {
    108                     $valid_json = false;
    109                     $data_type = $this->api[$key]['suffix'] ?? $key;
    110                     switch ($data_type) {
    111                         case 'table' : $data_type = 'league'; break;
    112                         case 'fixturesandresults' : $data_type = 'results/fixtures'; break;
    113                     }
    114                     $message = sprintf(esc_html__( 'No %s data could be found.', 'eh-gms-feed' ), $data_type);
    115                 }
    116             }
    117             else {
    118                 $valid_json = false;
    119                 $message = esc_html__( 'Failed to decode JSON.', 'eh-gms-feed' );
    120             }
    121         }
    122         if ($this->api[$key]['error_bag']) {
    123             if (isset($this->error_bag)) $this->error_bag->add($this->api[$key]['error_bag'], $message);
    124             return [];
    125         }
    126         else return $this->show_api_error($message);
    127     }
    128 
    129     private function get_link($type, $slug) {
    130         return 'https://englandhockey.co.uk/'.$type.'s/'.$slug;
    131     }
    132 
    133     private function is_competition () {
    134         return !empty($this->atts_show['comp_id']);
    135     }
    136 
    137     private function is_team () {
    138         return !empty($this->atts_show['team']);
    139     }
    140 
    141     private function is_clubwide () {
    142         return !$this->is_team() && !empty($this->atts_show['club_id']);
    143     }
    144 
    145     private function is_sortby_time () {
    146         return $this->atts_show['sort_by'] == 'fixtureTime' || $this->is_reverse_date();
    147     }
    148 
    149     private function is_reverse_date () {
    150         return $this->atts_show['sort_by'] == 'reverseDate';
    151     }
    152 
    153     private function show_api_error ($message) {
    154         return '<p>'.$message.'</p>';
    155     }
    156 
    157     private function filter_whatson ($fixture_date) {
    158         $filter = false;
    159         if (is_numeric($this->atts_show['whatson'])) {
    160             $compare = (clone $fixture_date)->setTime(0,0);
    161             $diff = (new \DateTime())->setTime(0,0)->diff($compare)->format('%a');
    162             if ($diff > $this->atts_show['whatson']) $filter = true;
    163         }
    164         return $filter;
    165     }
    166 
    167     private function is_beforetoday($valid_date) {
    168         return $valid_date < (new \DateTime())->setTime(0,0);
    169     }
    170 
    171     private function is_clubteam ($team) {
    172         if ($team->id == $this->atts_show['team'] || ($this->is_clubwide() && $team->clubId == $this->atts_show['club_id'])) {
    173             if (!$this->club_link) $this->club_link = $this->get_link('club', $team->clubUrlSlug);
    174             if (!$this->team_link) $this->team_link = $this->get_link('team', $team->entityUrlSlug);
    175             return true;
    176         }
    177         return false;
    178     }
    179 
    180     private function show_goals ($events) {
    181         $goals = [];
    182         foreach ($events as $event) if (in_array($event->eventType,['FG','PC','PS'])) $goals[$event->memberId][] = $event;
    183         $showGoals = [];
    184         foreach ($goals as $goalsById) {
    185             $playerName = '';
    186             $playerGoals = [];
    187             foreach ($goalsById as $goal) {
    188                 if (!$playerName) $playerName = $goal->displayName;
    189                 $playerGoals[] = ($goal->minute ? $goal->minute . '&prime; ' : '') . $goal->eventType;
    190             }
    191             $showGoals[] = $playerName . ' (' . implode(', ',$playerGoals) . ')';
    192         }
    193         return implode(', ', $showGoals);
    194     }
    195 
    196     private function show_players($players) {
    197         $showPlayers = '';
    198         $withheld = 0;
    199         foreach ($players as $player) {
    200             if (!($player->consent || isset($player->shirtNumber))) { $withheld += 1; continue; }
    201             $playerEvents = [];
    202             foreach ($player->playerEvents as $event) {
    203                 switch ($event->eventType) {
    204                     case 'GC': $showType = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M1.892 20.5 12 3.959 22.109 20.5z" fill="#0FBD00" stroke="#0DA300"/></svg>'; break;
    205                     case 'YC': $showType = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect x="3.5" y=".5" width="17" height="23" rx="1.5" fill="#FFE500" stroke="#DBCA39"/></svg>'; break;
    206                     case 'RC': $showType = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10.5" fill="#E0251B" stroke="#E0251B"/></svg>'; break;
    207                     default : $showType = '<b>'.$event->eventType.'</b>';
    208                 }
    209                 $playerEvents[] = ($event->minute ? '<b>'.$event->minute . '&prime;&nbsp;</b>' : '') . $showType;
    210             }
    211             switch ($player->otherRoleDescription) {
    212                 case 'Goalkeeper' : $role = ' (GK)'; break;
    213                 case 'Captain' : $role = ' (C)'; break;
    214                 default : $role = '';
    215             }
    216             $showPlayers .= '<li>'.($player->shirtNumber ?? '') . ' ' . $player->displayName . $role . (!empty($playerEvents) ? ('&nbsp;' . implode(',&nbsp;',$playerEvents)) : '') . '</li>';
    217         }
    218         if ($withheld) $showPlayers .= ($withheld > 1) ? '<li>Names Withheld (&times;'.$withheld.')</li>' : '<li>Name Withheld</li>';
    219         return $showPlayers;
    220     }
    221 
    222     private function show_officials($officials) {
    223         $showOfficials = '';
    224         foreach ($officials as $official) {
    225             if ($official->displayName != 'Name Withheld') $showOfficials .= '<li>' . $official->role . ': ' . $official->displayName . '</li>';
    226         }
    227         return $showOfficials;
    228     }
    229 
    230     private function fixture_summary ($fixture, $valid_date, $show_detail=false) {
    231         $html = '';
    232         $fixture_card = [
    233             'Date' => $valid_date->format('d M Y'),
    234             'Time' => $fixture->fixtureTime == '00:00' ? '' : $fixture->fixtureTime,
    235             'Home Team' => $fixture->homeTeam->teamName,
    236             'Score' => '',
    237             'Away Team' => $fixture->awayTeam->teamName,
    238             'Venue' => !empty($fixture->venue) ? ($this->show_detail || $show_detail ? esc_html($fixture->venue) : '<a href="https://www.google.com/maps/search/?api=1&query='.urlencode($fixture->venue).'" target="_blank">'.esc_html($fixture->venue).'</a>') : '',
    239         ];
    240         if ($show_detail) {
    241             $home_goals = $this->show_goals($fixture->homeTeamEvents);
    242             $away_goals = $this->show_goals($fixture->awayTeamEvents);
    243             $address = !empty($fixture->venueDetails->address) ? preg_replace ('#(\w+,)(\w+)#', '$1 $2' , $fixture->venueDetails->address) : null;
    244             if (!($fixture->isResult || $this->is_beforetoday($valid_date))) $this->directions = ['venue' => $fixture->venue ?? '', 'll' => null, 'address' => $address, 'postcode' => $fixture->venueDetails->postCode ?? null];
    245             $address .= !empty($address) ? (!empty($fixture->venueDetails->postCode) ? ', '.$fixture->venueDetails->postCode : '') : '';
    246         }
    247         $score_class = '';
    248         $home_attr = $away_attr = $home_class = $away_class = [];
    249         if ($fixture->isResult && !$fixture->isBye) {
    250             $fixture_card['Score'] = $fixture->homeTeamScore . ' : ' . $fixture->awayTeamScore;
    251             if ($fixture->status == 'Postponed' || ($fixture->homeTeamScore == 'P' && $fixture->awayTeamScore == 'P'));
    252             elseif ($fixture->status == 'Cancelled' || ($fixture->homeTeamScore == 'C' && $fixture->awayTeamScore == 'C'));
    253             elseif ($fixture->homeTeamScore == $fixture->awayTeamScore) $score_class = 'gms-draw';
    254             elseif (($fixture->homeTeam->id == $this->atts_show['team'] || ($this->is_clubwide() && $fixture->homeTeam->clubId == $this->atts_show['club_id'])) && $fixture->homeTeamScore > $fixture->awayTeamScore) $score_class = 'gms-win';
    255             elseif (($fixture->awayTeam->id == $this->atts_show['team'] || ($this->is_clubwide() && $fixture->awayTeam->clubId == $this->atts_show['club_id'])) && $fixture->homeTeamScore < $fixture->awayTeamScore) $score_class = 'gms-win';
    256             else $score_class = 'gms-loss';
    257         }
    258         if ($this->is_clubteam($fixture->homeTeam) && $this->is_clubwide()) {
    259             $home_class[] = 'gms-clubteam';
    260             $home_attr[] = 'data-team="'.($fixture->homeTeam->id).'"';
    261             if ($this->show_gender) $fixture_card['Home Team'] .= ' ('.$fixture->homeTeam->gender.')';
    262         }
    263         if ($this->is_clubteam($fixture->awayTeam) && $this->is_clubwide()) {
    264             $away_class[] = 'gms-clubteam';
    265             $away_attr[] = 'data-team="'.($fixture->awayTeam->id).'"';
    266             if ($this->show_gender) $fixture_card['Away Team'] .= ' ('.$fixture->awayTeam->gender.')';
    267         }
    268         if ($this->show_list) {
    269             $statusDisplay = !in_array($fixture->status, ['Active','Result','Bye']) ? $fixture->status : '';
    270             if ($fixture->isResult && ($fixture->homeTeamShootoutScore > 0 || $fixture->awayTeamShootoutScore > 0)) $statusDisplay = 'Shootout '.$fixture->homeTeamShootoutScore.' - '. $fixture->awayTeamShootoutScore;
    271             $home_attr[] = 'class="'.implode(' ',$home_class).'"';
    272             $away_attr[] = 'class="'.implode(' ',$away_class).'"';
    273             if ($fixture->isBye) {
    274                 $divide = '- : -';
    275                 $divide_attr = ' class="gms-carddivide gms-cardnoscore"';
    276             }
    277             elseif ($fixture->isResult) {
    278                 $divide = $fixture_card['Score'];
    279                 $divide_attr = ' class="gms-carddivide '.($score_class ?: 'gms-cardnoscore').'"';
    280             }
    281             else {
    282                 $divide = $fixture_card['Time'] ?: 'TBC';
    283                 $divide_attr = ' class="gms-carddivide gms-cardtime"';
    284             }
    285             $html .= '<div class="gms-card'.($this->show_detail ? ' gms-detaillink' : '').'"'.($this->show_detail ? ' data-fixture="'.$fixture->id.'"': '').'>'
    286                 .($show_detail ? '<div class="gms-cardtitle">Fixture Details</div><div class="gms-cardcomp">'.$fixture->competitionName.'</div>': '')
    287                 .'<div class="gms-carddate">'.$fixture_card['Date'].'</div>'
    288                 .'<div class="gms-cardfixture"><div class="gms-cardhome"><div '.implode(' ',$home_attr).'>'.$fixture_card['Home Team'].'</div></div><div'.$divide_attr.'>'.$divide.'</div><div class="gms-cardaway"><div '.implode(' ',$away_attr).'>'.$fixture_card['Away Team'].'</div></div></div>'
    289                 .(($show_detail && ($home_goals || $away_goals)) ? '<div class="gms-cardscorers"><div class="gms-cardhome"><div>'.$home_goals.'</div></div><div class="gms-carddivide"></div><div class="gms-cardaway"><div>'.$away_goals.'</div></div></div>' : '')
    290                 .($statusDisplay ? '<div class="gms-cardstatus">'.$statusDisplay.'</div>' : '')
    291                 .'<div class="gms-cardvenue">'.($fixture_card['Venue'] ?: 'Venue TBC').'</div>'
    292                 .($show_detail && $address ? '<div class="gms-cardaddress">'.$address.'</div>' : '')
    293                 .'</div>';
    294             if ($show_detail) {
    295                 $participant_details = false;
    296                 $html .= '<div class="gms-fixturedetails">';
    297                 foreach (['home','away'] as $team) {
    298                     $showPlayers = $this->show_players($fixture->{$team . 'Players'});
    299                     $showOfficials = $this->show_officials($fixture->{$team. 'TeamOfficials'});
    300                     if ($showPlayers || $showOfficials) {
    301                         $club_logo = $fixture->{$team . 'Team'}->clubLogoUrl ?? null;
    302                         $participant_details = true;
    303                         $html .= '<div>';
    304                         if ($showPlayers) $html .= '<div class="gms-players">'.($club_logo ? '<img src="'.$club_logo.'" onerror="this.style.display=\'none\'"></img>' : '').'<b>'.$fixture->{$team.'Team'}->teamName.'</b><ul>'.$showPlayers.'</ul></div>';
    305                         if ($showOfficials) $html .= '<div class="gms-officials">'.($showPlayers ? '<br/>' : '').'<b>Coaching Roles</b><ul>'.$showOfficials.'</ul></div>';
    306                         $html .= '</div>';
    307                     }
    308                 }
    309                 $showOfficials = $this->show_officials($fixture->officials);
    310                 if ($showOfficials) {
    311                     $participant_details = true;
    312                     $html .= '<div class="gms-officials"><b>Match Officials</b><ul>'.$showOfficials.'</ul></div>';
    313                 }
    314                 if (!$participant_details) $html .= '<div><b>No more details available</b></div>';
    315                 $html .= '</div>';
    316             }
    317         }
    318         else {
    319             $home_attr[] = 'class="'.implode(' ',$home_class).'"';
    320             $away_attr[] = 'class="'.implode(' ',$away_class).'"';
    321             $html .= $this->show_detail ? '<tr class="gms-detaillink" data-fixture="'.$fixture->id.'">': '<tr>';
    322             foreach ($this->fixture_data as $column_title => $field_name) {
    323                 $value = $fixture_card[$column_title];
    324                 switch ($column_title) {
    325                     case 'Home Team' : $attr = implode(' ',$home_attr); break;
    326                     case 'Away Team' : $attr = implode(' ',$away_attr); break;
    327                     case 'Score' : $attr = 'class="'.$score_class.'"';  break;
    328                     default : $attr = '';
    329                 }
    330                 $html .= '<td '.$attr.'>'.($column_title != 'Venue' ? esc_html($value) : $value).'</td>';
    331             }
    332             $html .= '</tr>';
    333         }
    334         return $html;
    335     }
    336 
    337     private function process_matches ($fixtures) {
    338         $html = '';
    339         foreach ($fixtures as $fixture) {
    340             $valid_date = new \DateTime($fixture->fixtureDate);
    341             if ($fixture->isBye) continue;
    342             if ($this->table_name == 'fixtures') {
    343                 if ($fixture->isResult || $this->is_beforetoday($valid_date)) continue;
    344             }
    345             elseif ($this->table_name == 'results') {
    346                 if (!$fixture->isResult && !$this->is_beforetoday($valid_date)) continue;
    347             }
    348             if ($this->filter_whatson($valid_date)) continue;
    349             $this->filter_match = true;
    350             $html .= $this->fixture_summary($fixture, $valid_date);
    351         }
    352         return $html;
    353     }
    354 
    355     private function process_competition ($data) {
    356         if (!$this->comp_link) $this->comp_link = $this->get_link('competition', $data->entityUrlSlug);
    357         $this->comp_name = $data->name . ' ('.$data->seasonName.')';
    358         if (empty($data->table)) return $this->get_json('table', $this->atts_show['comp_id']);
    359         return $this->process_table($data->table);
    360     }
    361 
    362     private function process_table ($data, $custom=false) {
    363         $html = ''; $link = $this->comp_link;
    364         $league_data = ['Team' => 'teamName', 'Played' => 'gamesPlayed', 'Won' => 'gamesWon', 'Drawn' => 'gamesDrawn', 'Lost' => 'gamesLost', 'For' => 'goalsFor', 'Against' => 'goalsAgainst', 'GD' => 'goalsDifference', 'Points' => 'totalPoints'];
    365         if ($custom) { $league_data['PPG'] = 'PPG'; $league_data['Form'] = 'form'; }
    366         $html .= '<table class="gms-table gms-table-'.$this->display_name.($custom ? ' gms-table-custom' : '').'"><thead><tr><th></th>';
    367         foreach ($league_data as $column_title => $field_name) $html .= '<th>'.$column_title.'</th>';
    368         $html .= '</tr></thead><tbody>';
    369         foreach ($data as $position => $team) {
    370             $class = '';
    371             if (!$custom && $team->teamId == $this->atts_show['team']) {
    372                 $class = ' class="gms-clubteam"';
    373                 if (!$link) $link = $this->get_link('team', $team->teamEntityUrlSlug);
    374             }
    375             $html .= '<tr'.$class.'><td>'.($position+1).'</td>';
    376             foreach ($league_data as $field_name) {
    377                 if ($field_name == 'form') {
    378                     if (count($team->form) > 5) $team->form = array_slice($team->form, -5, 5);
    379                     $team->form = implode(' ', $team->form);
    380                     $html .= '<td>'.$team->form.'</td>';
    381                 }
    382                 else $html .= '<td>'.(isset($field_name, $team->{$field_name}) ? esc_html($team->{$field_name}) : '').'</td>';
    383             }
    384             $html .= '</tr>';
    385         }
    386         if (empty($data)) $html .= '<tr><td colspan="'.(count($league_data)+1).'">No data for teams found</td></tr>';
    387         $html .= '</tbody></table>';
    388         $html .= '<div class="gms-footnote">'.($link ? sprintf(esc_html__( '[%5$s%3$s %1$s also found at%4$s %2$s]', 'eh-gms-feed' ), $this->comp_name ? 'for '.$this->comp_name : '', '<a href="'.$link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>', ($custom ? esc_html__('Data') : esc_html__('Table'))) : ($custom ? esc_html__('[League table for selected teams]') : '')).'</div>';
    389         return $html;
    390     }
    391    
    392     private function process_fixturesandresults($data) {
    393         $html = '';
    394         foreach ($data as $competition) {
    395             $this->team_comps[$competition->competitionId] = ['name' => $competition->competitionName];
    396             if ($this->is_competition() && $competition->competitionId != $this->atts_show['comp_id']) continue;
    397             $this->filter_match = false;
    398             if ($this->show_list) $html .= '<div class="gms-list">';
    399             else {
    400                 $html .= '<table class="gms-table gms-table-'.$this->display_name.'"><thead><tr>';
    401                 foreach ($this->fixture_data as $column_title => $field_name) $html .= '<th>'.$column_title.'</th>';
    402                 $html .= '</tr></thead><tbody>';
    403             }
    404             if ($this->is_reverse_date()) {
    405                 usort($competition->fixtures, function ($a,$b) {
    406                     return strcmp($b->fixtureDate, $a->fixtureDate);
    407                 });
    408             }
    409             $html .= $this->process_matches($competition->fixtures);
    410             if ($this->show_list) {
    411                 if (!$this->filter_match) $html .= '<div>No fixtures found</div>';
    412                 $html .= '</div>';
    413             }
    414             else {
    415                 if (!$this->filter_match) $html .= '<tr><td colspan="'.count($this->fixture_data).'">No fixtures found</td></tr>';
    416                 $html .= '</tbody></table>';
    417             }
    418             $html .= '<div class="gms-footnote">'.($this->team_link ? sprintf(esc_html__( '[Team %1$s%4$s for %2$s also found at%5$s %3$s]', 'eh-gms-feed'), 'fixtures', $competition->competitionName, '<a href="'.$this->team_link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>') : '').'</div>';
    419         }
    420         return $html ?: '<p>'.sprintf(esc_html__( 'No %s were found that matched the criteria.', 'eh-gms-feed' ), 'fixtures').'</p>';
    421     }
    422 
    423     private function process_matchday($data) {
    424         $html = '';
    425         if ($this->is_sortby_time()) { $sort = true; $sorted_fixtures = []; }
    426         else $sort = false;
    427         foreach ($data as $competition) {
    428             if ($sort) $sorted_fixtures = array_merge($sorted_fixtures, $competition->fixtures);
    429             else $html .= $this->process_matches($competition->fixtures);
    430         }
    431         if ($sort) {
    432             usort($sorted_fixtures, function ($a,$b) {
    433                 return strcmp($a->fixtureTime, $b->fixtureTime);
    434             });
    435             $html .= $this->process_matches($sorted_fixtures);
    436         }
    437         return $html;
    438     }
    439 
    440     private function process_matchdays($data) {
    441         $html = '';
    442         if (!empty($data->matchDays)) {
    443             $this->filter_match = false;
    444             if ($this->show_list) $html .= '<div class="gms-list">';
    445             else {
    446                 $html .= '<table class="gms-table gms-table-'.$this->display_name.'"><thead><tr>';
    447                 foreach ($this->fixture_data as $column_title => $field_name) $html .= '<th>'.$column_title.'</th>';
    448                 $html .= '</tr></thead><tbody>';
    449             }
    450             foreach (($this->is_reverse_date() ? array_reverse($data->matchDays) : $data->matchDays) as $matches) {
    451                 $valid_date = new \DateTime($matches->matchDay);
    452                 if ($this->table_name == 'fixtures' && $this->is_beforetoday($valid_date)) continue;
    453                 if ($this->filter_whatson($valid_date)) continue;
    454                 if (is_numeric($this->atts_show['whatson']) && $matches->matchDay != $data->nextMatchDay && !isset($matches->competitions)) {
    455                     $html .= $this->get_json('matchday', [$this->atts_show['club_id'], $matches->id]);
    456                 }
    457                 else {
    458                     if (!empty($matches->competitions)) $html .= $this->process_matchday($matches->competitions);
    459                 }
    460             }
    461             if ($this->show_list) {
    462                 if (!$this->filter_match) $html .= '<div>No fixtures found</div>';
    463                 $html .= '</div>';
    464             }
    465             else {
    466                 if (!$this->filter_match) $html .= '<tr><td colspan="'.count($this->fixture_data).'">No fixtures found</td></tr>';
    467                 $html .= '</tbody></table>';
    468             }
    469             $html .= '<div class="gms-footnote">'.($this->club_link ? sprintf(esc_html__( '[Club%3$s match day %1$s also found at%4$s %2$s]', 'eh-gms-feed' ), 'fixtures', '<a href="'.$this->club_link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>') : '').'</div>';
    470         }
    471         return $html;
    472     }
    473 
    474     private function process_teamslist($data) {
    475         $this->filter_match = false;
    476         $colspan = $this->show_cal ? 3 : 2;
    477         $cal_options = $this->cal_summary ? '&options=summary:'.$this->cal_summary : '';
    478         $html =  $this->show_cal ? '<p>If your calendar app supports subscribing to internet calendars (the WebCal protocol), then click on Copy WebCal for link to paste into your calendar app. For more help and advanced options please goto <a href="https://gmsfeed.co.uk/webcal?club_id='.$this->atts_show['club_id'].'" target="_blank">GMS Feed WebCal</a>.</p><p><span style="word-break: break-all" id="gms-webcal-link"><i>Click on Copy WebCal to select and copy link</i></span></p>' : '';
    479         $html .= '<table class="gms-table gms-table-'.$this->display_name.'"><thead><tr><th>England Hockey Link</th><th>Gender</th>'.($this->show_cal ? '<th>Fixtures Calendar</th>' : '').'</tr></thead><tbody>';
    480         foreach ($data as $team) {
    481             $this->filter_match = true;
    482             $calid = 'gms_webcal_'.$team->id;
    483             $webcal = $this->show_cal ? '<td><button type="button" class="gms-button gms-copy" data-copy_id="gms-webcal-link" data-copy_text="'.esc_html('webcal://gmsfeed.co.uk/api/calendar?team='.$team->id.$cal_options).'" title="'.esc_html($team->teamName).'">Copy WebCal</button></td>' : '';
    484             $html .= '<tr><td><a href="'.esc_attr($this->get_link('team', $team->entityUrlSlug)).'" target="_blank">'.esc_html($team->teamName).'</a></td><td>'.esc_html($team->gender).'</td>'.$webcal.'</tr>';
    485             if (!$this->club_link) $this->club_link = $this->get_link('club', $team->clubUrlSlug);
    486         }
    487         if (!$this->filter_match) $html .= '<tr><td colspan='.$colspan.'>No teams found</td></tr>';
    488         $html .= '</tbody></table><div class="gms-footnote">'.($this->club_link ? sprintf(esc_html__( '[Club %1$s%3$s also found at%4$s %2$s]', 'eh-gms-feed' ), 'teams', '<a href="'.$this->club_link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>') : '').'</div>';
    489         return $html;
    490     }
    491 
    492     private function process_fixture($data) {
    493         $html = '<div class="gms-list">';
    494         $html .= $this->fixture_summary($data, new \DateTime($data->fixtureDate), true);
    495         $html .= '</div>';
    496         $html .= '<div class="gms-footnote">'.sprintf(esc_html__( '[Fixture %2$s also found at%3$s %1$s]', 'eh-gms-feed'), '<a href="'.$this->get_link('fixture', $this->id).'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>').'</div>';
    497         return $html;
    498     }
    499 
    500     private function get_table() {
    501         $html = '';
    502         $tables = [];
    503         if ($this->atts_show['show'] == 'fixture') $tables[] = 'fixture';
    504         if (str_contains($this->atts_show['show'], 'league')) $tables[] = 'league';
    505         if (str_contains($this->atts_show['show'], 'results')) {
    506             $tables[] = (str_contains($this->atts_show['show'], 'fixtures')) ? 'combined' : 'results';
    507         }
    508         elseif (str_contains($this->atts_show['show'], 'fixtures')) $tables[] = 'fixtures';
    509         if (str_contains($this->atts_show['show'], 'teams')) $tables[] = 'teams';
    510         foreach ($tables as $table_name) {
    511             $this->table_name = $table_name;
    512             $this->display_name = ($table_name == 'combined') ? 'results' : $table_name;
    513             $this->fixture_data = ['Date' => 'fixtureDate', 'Time' => 'fixtureTime', 'Home Team' => ['homeTeam','teamName'], 'Score' => ['homeTeamScore', 'awayTeamScore'], 'Away Team' => ['awayTeam','teamName'], 'Venue' => 'venue'];
    514             if ($table_name == 'fixtures') unset($this->fixture_data['Score']);
    515             if ($table_name == 'league') {
    516                 if ($this->atts_show['link']) $this->comp_link = $this->atts_show['link'];
    517                 if ($this->is_competition()) $html .= $this->get_json('competition', $this->atts_show['comp_id']);
    518                 else $html .= $this->multiple_teams();
    519             }
    520             elseif (($table_name == 'fixtures' || $table_name == 'results' || $table_name == 'combined') && $this->is_team()) {
    521                 if ($this->atts_show['link']) $this->team_link = $this->atts_show['link'];
    522                 $html .= $this->get_json('fixturesandresults', $this->atts_show['team']);
    523             }
    524             elseif (($table_name == 'fixtures' || $table_name == 'results' || $table_name == 'combined') && $this->is_clubwide()) {
    525                 if ($this->atts_show['link']) $this->club_link = $this->atts_show['link'];
    526                 $html .= $this->get_json('matchdays', $this->atts_show['club_id']);
    527             }
    528             elseif ($table_name == 'teams' && $this->is_clubwide()) {
    529                 if ($this->atts_show['link']) $this->club_link = $this->atts_show['link'];
    530                 $html .= $this->get_json('teamslist', $this->atts_show['club_id']);
    531             }
    532             elseif ($table_name == 'fixture' && $this->id) {
    533                 $this->show_list = true;
    534                 $html .= $this->get_json('fixture', $this->id);
    535             }
    536         }
    537         return $html;
    538     }
    539 
    540     private function process_teams ($data) {
    541         $teams = [];
    542         foreach ($data as $team) $teams[$team->id] = ['teamName' => $team->teamName, 'clubId' => $team->clubId, 'clubName' => $team->clubName, 'slug' => $team->entityUrlSlug, 'clubSlug' => $team->clubUrlSlug, 'gender' => $team->gender, 'clubLogoUrl' => $team->clubLogoUrl ?? null];
    543         return $teams;
    544     }
    545 
    546     private function process_teamsinclub ($data) {
    547         return $this->process_teams($data);
    548     }
    549 
    550     private function process_compsinfixtures($data) {
    551         $competitions = [];
    552         // seasonId is available but season (name) is ONLY within fixtures object
    553         foreach ($data as $competition) $competitions[$competition->competitionId] = ['name' => $competition->competitionName, 'slug' => $competition->competitionEntityUrlSlug];
    554         return $competitions;
    555     }
    556 
    557     private function multiple_teams() {
    558         $html = '';
    559         $api = 'fixturesandresults';
    560         $json_data = [];
    561         $required_data = [];
    562         $no_data = 0;
    563         // Try the default data cache first
    564         foreach ($this->multiple_teams as $teamID) {
    565             $body = get_transient('eh_gms_feed '.$this->api[$api]['transient'].' '.$teamID);
    566             if ($body === false) $required_data[] = $teamID;
    567             else $json_data[$teamID] = $body;
    568         }
    569         // If Laravel then use Guzzle and do requests in parallel
    570         if ($this->isLaravel) {
    571             $refreshlist = collect();
    572             foreach ($required_data as $teamID) {
    573                 $object = new \stdClass;
    574                 $object->api = $api;
    575                 $object->api_key = $teamID;
    576                 $refreshlist->push($object);
    577             }
    578             if ($refreshlist->isNotEmpty()) $this->refresh_cache($refreshlist);
    579         }
    580         foreach ($required_data as $teamID) {
    581             $json_data[$teamID] = $this->get_json($api, $teamID, true);
    582         }
    583         if (!empty($json_data)) {
    584             $league = [];
    585             foreach ($json_data as $key => $snapshot) {
    586                 if ($snapshot && ($data = json_decode($snapshot)) && json_last_error() === JSON_ERROR_NONE && !empty($data)) {
    587                     $teamname = $next_fixture_date = null;
    588                     $gp = $gw = $gd = $gl = $gf = $ga = 0;
    589                     $form = [];
    590                     foreach ($data as $competition) {
    591                         foreach ($competition->fixtures as $fixture) {
    592                             $isHome = $fixture->homeTeamId == $key;
    593                             if (!$teamname) $teamname = $isHome ? $fixture->homeTeam->teamName : $fixture->awayTeam->teamName;
    594                             if ($fixture->isBye) continue;
    595                             $valid_date = new \DateTime($fixture->fixtureDate);
    596                             if ($fixture->isResult) {
    597                                 if ($fixture->status == 'Postponed' || ($fixture->homeTeamScore == 'P' && $fixture->awayTeamScore == 'P')) continue;
    598                                 elseif ($fixture->status == 'Cancelled' || ($fixture->homeTeamScore == 'C' && $fixture->awayTeamScore == 'C')) continue;
    599                                 else {
    600                                     $gp++;
    601                                     $gf += $isHome ? $fixture->homeTeamScoreAsInt : $fixture->awayTeamScoreAsInt;
    602                                     $ga += $isHome ? $fixture->awayTeamScoreAsInt : $fixture->homeTeamScoreAsInt;
    603                                     if ($fixture->homeTeamScoreAsInt == $fixture->awayTeamScoreAsInt) { $gd++; $form[] = '<span class="gms-form gms-draw">D</span>'; }
    604                                     else if (($isHome && $fixture->homeTeamScoreAsInt > $fixture->awayTeamScoreAsInt) || (!$isHome && $fixture->homeTeamScoreAsInt < $fixture->awayTeamScoreAsInt)) { $gw++; $form[] = '<span class="gms-form gms-win">W</span>'; }
    605                                     else { $gl++; $form[] = '<span class="gms-form gms-loss">L</span>'; }
    606                                 }
    607                             }
    608                             elseif ($this->is_beforetoday($valid_date)) continue;
    609                             elseif (!$next_fixture_date || $valid_date < $next_fixture_date) $next_fixture_date = $valid_date;
    610                         }
    611                     }
    612                     if ($teamname) {
    613                         $points = $gw * 3 + $gd;
    614                         $object = new \stdClass;
    615                         $object->teamId = $key;
    616                         $object->teamName = $teamname;
    617                         $object->gamesPlayed = $gp;
    618                         $object->gamesWon = $gw;
    619                         $object->gamesDrawn = $gd;
    620                         $object->gamesLost = $gl;
    621                         $object->goalsFor = $gf;
    622                         $object->goalsAgainst = $ga;
    623                         $object->goalsDifference = $gf - $ga;
    624                         $object->totalPoints = $points;
    625                         $object->PPG = number_format($gp ? $points/$gp : 0, 2, '.', '');
    626                         $object->form = $form;
    627                         $league[] = $object;
    628                     }
    629                 }
    630                 else $no_data++;
    631             }
    632             usort($league, function ($a,$b) {
    633                 if ($a->PPG != $b->PPG) return $a->PPG < $b->PPG ? 1 : -1;
    634                 if ($a->goalsDifference != $b->goalsDifference) return $a->goalsDifference < $b->goalsDifference ? 1 : -1;
    635                 if ($a->goalsFor != $b->goalsFor) return $a->goalsFor < $b->goalsFor ? 1 : -1;
    636                 if ($a->gamesWon != $b->gamesWon) return $a->gamesWon < $b->gamesWon ? 1 : -1;
    637                 return 0;
    638             });
    639             $html .= $this->process_table($league, true);
    640             if ($no_data) $html .= $this->show_api_error(sprintf(esc_html__( 'Failed to retrieve data for %s of selected team(s)', 'eh-gms-feed' ), $no_data));
    641         }
    642         else $html .= $this->show_api_error(esc_html__( 'You have selected a custom league table without any teams', 'eh-gms-feed' ));
    643         return $html;
    644     }
    645 
    646     private function ajax_method () {
    647         wp_enqueue_script('EH_GMS_Feed');
    648         $atts = '';
    649         foreach ($this->args as $value) {
    650             if (!empty($this->atts_show[$value])) $atts .= ' data-'.$value.'="'.esc_attr($this->atts_show[$value]).'"';
    651         }
    652         return '<div class="gms-wrapper gms-ajax"'.$atts.'></div>';
     22        parent::__construct();
    65323    }
    65424
     
    71282        }
    71383        foreach (explode('+',$this->atts_show['show']) as $show) {
    714             if (!in_array($show,['fixtures','results','league','teams','fixture'])) {
     84            if (!in_array($show, $this->valid_show)) {
    71585                $message = sprintf(esc_html__( 'Please enter a "show" parameter (%s) equal to "fixtures", "results", "league" or "teams".', 'eh-gms-feed' ), $show ?: 'empty');
    71686                $this->not_valid .= '<p>'.$message.'</p>';
     
    758128    public function gms_shortcode ( $atts = [] ) {
    759129        if ($this->validate_atts($atts)) {
    760             if ($this->settings->default_ajax == 'yes' || $this->atts_show['method'] == 'api-dynamic')
    761                 $html = $this->ajax_method ();
     130            if ($this->settings->default_ajax == 'yes' || $this->atts_show['method'] == 'api-dynamic') {
     131                wp_enqueue_script('EH_GMS_Feed');
     132                $html_atts = '';
     133                foreach ($this->args as $value) {
     134                    if (!empty($this->atts_show[$value])) $html_atts .= ' data-'.$value.'="'.esc_attr($this->atts_show[$value]).'"';
     135                }
     136                $html = '<div class="gms-wrapper gms-ajax"'.$html_atts.'></div>';
     137            }
    762138            elseif ($this->atts_show['method'] == 'api') $html = '<div class="gms-wrapper">'.$this->get_table().'</div>';
    763139            return $html;
     
    767143
    768144    public function enqueue_scripts () {
    769         wp_register_script('EH_GMS_Feed', plugin_dir_url(__DIR__).'js/eh-gms-feed.js', ['jquery'], '3.12', true);
     145        wp_register_script('EH_GMS_Feed', plugin_dir_url(__DIR__).'js/eh-gms-feed.js', ['jquery'], '3.13', true);
    770146        wp_localize_script('EH_GMS_Feed', 'eh_gms_feed_ajax_obj', ['ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce('get_gms_table')]);
    771147        wp_register_style('EH_GMS_Feed', plugin_dir_url(__DIR__).'css/gms-default.css',[],'3.12');
    772148        if ($this->settings->default_css == 'yes') wp_enqueue_style('EH_GMS_Feed');
    773149    }
     150
    774151}
    775152
  • eh-gms-feed/tags/3.13/js/eh-gms-feed.js

    r3064521 r3065987  
    112112                    .always(function() {
    113113                        var goback = jQuery('<button type="button" class="gms-button">Go Back</button>').appendTo(detail);
    114                         back_btns.push = goback[0];
     114                        back_btns.push(goback[0]);
    115115                        back_btns.forEach(function (ele) {
    116116                            ele.addEventListener('click', function() {
  • eh-gms-feed/tags/3.13/readme.txt

    r3064521 r3065987  
    55Tested up to: 6.5
    66Requires PHP: 5.3
    7 Stable tag: 3.12
     7Stable tag: 3.13
    88License: GPLv2
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    6262
    6363== Changelog ==
     64
     65= 3.13 =
     66* Fix fault with back button on fixture detail
     67* Added showGender option to custom league table
    6468
    6569= 3.12 =
  • eh-gms-feed/trunk/eh-gms-feed.php

    r3064521 r3065987  
    44 * Plugin URI: https://wordpress.org/plugins/eh-gms-feed/
    55 * Description: Show fixtures, results and tables from England Hockey GMS
    6  * Version: 3.12
     6 * Version: 3.13
    77 * Author: Matthew Treherne
    88 * Author URI: https://profiles.wordpress.org/mtreherne
  • eh-gms-feed/trunk/includes/main-class.php

    r3064521 r3065987  
    77
    88include_once 'settings.php';
     9include_once 'coreAPI.php';
    910
    10 class EH_GMS_Feed {
     11class EH_GMS_Feed extends coreAPI {
    1112
    12     private $basename, $settings, $atts_show, $not_valid, $filter_match, $table_name, $fixture_data, $display_name, $show_gender, $show_list, $show_cal, $cal_summary, $id, $show_detail, $directions, $multiple_teams = [], $isLaravel = false, $teamlimit = 12;
    13     private $club_link, $team_link, $comp_link, $team_comps, $comp_name;
    14     private $args = ['method','show','team','comp_id','club_id','whatson','link','sort_by','options'];
    15     private $api = [
    16         'table' => ['transient' => 'COMPETITION LEAGUE', 'keys' => ['competitions'], 'error_bag' => null, 'expiry' => 'default'],
    17         'fixturesandresults' => ['transient' => 'TEAM', 'keys' => ['teams'], 'error_bag' => null, 'expiry' => 'default'],
    18         'matchdays' => ['transient' => 'CLUB MATCHDAYS', 'keys' => ['clubs'], 'error_bag' => null, 'expiry' => 'default'],
    19         'matchday' => ['suffix' => '', 'transient' => 'CLUB MATCHDAY', 'keys' => ['clubs', 'matchdays'], 'error_bag' => null, 'expiry' => 'static'],
    20         'teamsinclub' => ['suffix' => 'teams', 'transient' => 'CLUB TEAMS', 'keys' => ['clubs'], 'error_bag' => 'teamselected', 'expiry' => 'static'],
    21         'teamslist' => ['suffix' => 'teams', 'transient' => 'CLUB TEAMS', 'keys' => ['clubs'], 'error_bag' => null, 'expiry' => 'static'],
    22         'compsinfixtures' => ['suffix' => 'fixturesandresults', 'transient' => 'TEAM', 'keys' => ['teams'], 'error_bag' => 'competition', 'expiry' => 'default'],
    23         'competition' => ['suffix' => '', 'transient' => 'COMPETITION SUMMARY', 'keys' => ['competitions'], 'error_bag' => null, 'expiry' => 'default'],
    24         'fixture' => ['suffix' => '', 'transient' => 'FIXTURE', 'keys' => ['fixtures'], 'error_bag' => null, 'expiry' => 'default'],
    25     ];
     13    private $basename, $not_valid;
    2614
    2715    public function __construct () {
    2816        $this->basename = $GLOBALS['EH_GMS_Feed_basename'];
    2917        $this->settings = new Settings($this->basename);
    30         $this->settings->static_transient_expiry = '86400';
    3118        add_shortcode( 'gms', array( $this, 'gms_shortcode' ) );
    3219        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
    3320        add_action( 'wp_ajax_get_gms_table', array( $this, 'ajax_handler' ) );
    3421        add_action( 'wp_ajax_nopriv_get_gms_table', array( $this, 'ajax_handler' ) );
    35     }
    36 
    37     private function get_comp_list () {
    38         if (is_null($this->team_comps)) $this->team_comps = $this->is_team() ? $this->get_json('compsinfixtures', $this->atts_show['team']) : [];
    39         $comp_count = count($this->team_comps);
    40         $html = '<div'.(($comp_count == 0) ? ' style="display: none" ': '').'><label><span class="gms-nomobile">Competition </span><select name="comp_id"><option value="">- All Competitions -</option>';
    41         foreach ($this->team_comps as $key => $competition) $html .= '<option value="'.$key.'"'.(($this->is_competition() && $this->atts_show['comp_id'] == $key) || ($comp_count == 1) ? ' selected' : '').'>'.esc_html($competition['name']).'</option>';
    42         if ($this->is_competition() && !array_key_exists($this->atts_show['comp_id'], $this->team_comps)) {
    43             $html .= '<option value="'.$this->atts_show['comp_id'].'" selected>Previous Season</option>';
    44         }
    45         $html .= '</select></label></div>';
    46         return $html;
    47     }
    48 
    49     private function get_filter () {
    50         $html = '<div class="gms-filter"><div'.($this->is_team() ? ' style="display: none" ': '').'><label><span class="gms-nomobile">Team </span><select name="team"><option value="">- All Club Teams -</option>';
    51         $teams = $this->get_json('teamsinclub', $this->atts_show['club_id']);
    52         foreach ($teams as $key => $team) $html .= '<option value="'.$key.'"'.(($this->is_team() && $this->atts_show['team'] == $key) ? ' selected' : '').'>'.esc_html($team['teamName']).' ('.esc_html($team['gender']).')</option>';
    53         $html .= '</select></label></div>'.$this->get_comp_list().'<div><label><span class="gms-nomobile">What`s On </span><select name="whatson">';
    54         $whatson = $this->atts_show['whatson'];
    55         $options = ($whatson && !in_array($whatson,[7, 14, 31])) ? ['Days ('.$whatson.')' => $whatson] : [];
    56         $options = array_merge($options, [$this->is_team () ? '- All Match Days -' : '- Next Match Day -' => '', 'Week' => 7, 'Fortnight' => 14, 'Month' => 31]);
    57         foreach ($options as $key => $value) $html .= '<option value="'.$value.'"'.($whatson == $value ? ' selected' : '').'>'.$key.'</option>';
    58         $html .= '</select></label></div><div><fieldset><legend class="gms-nomobile">Show</legend>';
    59         foreach (['league' => 'League', 'results' => 'Results', 'fixtures' => 'Fixtures'] as $key => $value) {
    60             $html .= '<div><label><input type="checkbox" name="show" value="'.$key.'" '.(str_contains($this->atts_show['show'], $key) ? ' checked' : '').'> '.$value.'</label></div>';
    61         }
    62         $html .= '</fieldset></div><button type="button" class="gms-button">Refresh</button></div>';
    63         return $html;
    64     }
    65 
    66     private function get_json($key, $keys=[], $raw=false) {
    67     $keys = (array) $keys; $valid_json = true;
    68         $headers = ['headers' => ['Content-Type' => 'application/json;charset=UTF-8', 'x-functions-key' => $this->settings->gms_api_key]];
    69         $transient_name = 'eh_gms_feed '.$this->api[$key]['transient'];
    70         $gms_api_url = $this->settings->gms_api_url;
    71         foreach ($keys as $index => $value) {
    72             $transient_name .= ' '.$value;
    73             $gms_api_url .= ($this->api[$key]['keys'][$index] ?? '').'/'.$value.'/';
    74         }
    75         $gms_api_url .= $this->api[$key]['suffix'] ?? $key;
    76         $body = get_transient($transient_name);
    77         if ($body === false) {
    78             $response = wp_remote_get($gms_api_url, $headers);
    79             $http_code = wp_remote_retrieve_response_code($response);
    80             if ($http_code == 200) {
    81                 $body = wp_remote_retrieve_body($response);
    82                 if (strlen($transient_name) <= 172) {
    83                     switch ($this->api[$key]['expiry']) {
    84                         case 'static' : $expiry = $this->settings->static_transient_expiry; break;
    85                         case 'weekly' : $expiry = '604800'; break;
    86                         default : $expiry = $this->settings->default_transient_expiry;
    87                     }
    88                     set_transient($transient_name, $body, $expiry);
    89                 }
    90             }
    91             else {
    92                 $valid_json = false;
    93                 if ($http_code) $message = sprintf(esc_html__( 'Failed to get data with HTTP error code = %s', 'eh-gms-feed' ), $http_code);
    94                 else {
    95                     $error_message = is_wp_error($response) ? $response->get_error_message() : 'unknown';
    96                     $message = sprintf(esc_html__( 'Failed to get data with error: %s', 'eh-gms-feed' ), $error_message);
    97                 }
    98             }
    99         }
    100         if ($raw) return $valid_json ? $body : null;
    101         if ($valid_json) {
    102             $data = json_decode($body);
    103             if (json_last_error() === JSON_ERROR_NONE) {
    104                 if (!empty($data)) {
    105                     return($this->{'process_'.$key}($data));
    106                 }
    107                 else {
    108                     $valid_json = false;
    109                     $data_type = $this->api[$key]['suffix'] ?? $key;
    110                     switch ($data_type) {
    111                         case 'table' : $data_type = 'league'; break;
    112                         case 'fixturesandresults' : $data_type = 'results/fixtures'; break;
    113                     }
    114                     $message = sprintf(esc_html__( 'No %s data could be found.', 'eh-gms-feed' ), $data_type);
    115                 }
    116             }
    117             else {
    118                 $valid_json = false;
    119                 $message = esc_html__( 'Failed to decode JSON.', 'eh-gms-feed' );
    120             }
    121         }
    122         if ($this->api[$key]['error_bag']) {
    123             if (isset($this->error_bag)) $this->error_bag->add($this->api[$key]['error_bag'], $message);
    124             return [];
    125         }
    126         else return $this->show_api_error($message);
    127     }
    128 
    129     private function get_link($type, $slug) {
    130         return 'https://englandhockey.co.uk/'.$type.'s/'.$slug;
    131     }
    132 
    133     private function is_competition () {
    134         return !empty($this->atts_show['comp_id']);
    135     }
    136 
    137     private function is_team () {
    138         return !empty($this->atts_show['team']);
    139     }
    140 
    141     private function is_clubwide () {
    142         return !$this->is_team() && !empty($this->atts_show['club_id']);
    143     }
    144 
    145     private function is_sortby_time () {
    146         return $this->atts_show['sort_by'] == 'fixtureTime' || $this->is_reverse_date();
    147     }
    148 
    149     private function is_reverse_date () {
    150         return $this->atts_show['sort_by'] == 'reverseDate';
    151     }
    152 
    153     private function show_api_error ($message) {
    154         return '<p>'.$message.'</p>';
    155     }
    156 
    157     private function filter_whatson ($fixture_date) {
    158         $filter = false;
    159         if (is_numeric($this->atts_show['whatson'])) {
    160             $compare = (clone $fixture_date)->setTime(0,0);
    161             $diff = (new \DateTime())->setTime(0,0)->diff($compare)->format('%a');
    162             if ($diff > $this->atts_show['whatson']) $filter = true;
    163         }
    164         return $filter;
    165     }
    166 
    167     private function is_beforetoday($valid_date) {
    168         return $valid_date < (new \DateTime())->setTime(0,0);
    169     }
    170 
    171     private function is_clubteam ($team) {
    172         if ($team->id == $this->atts_show['team'] || ($this->is_clubwide() && $team->clubId == $this->atts_show['club_id'])) {
    173             if (!$this->club_link) $this->club_link = $this->get_link('club', $team->clubUrlSlug);
    174             if (!$this->team_link) $this->team_link = $this->get_link('team', $team->entityUrlSlug);
    175             return true;
    176         }
    177         return false;
    178     }
    179 
    180     private function show_goals ($events) {
    181         $goals = [];
    182         foreach ($events as $event) if (in_array($event->eventType,['FG','PC','PS'])) $goals[$event->memberId][] = $event;
    183         $showGoals = [];
    184         foreach ($goals as $goalsById) {
    185             $playerName = '';
    186             $playerGoals = [];
    187             foreach ($goalsById as $goal) {
    188                 if (!$playerName) $playerName = $goal->displayName;
    189                 $playerGoals[] = ($goal->minute ? $goal->minute . '&prime; ' : '') . $goal->eventType;
    190             }
    191             $showGoals[] = $playerName . ' (' . implode(', ',$playerGoals) . ')';
    192         }
    193         return implode(', ', $showGoals);
    194     }
    195 
    196     private function show_players($players) {
    197         $showPlayers = '';
    198         $withheld = 0;
    199         foreach ($players as $player) {
    200             if (!($player->consent || isset($player->shirtNumber))) { $withheld += 1; continue; }
    201             $playerEvents = [];
    202             foreach ($player->playerEvents as $event) {
    203                 switch ($event->eventType) {
    204                     case 'GC': $showType = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M1.892 20.5 12 3.959 22.109 20.5z" fill="#0FBD00" stroke="#0DA300"/></svg>'; break;
    205                     case 'YC': $showType = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect x="3.5" y=".5" width="17" height="23" rx="1.5" fill="#FFE500" stroke="#DBCA39"/></svg>'; break;
    206                     case 'RC': $showType = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10.5" fill="#E0251B" stroke="#E0251B"/></svg>'; break;
    207                     default : $showType = '<b>'.$event->eventType.'</b>';
    208                 }
    209                 $playerEvents[] = ($event->minute ? '<b>'.$event->minute . '&prime;&nbsp;</b>' : '') . $showType;
    210             }
    211             switch ($player->otherRoleDescription) {
    212                 case 'Goalkeeper' : $role = ' (GK)'; break;
    213                 case 'Captain' : $role = ' (C)'; break;
    214                 default : $role = '';
    215             }
    216             $showPlayers .= '<li>'.($player->shirtNumber ?? '') . ' ' . $player->displayName . $role . (!empty($playerEvents) ? ('&nbsp;' . implode(',&nbsp;',$playerEvents)) : '') . '</li>';
    217         }
    218         if ($withheld) $showPlayers .= ($withheld > 1) ? '<li>Names Withheld (&times;'.$withheld.')</li>' : '<li>Name Withheld</li>';
    219         return $showPlayers;
    220     }
    221 
    222     private function show_officials($officials) {
    223         $showOfficials = '';
    224         foreach ($officials as $official) {
    225             if ($official->displayName != 'Name Withheld') $showOfficials .= '<li>' . $official->role . ': ' . $official->displayName . '</li>';
    226         }
    227         return $showOfficials;
    228     }
    229 
    230     private function fixture_summary ($fixture, $valid_date, $show_detail=false) {
    231         $html = '';
    232         $fixture_card = [
    233             'Date' => $valid_date->format('d M Y'),
    234             'Time' => $fixture->fixtureTime == '00:00' ? '' : $fixture->fixtureTime,
    235             'Home Team' => $fixture->homeTeam->teamName,
    236             'Score' => '',
    237             'Away Team' => $fixture->awayTeam->teamName,
    238             'Venue' => !empty($fixture->venue) ? ($this->show_detail || $show_detail ? esc_html($fixture->venue) : '<a href="https://www.google.com/maps/search/?api=1&query='.urlencode($fixture->venue).'" target="_blank">'.esc_html($fixture->venue).'</a>') : '',
    239         ];
    240         if ($show_detail) {
    241             $home_goals = $this->show_goals($fixture->homeTeamEvents);
    242             $away_goals = $this->show_goals($fixture->awayTeamEvents);
    243             $address = !empty($fixture->venueDetails->address) ? preg_replace ('#(\w+,)(\w+)#', '$1 $2' , $fixture->venueDetails->address) : null;
    244             if (!($fixture->isResult || $this->is_beforetoday($valid_date))) $this->directions = ['venue' => $fixture->venue ?? '', 'll' => null, 'address' => $address, 'postcode' => $fixture->venueDetails->postCode ?? null];
    245             $address .= !empty($address) ? (!empty($fixture->venueDetails->postCode) ? ', '.$fixture->venueDetails->postCode : '') : '';
    246         }
    247         $score_class = '';
    248         $home_attr = $away_attr = $home_class = $away_class = [];
    249         if ($fixture->isResult && !$fixture->isBye) {
    250             $fixture_card['Score'] = $fixture->homeTeamScore . ' : ' . $fixture->awayTeamScore;
    251             if ($fixture->status == 'Postponed' || ($fixture->homeTeamScore == 'P' && $fixture->awayTeamScore == 'P'));
    252             elseif ($fixture->status == 'Cancelled' || ($fixture->homeTeamScore == 'C' && $fixture->awayTeamScore == 'C'));
    253             elseif ($fixture->homeTeamScore == $fixture->awayTeamScore) $score_class = 'gms-draw';
    254             elseif (($fixture->homeTeam->id == $this->atts_show['team'] || ($this->is_clubwide() && $fixture->homeTeam->clubId == $this->atts_show['club_id'])) && $fixture->homeTeamScore > $fixture->awayTeamScore) $score_class = 'gms-win';
    255             elseif (($fixture->awayTeam->id == $this->atts_show['team'] || ($this->is_clubwide() && $fixture->awayTeam->clubId == $this->atts_show['club_id'])) && $fixture->homeTeamScore < $fixture->awayTeamScore) $score_class = 'gms-win';
    256             else $score_class = 'gms-loss';
    257         }
    258         if ($this->is_clubteam($fixture->homeTeam) && $this->is_clubwide()) {
    259             $home_class[] = 'gms-clubteam';
    260             $home_attr[] = 'data-team="'.($fixture->homeTeam->id).'"';
    261             if ($this->show_gender) $fixture_card['Home Team'] .= ' ('.$fixture->homeTeam->gender.')';
    262         }
    263         if ($this->is_clubteam($fixture->awayTeam) && $this->is_clubwide()) {
    264             $away_class[] = 'gms-clubteam';
    265             $away_attr[] = 'data-team="'.($fixture->awayTeam->id).'"';
    266             if ($this->show_gender) $fixture_card['Away Team'] .= ' ('.$fixture->awayTeam->gender.')';
    267         }
    268         if ($this->show_list) {
    269             $statusDisplay = !in_array($fixture->status, ['Active','Result','Bye']) ? $fixture->status : '';
    270             if ($fixture->isResult && ($fixture->homeTeamShootoutScore > 0 || $fixture->awayTeamShootoutScore > 0)) $statusDisplay = 'Shootout '.$fixture->homeTeamShootoutScore.' - '. $fixture->awayTeamShootoutScore;
    271             $home_attr[] = 'class="'.implode(' ',$home_class).'"';
    272             $away_attr[] = 'class="'.implode(' ',$away_class).'"';
    273             if ($fixture->isBye) {
    274                 $divide = '- : -';
    275                 $divide_attr = ' class="gms-carddivide gms-cardnoscore"';
    276             }
    277             elseif ($fixture->isResult) {
    278                 $divide = $fixture_card['Score'];
    279                 $divide_attr = ' class="gms-carddivide '.($score_class ?: 'gms-cardnoscore').'"';
    280             }
    281             else {
    282                 $divide = $fixture_card['Time'] ?: 'TBC';
    283                 $divide_attr = ' class="gms-carddivide gms-cardtime"';
    284             }
    285             $html .= '<div class="gms-card'.($this->show_detail ? ' gms-detaillink' : '').'"'.($this->show_detail ? ' data-fixture="'.$fixture->id.'"': '').'>'
    286                 .($show_detail ? '<div class="gms-cardtitle">Fixture Details</div><div class="gms-cardcomp">'.$fixture->competitionName.'</div>': '')
    287                 .'<div class="gms-carddate">'.$fixture_card['Date'].'</div>'
    288                 .'<div class="gms-cardfixture"><div class="gms-cardhome"><div '.implode(' ',$home_attr).'>'.$fixture_card['Home Team'].'</div></div><div'.$divide_attr.'>'.$divide.'</div><div class="gms-cardaway"><div '.implode(' ',$away_attr).'>'.$fixture_card['Away Team'].'</div></div></div>'
    289                 .(($show_detail && ($home_goals || $away_goals)) ? '<div class="gms-cardscorers"><div class="gms-cardhome"><div>'.$home_goals.'</div></div><div class="gms-carddivide"></div><div class="gms-cardaway"><div>'.$away_goals.'</div></div></div>' : '')
    290                 .($statusDisplay ? '<div class="gms-cardstatus">'.$statusDisplay.'</div>' : '')
    291                 .'<div class="gms-cardvenue">'.($fixture_card['Venue'] ?: 'Venue TBC').'</div>'
    292                 .($show_detail && $address ? '<div class="gms-cardaddress">'.$address.'</div>' : '')
    293                 .'</div>';
    294             if ($show_detail) {
    295                 $participant_details = false;
    296                 $html .= '<div class="gms-fixturedetails">';
    297                 foreach (['home','away'] as $team) {
    298                     $showPlayers = $this->show_players($fixture->{$team . 'Players'});
    299                     $showOfficials = $this->show_officials($fixture->{$team. 'TeamOfficials'});
    300                     if ($showPlayers || $showOfficials) {
    301                         $club_logo = $fixture->{$team . 'Team'}->clubLogoUrl ?? null;
    302                         $participant_details = true;
    303                         $html .= '<div>';
    304                         if ($showPlayers) $html .= '<div class="gms-players">'.($club_logo ? '<img src="'.$club_logo.'" onerror="this.style.display=\'none\'"></img>' : '').'<b>'.$fixture->{$team.'Team'}->teamName.'</b><ul>'.$showPlayers.'</ul></div>';
    305                         if ($showOfficials) $html .= '<div class="gms-officials">'.($showPlayers ? '<br/>' : '').'<b>Coaching Roles</b><ul>'.$showOfficials.'</ul></div>';
    306                         $html .= '</div>';
    307                     }
    308                 }
    309                 $showOfficials = $this->show_officials($fixture->officials);
    310                 if ($showOfficials) {
    311                     $participant_details = true;
    312                     $html .= '<div class="gms-officials"><b>Match Officials</b><ul>'.$showOfficials.'</ul></div>';
    313                 }
    314                 if (!$participant_details) $html .= '<div><b>No more details available</b></div>';
    315                 $html .= '</div>';
    316             }
    317         }
    318         else {
    319             $home_attr[] = 'class="'.implode(' ',$home_class).'"';
    320             $away_attr[] = 'class="'.implode(' ',$away_class).'"';
    321             $html .= $this->show_detail ? '<tr class="gms-detaillink" data-fixture="'.$fixture->id.'">': '<tr>';
    322             foreach ($this->fixture_data as $column_title => $field_name) {
    323                 $value = $fixture_card[$column_title];
    324                 switch ($column_title) {
    325                     case 'Home Team' : $attr = implode(' ',$home_attr); break;
    326                     case 'Away Team' : $attr = implode(' ',$away_attr); break;
    327                     case 'Score' : $attr = 'class="'.$score_class.'"';  break;
    328                     default : $attr = '';
    329                 }
    330                 $html .= '<td '.$attr.'>'.($column_title != 'Venue' ? esc_html($value) : $value).'</td>';
    331             }
    332             $html .= '</tr>';
    333         }
    334         return $html;
    335     }
    336 
    337     private function process_matches ($fixtures) {
    338         $html = '';
    339         foreach ($fixtures as $fixture) {
    340             $valid_date = new \DateTime($fixture->fixtureDate);
    341             if ($fixture->isBye) continue;
    342             if ($this->table_name == 'fixtures') {
    343                 if ($fixture->isResult || $this->is_beforetoday($valid_date)) continue;
    344             }
    345             elseif ($this->table_name == 'results') {
    346                 if (!$fixture->isResult && !$this->is_beforetoday($valid_date)) continue;
    347             }
    348             if ($this->filter_whatson($valid_date)) continue;
    349             $this->filter_match = true;
    350             $html .= $this->fixture_summary($fixture, $valid_date);
    351         }
    352         return $html;
    353     }
    354 
    355     private function process_competition ($data) {
    356         if (!$this->comp_link) $this->comp_link = $this->get_link('competition', $data->entityUrlSlug);
    357         $this->comp_name = $data->name . ' ('.$data->seasonName.')';
    358         if (empty($data->table)) return $this->get_json('table', $this->atts_show['comp_id']);
    359         return $this->process_table($data->table);
    360     }
    361 
    362     private function process_table ($data, $custom=false) {
    363         $html = ''; $link = $this->comp_link;
    364         $league_data = ['Team' => 'teamName', 'Played' => 'gamesPlayed', 'Won' => 'gamesWon', 'Drawn' => 'gamesDrawn', 'Lost' => 'gamesLost', 'For' => 'goalsFor', 'Against' => 'goalsAgainst', 'GD' => 'goalsDifference', 'Points' => 'totalPoints'];
    365         if ($custom) { $league_data['PPG'] = 'PPG'; $league_data['Form'] = 'form'; }
    366         $html .= '<table class="gms-table gms-table-'.$this->display_name.($custom ? ' gms-table-custom' : '').'"><thead><tr><th></th>';
    367         foreach ($league_data as $column_title => $field_name) $html .= '<th>'.$column_title.'</th>';
    368         $html .= '</tr></thead><tbody>';
    369         foreach ($data as $position => $team) {
    370             $class = '';
    371             if (!$custom && $team->teamId == $this->atts_show['team']) {
    372                 $class = ' class="gms-clubteam"';
    373                 if (!$link) $link = $this->get_link('team', $team->teamEntityUrlSlug);
    374             }
    375             $html .= '<tr'.$class.'><td>'.($position+1).'</td>';
    376             foreach ($league_data as $field_name) {
    377                 if ($field_name == 'form') {
    378                     if (count($team->form) > 5) $team->form = array_slice($team->form, -5, 5);
    379                     $team->form = implode(' ', $team->form);
    380                     $html .= '<td>'.$team->form.'</td>';
    381                 }
    382                 else $html .= '<td>'.(isset($field_name, $team->{$field_name}) ? esc_html($team->{$field_name}) : '').'</td>';
    383             }
    384             $html .= '</tr>';
    385         }
    386         if (empty($data)) $html .= '<tr><td colspan="'.(count($league_data)+1).'">No data for teams found</td></tr>';
    387         $html .= '</tbody></table>';
    388         $html .= '<div class="gms-footnote">'.($link ? sprintf(esc_html__( '[%5$s%3$s %1$s also found at%4$s %2$s]', 'eh-gms-feed' ), $this->comp_name ? 'for '.$this->comp_name : '', '<a href="'.$link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>', ($custom ? esc_html__('Data') : esc_html__('Table'))) : ($custom ? esc_html__('[League table for selected teams]') : '')).'</div>';
    389         return $html;
    390     }
    391    
    392     private function process_fixturesandresults($data) {
    393         $html = '';
    394         foreach ($data as $competition) {
    395             $this->team_comps[$competition->competitionId] = ['name' => $competition->competitionName];
    396             if ($this->is_competition() && $competition->competitionId != $this->atts_show['comp_id']) continue;
    397             $this->filter_match = false;
    398             if ($this->show_list) $html .= '<div class="gms-list">';
    399             else {
    400                 $html .= '<table class="gms-table gms-table-'.$this->display_name.'"><thead><tr>';
    401                 foreach ($this->fixture_data as $column_title => $field_name) $html .= '<th>'.$column_title.'</th>';
    402                 $html .= '</tr></thead><tbody>';
    403             }
    404             if ($this->is_reverse_date()) {
    405                 usort($competition->fixtures, function ($a,$b) {
    406                     return strcmp($b->fixtureDate, $a->fixtureDate);
    407                 });
    408             }
    409             $html .= $this->process_matches($competition->fixtures);
    410             if ($this->show_list) {
    411                 if (!$this->filter_match) $html .= '<div>No fixtures found</div>';
    412                 $html .= '</div>';
    413             }
    414             else {
    415                 if (!$this->filter_match) $html .= '<tr><td colspan="'.count($this->fixture_data).'">No fixtures found</td></tr>';
    416                 $html .= '</tbody></table>';
    417             }
    418             $html .= '<div class="gms-footnote">'.($this->team_link ? sprintf(esc_html__( '[Team %1$s%4$s for %2$s also found at%5$s %3$s]', 'eh-gms-feed'), 'fixtures', $competition->competitionName, '<a href="'.$this->team_link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>') : '').'</div>';
    419         }
    420         return $html ?: '<p>'.sprintf(esc_html__( 'No %s were found that matched the criteria.', 'eh-gms-feed' ), 'fixtures').'</p>';
    421     }
    422 
    423     private function process_matchday($data) {
    424         $html = '';
    425         if ($this->is_sortby_time()) { $sort = true; $sorted_fixtures = []; }
    426         else $sort = false;
    427         foreach ($data as $competition) {
    428             if ($sort) $sorted_fixtures = array_merge($sorted_fixtures, $competition->fixtures);
    429             else $html .= $this->process_matches($competition->fixtures);
    430         }
    431         if ($sort) {
    432             usort($sorted_fixtures, function ($a,$b) {
    433                 return strcmp($a->fixtureTime, $b->fixtureTime);
    434             });
    435             $html .= $this->process_matches($sorted_fixtures);
    436         }
    437         return $html;
    438     }
    439 
    440     private function process_matchdays($data) {
    441         $html = '';
    442         if (!empty($data->matchDays)) {
    443             $this->filter_match = false;
    444             if ($this->show_list) $html .= '<div class="gms-list">';
    445             else {
    446                 $html .= '<table class="gms-table gms-table-'.$this->display_name.'"><thead><tr>';
    447                 foreach ($this->fixture_data as $column_title => $field_name) $html .= '<th>'.$column_title.'</th>';
    448                 $html .= '</tr></thead><tbody>';
    449             }
    450             foreach (($this->is_reverse_date() ? array_reverse($data->matchDays) : $data->matchDays) as $matches) {
    451                 $valid_date = new \DateTime($matches->matchDay);
    452                 if ($this->table_name == 'fixtures' && $this->is_beforetoday($valid_date)) continue;
    453                 if ($this->filter_whatson($valid_date)) continue;
    454                 if (is_numeric($this->atts_show['whatson']) && $matches->matchDay != $data->nextMatchDay && !isset($matches->competitions)) {
    455                     $html .= $this->get_json('matchday', [$this->atts_show['club_id'], $matches->id]);
    456                 }
    457                 else {
    458                     if (!empty($matches->competitions)) $html .= $this->process_matchday($matches->competitions);
    459                 }
    460             }
    461             if ($this->show_list) {
    462                 if (!$this->filter_match) $html .= '<div>No fixtures found</div>';
    463                 $html .= '</div>';
    464             }
    465             else {
    466                 if (!$this->filter_match) $html .= '<tr><td colspan="'.count($this->fixture_data).'">No fixtures found</td></tr>';
    467                 $html .= '</tbody></table>';
    468             }
    469             $html .= '<div class="gms-footnote">'.($this->club_link ? sprintf(esc_html__( '[Club%3$s match day %1$s also found at%4$s %2$s]', 'eh-gms-feed' ), 'fixtures', '<a href="'.$this->club_link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>') : '').'</div>';
    470         }
    471         return $html;
    472     }
    473 
    474     private function process_teamslist($data) {
    475         $this->filter_match = false;
    476         $colspan = $this->show_cal ? 3 : 2;
    477         $cal_options = $this->cal_summary ? '&options=summary:'.$this->cal_summary : '';
    478         $html =  $this->show_cal ? '<p>If your calendar app supports subscribing to internet calendars (the WebCal protocol), then click on Copy WebCal for link to paste into your calendar app. For more help and advanced options please goto <a href="https://gmsfeed.co.uk/webcal?club_id='.$this->atts_show['club_id'].'" target="_blank">GMS Feed WebCal</a>.</p><p><span style="word-break: break-all" id="gms-webcal-link"><i>Click on Copy WebCal to select and copy link</i></span></p>' : '';
    479         $html .= '<table class="gms-table gms-table-'.$this->display_name.'"><thead><tr><th>England Hockey Link</th><th>Gender</th>'.($this->show_cal ? '<th>Fixtures Calendar</th>' : '').'</tr></thead><tbody>';
    480         foreach ($data as $team) {
    481             $this->filter_match = true;
    482             $calid = 'gms_webcal_'.$team->id;
    483             $webcal = $this->show_cal ? '<td><button type="button" class="gms-button gms-copy" data-copy_id="gms-webcal-link" data-copy_text="'.esc_html('webcal://gmsfeed.co.uk/api/calendar?team='.$team->id.$cal_options).'" title="'.esc_html($team->teamName).'">Copy WebCal</button></td>' : '';
    484             $html .= '<tr><td><a href="'.esc_attr($this->get_link('team', $team->entityUrlSlug)).'" target="_blank">'.esc_html($team->teamName).'</a></td><td>'.esc_html($team->gender).'</td>'.$webcal.'</tr>';
    485             if (!$this->club_link) $this->club_link = $this->get_link('club', $team->clubUrlSlug);
    486         }
    487         if (!$this->filter_match) $html .= '<tr><td colspan='.$colspan.'>No teams found</td></tr>';
    488         $html .= '</tbody></table><div class="gms-footnote">'.($this->club_link ? sprintf(esc_html__( '[Club %1$s%3$s also found at%4$s %2$s]', 'eh-gms-feed' ), 'teams', '<a href="'.$this->club_link.'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>') : '').'</div>';
    489         return $html;
    490     }
    491 
    492     private function process_fixture($data) {
    493         $html = '<div class="gms-list">';
    494         $html .= $this->fixture_summary($data, new \DateTime($data->fixtureDate), true);
    495         $html .= '</div>';
    496         $html .= '<div class="gms-footnote">'.sprintf(esc_html__( '[Fixture %2$s also found at%3$s %1$s]', 'eh-gms-feed'), '<a href="'.$this->get_link('fixture', $this->id).'" target="_blank">England Hockey Link</a>', '<span class="gms-nomobile">', '</span>').'</div>';
    497         return $html;
    498     }
    499 
    500     private function get_table() {
    501         $html = '';
    502         $tables = [];
    503         if ($this->atts_show['show'] == 'fixture') $tables[] = 'fixture';
    504         if (str_contains($this->atts_show['show'], 'league')) $tables[] = 'league';
    505         if (str_contains($this->atts_show['show'], 'results')) {
    506             $tables[] = (str_contains($this->atts_show['show'], 'fixtures')) ? 'combined' : 'results';
    507         }
    508         elseif (str_contains($this->atts_show['show'], 'fixtures')) $tables[] = 'fixtures';
    509         if (str_contains($this->atts_show['show'], 'teams')) $tables[] = 'teams';
    510         foreach ($tables as $table_name) {
    511             $this->table_name = $table_name;
    512             $this->display_name = ($table_name == 'combined') ? 'results' : $table_name;
    513             $this->fixture_data = ['Date' => 'fixtureDate', 'Time' => 'fixtureTime', 'Home Team' => ['homeTeam','teamName'], 'Score' => ['homeTeamScore', 'awayTeamScore'], 'Away Team' => ['awayTeam','teamName'], 'Venue' => 'venue'];
    514             if ($table_name == 'fixtures') unset($this->fixture_data['Score']);
    515             if ($table_name == 'league') {
    516                 if ($this->atts_show['link']) $this->comp_link = $this->atts_show['link'];
    517                 if ($this->is_competition()) $html .= $this->get_json('competition', $this->atts_show['comp_id']);
    518                 else $html .= $this->multiple_teams();
    519             }
    520             elseif (($table_name == 'fixtures' || $table_name == 'results' || $table_name == 'combined') && $this->is_team()) {
    521                 if ($this->atts_show['link']) $this->team_link = $this->atts_show['link'];
    522                 $html .= $this->get_json('fixturesandresults', $this->atts_show['team']);
    523             }
    524             elseif (($table_name == 'fixtures' || $table_name == 'results' || $table_name == 'combined') && $this->is_clubwide()) {
    525                 if ($this->atts_show['link']) $this->club_link = $this->atts_show['link'];
    526                 $html .= $this->get_json('matchdays', $this->atts_show['club_id']);
    527             }
    528             elseif ($table_name == 'teams' && $this->is_clubwide()) {
    529                 if ($this->atts_show['link']) $this->club_link = $this->atts_show['link'];
    530                 $html .= $this->get_json('teamslist', $this->atts_show['club_id']);
    531             }
    532             elseif ($table_name == 'fixture' && $this->id) {
    533                 $this->show_list = true;
    534                 $html .= $this->get_json('fixture', $this->id);
    535             }
    536         }
    537         return $html;
    538     }
    539 
    540     private function process_teams ($data) {
    541         $teams = [];
    542         foreach ($data as $team) $teams[$team->id] = ['teamName' => $team->teamName, 'clubId' => $team->clubId, 'clubName' => $team->clubName, 'slug' => $team->entityUrlSlug, 'clubSlug' => $team->clubUrlSlug, 'gender' => $team->gender, 'clubLogoUrl' => $team->clubLogoUrl ?? null];
    543         return $teams;
    544     }
    545 
    546     private function process_teamsinclub ($data) {
    547         return $this->process_teams($data);
    548     }
    549 
    550     private function process_compsinfixtures($data) {
    551         $competitions = [];
    552         // seasonId is available but season (name) is ONLY within fixtures object
    553         foreach ($data as $competition) $competitions[$competition->competitionId] = ['name' => $competition->competitionName, 'slug' => $competition->competitionEntityUrlSlug];
    554         return $competitions;
    555     }
    556 
    557     private function multiple_teams() {
    558         $html = '';
    559         $api = 'fixturesandresults';
    560         $json_data = [];
    561         $required_data = [];
    562         $no_data = 0;
    563         // Try the default data cache first
    564         foreach ($this->multiple_teams as $teamID) {
    565             $body = get_transient('eh_gms_feed '.$this->api[$api]['transient'].' '.$teamID);
    566             if ($body === false) $required_data[] = $teamID;
    567             else $json_data[$teamID] = $body;
    568         }
    569         // If Laravel then use Guzzle and do requests in parallel
    570         if ($this->isLaravel) {
    571             $refreshlist = collect();
    572             foreach ($required_data as $teamID) {
    573                 $object = new \stdClass;
    574                 $object->api = $api;
    575                 $object->api_key = $teamID;
    576                 $refreshlist->push($object);
    577             }
    578             if ($refreshlist->isNotEmpty()) $this->refresh_cache($refreshlist);
    579         }
    580         foreach ($required_data as $teamID) {
    581             $json_data[$teamID] = $this->get_json($api, $teamID, true);
    582         }
    583         if (!empty($json_data)) {
    584             $league = [];
    585             foreach ($json_data as $key => $snapshot) {
    586                 if ($snapshot && ($data = json_decode($snapshot)) && json_last_error() === JSON_ERROR_NONE && !empty($data)) {
    587                     $teamname = $next_fixture_date = null;
    588                     $gp = $gw = $gd = $gl = $gf = $ga = 0;
    589                     $form = [];
    590                     foreach ($data as $competition) {
    591                         foreach ($competition->fixtures as $fixture) {
    592                             $isHome = $fixture->homeTeamId == $key;
    593                             if (!$teamname) $teamname = $isHome ? $fixture->homeTeam->teamName : $fixture->awayTeam->teamName;
    594                             if ($fixture->isBye) continue;
    595                             $valid_date = new \DateTime($fixture->fixtureDate);
    596                             if ($fixture->isResult) {
    597                                 if ($fixture->status == 'Postponed' || ($fixture->homeTeamScore == 'P' && $fixture->awayTeamScore == 'P')) continue;
    598                                 elseif ($fixture->status == 'Cancelled' || ($fixture->homeTeamScore == 'C' && $fixture->awayTeamScore == 'C')) continue;
    599                                 else {
    600                                     $gp++;
    601                                     $gf += $isHome ? $fixture->homeTeamScoreAsInt : $fixture->awayTeamScoreAsInt;
    602                                     $ga += $isHome ? $fixture->awayTeamScoreAsInt : $fixture->homeTeamScoreAsInt;
    603                                     if ($fixture->homeTeamScoreAsInt == $fixture->awayTeamScoreAsInt) { $gd++; $form[] = '<span class="gms-form gms-draw">D</span>'; }
    604                                     else if (($isHome && $fixture->homeTeamScoreAsInt > $fixture->awayTeamScoreAsInt) || (!$isHome && $fixture->homeTeamScoreAsInt < $fixture->awayTeamScoreAsInt)) { $gw++; $form[] = '<span class="gms-form gms-win">W</span>'; }
    605                                     else { $gl++; $form[] = '<span class="gms-form gms-loss">L</span>'; }
    606                                 }
    607                             }
    608                             elseif ($this->is_beforetoday($valid_date)) continue;
    609                             elseif (!$next_fixture_date || $valid_date < $next_fixture_date) $next_fixture_date = $valid_date;
    610                         }
    611                     }
    612                     if ($teamname) {
    613                         $points = $gw * 3 + $gd;
    614                         $object = new \stdClass;
    615                         $object->teamId = $key;
    616                         $object->teamName = $teamname;
    617                         $object->gamesPlayed = $gp;
    618                         $object->gamesWon = $gw;
    619                         $object->gamesDrawn = $gd;
    620                         $object->gamesLost = $gl;
    621                         $object->goalsFor = $gf;
    622                         $object->goalsAgainst = $ga;
    623                         $object->goalsDifference = $gf - $ga;
    624                         $object->totalPoints = $points;
    625                         $object->PPG = number_format($gp ? $points/$gp : 0, 2, '.', '');
    626                         $object->form = $form;
    627                         $league[] = $object;
    628                     }
    629                 }
    630                 else $no_data++;
    631             }
    632             usort($league, function ($a,$b) {
    633                 if ($a->PPG != $b->PPG) return $a->PPG < $b->PPG ? 1 : -1;
    634                 if ($a->goalsDifference != $b->goalsDifference) return $a->goalsDifference < $b->goalsDifference ? 1 : -1;
    635                 if ($a->goalsFor != $b->goalsFor) return $a->goalsFor < $b->goalsFor ? 1 : -1;
    636                 if ($a->gamesWon != $b->gamesWon) return $a->gamesWon < $b->gamesWon ? 1 : -1;
    637                 return 0;
    638             });
    639             $html .= $this->process_table($league, true);
    640             if ($no_data) $html .= $this->show_api_error(sprintf(esc_html__( 'Failed to retrieve data for %s of selected team(s)', 'eh-gms-feed' ), $no_data));
    641         }
    642         else $html .= $this->show_api_error(esc_html__( 'You have selected a custom league table without any teams', 'eh-gms-feed' ));
    643         return $html;
    644     }
    645 
    646     private function ajax_method () {
    647         wp_enqueue_script('EH_GMS_Feed');
    648         $atts = '';
    649         foreach ($this->args as $value) {
    650             if (!empty($this->atts_show[$value])) $atts .= ' data-'.$value.'="'.esc_attr($this->atts_show[$value]).'"';
    651         }
    652         return '<div class="gms-wrapper gms-ajax"'.$atts.'></div>';
     22        parent::__construct();
    65323    }
    65424
     
    71282        }
    71383        foreach (explode('+',$this->atts_show['show']) as $show) {
    714             if (!in_array($show,['fixtures','results','league','teams','fixture'])) {
     84            if (!in_array($show, $this->valid_show)) {
    71585                $message = sprintf(esc_html__( 'Please enter a "show" parameter (%s) equal to "fixtures", "results", "league" or "teams".', 'eh-gms-feed' ), $show ?: 'empty');
    71686                $this->not_valid .= '<p>'.$message.'</p>';
     
    758128    public function gms_shortcode ( $atts = [] ) {
    759129        if ($this->validate_atts($atts)) {
    760             if ($this->settings->default_ajax == 'yes' || $this->atts_show['method'] == 'api-dynamic')
    761                 $html = $this->ajax_method ();
     130            if ($this->settings->default_ajax == 'yes' || $this->atts_show['method'] == 'api-dynamic') {
     131                wp_enqueue_script('EH_GMS_Feed');
     132                $html_atts = '';
     133                foreach ($this->args as $value) {
     134                    if (!empty($this->atts_show[$value])) $html_atts .= ' data-'.$value.'="'.esc_attr($this->atts_show[$value]).'"';
     135                }
     136                $html = '<div class="gms-wrapper gms-ajax"'.$html_atts.'></div>';
     137            }
    762138            elseif ($this->atts_show['method'] == 'api') $html = '<div class="gms-wrapper">'.$this->get_table().'</div>';
    763139            return $html;
     
    767143
    768144    public function enqueue_scripts () {
    769         wp_register_script('EH_GMS_Feed', plugin_dir_url(__DIR__).'js/eh-gms-feed.js', ['jquery'], '3.12', true);
     145        wp_register_script('EH_GMS_Feed', plugin_dir_url(__DIR__).'js/eh-gms-feed.js', ['jquery'], '3.13', true);
    770146        wp_localize_script('EH_GMS_Feed', 'eh_gms_feed_ajax_obj', ['ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce('get_gms_table')]);
    771147        wp_register_style('EH_GMS_Feed', plugin_dir_url(__DIR__).'css/gms-default.css',[],'3.12');
    772148        if ($this->settings->default_css == 'yes') wp_enqueue_style('EH_GMS_Feed');
    773149    }
     150
    774151}
    775152
  • eh-gms-feed/trunk/js/eh-gms-feed.js

    r3064521 r3065987  
    112112                    .always(function() {
    113113                        var goback = jQuery('<button type="button" class="gms-button">Go Back</button>').appendTo(detail);
    114                         back_btns.push = goback[0];
     114                        back_btns.push(goback[0]);
    115115                        back_btns.forEach(function (ele) {
    116116                            ele.addEventListener('click', function() {
  • eh-gms-feed/trunk/readme.txt

    r3064521 r3065987  
    55Tested up to: 6.5
    66Requires PHP: 5.3
    7 Stable tag: 3.12
     7Stable tag: 3.13
    88License: GPLv2
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    6262
    6363== Changelog ==
     64
     65= 3.13 =
     66* Fix fault with back button on fixture detail
     67* Added showGender option to custom league table
    6468
    6569= 3.12 =
Note: See TracChangeset for help on using the changeset viewer.