public function OnPrePageLoad()
    {
        /* @var $match Match */
        #$this->SetContentConstraint(StoolballPage::ConstrainText());
        $this->SetContentCssClass('scorecardPage');
        $this->SetContentCssClass('scorecardPage');
        if ($this->page_not_found) {
            $this->SetPageTitle('Page not found');
            return;
            # Don't load any JS
        }
        # Set page title
        $edit_or_update = ($this->b_user_is_match_admin or $this->b_user_is_match_owner) ? "Edit" : "Update";
        $step = ", step " . $this->editor->GetCurrentPage() . " of 4";
        $this->SetPageTitle("{$edit_or_update} " . $this->match->GetTitle() . ', ' . Date::BritishDate($this->match->GetStartTime()) . $step);
        # Load JavaScript
        $autocomplete_team_ids = array();
        if ($this->match->GetHomeTeamId()) {
            $autocomplete_team_ids[] = $this->match->GetHomeTeamId();
        }
        if ($this->match->GetAwayTeamId()) {
            $autocomplete_team_ids[] = $this->match->GetAwayTeamId();
        }
        if (count($autocomplete_team_ids)) {
            $this->LoadClientScript("/scripts/lib/jquery-ui-1.8.11.custom.min.js");
            $this->LoadClientScript("/play/playersuggest.js.php?v=2&team=" . implode(",", $autocomplete_team_ids));
            // . "&time=" . time());
            ?>
<link rel="stylesheet" type="text/css" href="/css/custom-theme/jquery-ui-1.8.11.custom.css" media="all" />
			<?php 
        }
        $this->LoadClientScript('scorecard.js', true);
    }
 /**
  * Re-build from data posted by this control a single data object which this control is editing
  *
  * @param int $i_counter
  * @param int $i_id
  */
 protected function BuildPostedItem($i_counter = null, $i_id = null)
 {
     $match = new Match($this->GetSettings());
     $match->SetMatchType(MatchType::TOURNAMENT_MATCH);
     $key = $this->GetNamingPrefix() . 'MatchId' . $i_counter;
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         $match->SetId($_POST[$key]);
     }
     $key = $this->GetNamingPrefix() . 'MatchOrder' . $i_counter;
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         $match->SetOrderInTournament($_POST[$key]);
     }
     $key = $this->GetNamingPrefix() . 'MatchIdValue' . $i_counter;
     if (isset($_POST[$key])) {
         $match->SetTitle($_POST[$key]);
     }
     $key = $this->GetNamingPrefix() . 'HomeTeamId' . $i_counter;
     if (isset($_POST[$key]) and $_POST[$key]) {
         $team = new Team($this->GetSettings());
         $team->SetId($_POST[$key]);
         $match->SetHomeTeam($team);
     }
     $key = $this->GetNamingPrefix() . 'AwayTeamId' . $i_counter;
     if (isset($_POST[$key]) and $_POST[$key]) {
         $team = new Team($this->GetSettings());
         $team->SetId($_POST[$key]);
         $match->SetAwayTeam($team);
     }
     if ($match->GetId() or $match->GetHomeTeamId() and $match->GetAwayTeamId()) {
         $this->DataObjects()->Add($match);
     } else {
         $this->IgnorePostedItem($i_counter);
     }
 }
 /**
  * Sets up controls for page 4 of the wizard
  * @param Match $match
  * @return void
  */
 private function CreateHighlightsControls(Match $match)
 {
     $b_got_teams = !(is_null($match->GetHomeTeam()) || is_null($match->GetAwayTeam()));
     // Move CSS class to div element
     $match_outer_1 = new XhtmlElement('div');
     $match_outer_1->SetCssClass('matchResultEdit panel');
     $match_outer_2 = new XhtmlElement('div');
     $match_box = new XhtmlElement('div');
     $this->AddControl($match_outer_1);
     $match_outer_1->AddControl($match_outer_2);
     $match_outer_2->AddControl($match_box);
     $o_title_inner_1 = new XhtmlElement('span', "Match highlights");
     $o_title_inner_2 = new XhtmlElement('span', $o_title_inner_1);
     $o_title_inner_3 = new XhtmlElement('span', $o_title_inner_2);
     $o_heading = new XhtmlElement('h2', $o_title_inner_3);
     $match_box->AddControl($o_heading);
     # Who's playing?
     $o_home_name = new TextBox($this->GetNamingPrefix() . 'Home');
     $o_away_name = new TextBox($this->GetNamingPrefix() . 'Away');
     $o_home_name->SetMode(TextBoxMode::Hidden());
     $o_away_name->SetMode(TextBoxMode::Hidden());
     if (!is_null($match->GetHomeTeam())) {
         $o_home_name->SetText($match->GetHomeTeam()->GetId() . MatchHighlightsEditControl::DATA_SEPARATOR . $match->GetHomeTeam()->GetName());
     }
     if (!is_null($match->GetAwayTeam())) {
         $o_away_name->SetText($match->GetAwayTeam()->GetId() . MatchHighlightsEditControl::DATA_SEPARATOR . $match->GetAwayTeam()->GetName());
     }
     $this->AddControl($o_home_name);
     $this->AddControl($o_away_name);
     # When? (for validator message only)
     $when = new TextBox($this->GetNamingPrefix() . 'Date', $match->GetStartTime());
     $when->SetMode(TextBoxMode::Hidden());
     $this->AddControl($when);
     # Who won?
     $o_winner = new XhtmlSelect($this->GetNamingPrefix() . 'Result');
     $o_winner->AddControl(new XhtmlOption("Don't know", ''));
     $result_types = array(MatchResult::HOME_WIN, MatchResult::AWAY_WIN, MatchResult::TIE, MatchResult::ABANDONED);
     foreach ($result_types as $result_type) {
         if ($b_got_teams) {
             $o_winner->AddControl(new XhtmlOption($this->NameTeams(MatchResult::Text($result_type), $match->GetHomeTeam(), $match->GetAwayTeam()), $result_type));
         } else {
             $o_winner->AddControl(new XhtmlOption(MatchResult::Text($result_type), $result_type));
         }
     }
     if ($this->IsValidSubmit()) {
         if ($match->Result()->GetResultType() == MatchResult::UNKNOWN and !is_null($match->Result()->GetHomeRuns()) and !is_null($match->Result()->GetAwayRuns())) {
             # If match result is not known but we can guess from the entered scores, select it
             if ($match->Result()->GetHomeRuns() > $match->Result()->GetAwayRuns()) {
                 $o_winner->SelectOption(MatchResult::HOME_WIN);
             } else {
                 if ($match->Result()->GetHomeRuns() < $match->Result()->GetAwayRuns()) {
                     $o_winner->SelectOption(MatchResult::AWAY_WIN);
                 } else {
                     if ($match->Result()->GetHomeRuns() == $match->Result()->GetAwayRuns()) {
                         $o_winner->SelectOption(MatchResult::TIE);
                     }
                 }
             }
         } else {
             $o_winner->SelectOption($match->Result()->GetResultType());
         }
     }
     $o_win_part = new FormPart('Who won?', $o_winner);
     $match_box->AddControl($o_win_part);
     # Get current player of match
     $player = $match->Result()->GetPlayerOfTheMatch();
     $home_player = $match->Result()->GetPlayerOfTheMatchHome();
     $away_player = $match->Result()->GetPlayerOfTheMatchAway();
     $current_pom = MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_NONE;
     if ($player instanceof Player) {
         $current_pom = MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_OVERALL;
     } else {
         if ($home_player instanceof Player or $away_player instanceof Player) {
             $current_pom = MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_HOME_AND_AWAY;
         }
     }
     # Choose from different types of player of the match
     require_once 'xhtml/forms/radio-button.class.php';
     $pom_container = new XhtmlElement('fieldset', new XhtmlElement('legend', 'Player of the match', 'formLabel'));
     $pom_container->SetCssClass('formPart');
     $pom_options = new XhtmlElement('div', null, 'formControl radioButtonList');
     $pom_options->SetXhtmlId($this->GetNamingPrefix() . "PlayerOptions");
     $pom_container->AddControl($pom_options);
     $match_box->AddControl($pom_container);
     $pom_options->AddControl(new RadioButton($this->GetNamingPrefix() . 'POM' . MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_NONE, $this->GetNamingPrefix() . 'POM', "none chosen", MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_NONE, $current_pom == MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_NONE, $this->IsValidSubmit()));
     $pom_options->AddControl(new RadioButton($this->GetNamingPrefix() . 'POM' . MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_OVERALL, $this->GetNamingPrefix() . 'POM', "yes, one chosen", MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_OVERALL, $current_pom == MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_OVERALL, $this->IsValidSubmit()));
     $pom_options->AddControl(new RadioButton($this->GetNamingPrefix() . 'POM' . MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_HOME_AND_AWAY, $this->GetNamingPrefix() . 'POM', "yes, one from each team", MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_HOME_AND_AWAY, $current_pom == MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_HOME_AND_AWAY, $this->IsValidSubmit()));
     # Controls for entering a single player of the match
     $player_name = new TextBox($this->GetNamingPrefix() . 'Player', $player instanceof Player ? $player->GetName() : '', $this->IsValidSubmit());
     $player_name->SetMaxLength(100);
     $player_name->AddCssClass("player");
     $player_name->AddCssClass("team" . $match->GetHomeTeamId());
     $player_name->AddCssClass("team" . $match->GetAwayTeamId());
     $player_name->AddAttribute("autocomplete", "off");
     $player_box = new XhtmlElement("div", $player_name);
     $player_team = new XhtmlSelect($this->GetNamingPrefix() . "PlayerTeam", " playing for", $this->IsValidSubmit());
     $player_team->SetCssClass("playerTeam");
     # for JS
     $player_team->AddControl(new XhtmlOption("Don't know", ""));
     $player_team->AddControl(new XhtmlOption($match->GetHomeTeam()->GetName(), $match->GetHomeTeamId()));
     $player_team->AddControl(new XhtmlOption($match->GetAwayTeam()->GetName(), $match->GetAwayTeamId()));
     if ($player instanceof Player) {
         $player_team->SelectOption($player->Team()->GetId());
     }
     $player_box->AddControl($player_team);
     $player_part = new FormPart("Player's name", $player_box);
     $player_part->SetXhtmlId($this->GetNamingPrefix() . "OnePlayer");
     $player_part->GetLabel()->AddAttribute("for", $player_name->GetXhtmlId());
     $match_box->AddControl($player_part);
     # Controls for entering home and away players of the match
     $home_box = new TextBox($this->GetNamingPrefix() . 'PlayerHome', $home_player instanceof Player ? $home_player->GetName() : '', $this->IsValidSubmit());
     $home_box->SetMaxLength(100);
     $home_box->AddCssClass("player");
     $home_box->AddCssClass("team" . $match->GetHomeTeamId());
     $home_box->AddAttribute("autocomplete", "off");
     $home_part = new FormPart($this->NameTeams('Home player', $match->GetHomeTeam(), $match->GetAwayTeam()), $home_box);
     $home_part->SetCssClass("formPart multiPlayer");
     $match_box->AddControl($home_part);
     $away_box = new TextBox($this->GetNamingPrefix() . 'PlayerAway', $away_player instanceof Player ? $away_player->GetName() : '', $this->IsValidSubmit());
     $away_box->SetMaxLength(100);
     $away_box->AddCssClass("player");
     $away_box->AddCssClass("team" . $match->GetAwayTeamId());
     $away_box->AddAttribute("autocomplete", "off");
     $away_part = new FormPart($this->NameTeams('Away player', $match->GetHomeTeam(), $match->GetAwayTeam()), $away_box);
     $away_part->SetCssClass("formPart multiPlayer");
     $match_box->AddControl($away_part);
     # Any comments?
     $comments = new TextBox($this->GetNamingPrefix() . 'Comments', '', $this->IsValidSubmit());
     $comments->SetMode(TextBoxMode::MultiLine());
     $comments->AddAttribute('class', 'matchReport');
     $comments_label = new XhtmlElement('label');
     $comments_label->AddAttribute('for', $comments->GetXhtmlId());
     $comments_label->AddCssClass('matchReport');
     $comments_label->AddControl('Add a match report:');
     $match_box->AddControl($comments_label);
     $match_box->AddControl($comments);
     if ($match->GetLastAudit() != null) {
         require_once "data/audit-control.class.php";
         $match_box->AddControl(new AuditControl($match->GetLastAudit(), "match"));
     }
     $this->SetButtonText('Save match');
 }
 /**
  * @return void
  * @param Match $match
  * @param bool $is_first_innings
  * @desc Saves the batting and bowling scorecards for one innings
  */
 public function SaveScorecard(Match $match, $is_first_innings, ISearchIndexProvider $search)
 {
     # To add a scorecard there must always already be a match to update
     if (!$match->GetId()) {
         return;
     }
     # This isn't for tournaments
     if ($match->GetMatchType() == MatchType::TOURNAMENT) {
         return;
     }
     # Get tables
     $batting_table = $this->GetSettings()->GetTable("Batting");
     $bowling_table = $this->GetSettings()->GetTable("Bowling");
     $match_table = $this->GetSettings()->GetTable('Match');
     $mt = $this->GetSettings()->GetTable('MatchTeam');
     # Is this scorecard for the home or the away innings?
     $sql = "SELECT home_bat_first FROM {$match_table} WHERE match_id = " . Sql::ProtectNumeric($match->GetId());
     $result = $this->GetDataConnection()->query($sql);
     $row = $result->fetch();
     if (is_null($row->home_bat_first) or (bool) $row->home_bat_first === true) {
         $is_home_innings = $is_first_innings;
     } else {
         $is_home_innings = !$is_first_innings;
     }
     $result->closeCursor();
     # Prepare data for query
     if ($is_home_innings) {
         $bowling_team_id = $match->GetAwayTeamId();
         $batting_team_id = $match->GetHomeTeamId();
         $team_bowling = $match->Result()->AwayOvers();
         $team_batting = $match->Result()->HomeBatting();
     } else {
         $bowling_team_id = $match->GetHomeTeamId();
         $batting_team_id = $match->GetAwayTeamId();
         $team_bowling = $match->Result()->HomeOvers();
         $team_batting = $match->Result()->AwayBatting();
     }
     # Find the match_team_id for the bowling
     $sql = "SELECT match_team_id FROM {$mt}\r\n\t\t\t\tWHERE match_id " . Sql::ProtectNumeric($match->GetId(), false, true) . "\r\n\t\t\t\tAND team_id " . Sql::ProtectNumeric($bowling_team_id, false, true) . "\r\n\t\t\t\tAND team_role = " . ($is_home_innings ? TeamRole::Away() : TeamRole::Home());
     $result = $this->GetDataConnection()->query($sql);
     $row = $result->fetch();
     $bowling_match_team_id = $row->match_team_id;
     $result->closeCursor();
     # Find the match_team_id for the batting
     $sql = "SELECT match_team_id FROM {$mt}\r\n\t\t\t\tWHERE match_id " . Sql::ProtectNumeric($match->GetId(), false, true) . "\r\n\t\t\t\tAND team_id " . Sql::ProtectNumeric($batting_team_id, false, true) . "\r\n\t\t\t\tAND team_role = " . ($is_home_innings ? TeamRole::Home() : TeamRole::Away());
     $result = $this->GetDataConnection()->query($sql);
     $row = $result->fetch();
     $batting_match_team_id = $row->match_team_id;
     $result->closeCursor();
     $affected_players = $this->SaveBattingScorecard($match, $is_home_innings, $batting_match_team_id, $team_batting);
     $affected_bowlers = $this->SaveBowlingScorecard($match, $is_home_innings, $batting_match_team_id, $bowling_match_team_id, $team_bowling);
     $affected_players = array_merge($affected_players, $affected_bowlers);
     $affected_players = array_unique($affected_players);
     if (count($affected_players)) {
         require_once 'stoolball/statistics/statistics-manager.class.php';
         $statistics_manager = new StatisticsManager($this->GetSettings(), $this->GetDataConnection());
         # generate player statistics from the data entered
         $statistics_manager->UpdateBattingStatistics($affected_players, array($batting_match_team_id));
         $statistics_manager->UpdateFieldingStatistics($affected_players, array($bowling_match_team_id));
         $statistics_manager->UpdateBowlingStatistics($affected_players, array($bowling_match_team_id));
         $statistics_manager->DeleteObsoleteStatistics($match->GetId());
         # update overall stats for players
         $statistics_manager->UpdatePlayerStatistics($affected_players);
         unset($statistics_manager);
         # update search engine
         require_once "stoolball/player-manager.class.php";
         require_once "search/player-search-adapter.class.php";
         $player_manager = new PlayerManager($this->GetSettings(), $this->GetDataConnection());
         foreach ($affected_players as $player_id) {
             $player_manager->ReadPlayerById($player_id);
             $player = $player_manager->GetFirst();
             $search->DeleteFromIndexById("player" . $player_id);
             if ($player instanceof Player) {
                 $adapter = new PlayerSearchAdapter($player);
                 $search->Index($adapter->GetSearchableItem());
             }
         }
         $search->CommitChanges();
         unset($player_manager);
     }
 }
 public function OnPostback()
 {
     # If there's no id, ensure no match object is created. Page will then display a "match not found" message.
     # There's a separate page for adding matches, even for admins.
     if (!$this->editor->GetDataObjectId()) {
         return;
     }
     # Get the submitted match
     $this->match = $this->editor->GetDataObject();
     $check_match = $this->match;
     # Because this is a new request, if the user isn't admin we need to reverify whether this is the match owner
     # before letting anything happen. Can't trust that info from a postback so MUST go to the database to check it.
     if (!$this->b_user_is_match_admin) {
         $this->match_manager->ReadByMatchId(array($this->editor->GetDataObjectId()));
         $check_match = $this->match_manager->GetFirst();
         $this->b_user_is_match_owner = ($check_match instanceof Match and AuthenticationManager::GetUser()->GetId() == $check_match->GetAddedBy()->GetId());
         if ($this->b_user_is_match_owner) {
             # Set the owner of the match. This means the edit control knows who the owner is and therefore
             # whether to display the fixture editor on an invalid postback
             $this->match->SetAddedBy(AuthenticationManager::GetUser());
         } else {
             # If user is neither admin nor owner, they won't have the team info. Get it from the $check_match so
             # that the match title can be updated correctly with a changed result.
             $this->match->SetHomeTeam($check_match->GetHomeTeam());
             $this->match->SetAwayTeam($check_match->GetAwayTeam());
         }
     }
     # Don't wan't to edit tournaments on this page, so even as admin make sure we're not trying to save one.
     # If user's not admin, can't change the match type, so find out what that is from the db too. For admin,
     # $check_match is the submitted one as the match type might've been changed.
     $this->b_is_tournament = $check_match->GetMatchType() == MatchType::TOURNAMENT;
     # Check whether cancel was clicked
     if ($this->editor->CancelClicked()) {
         # If so, get the match's short URL and redirect
         $this->match_manager->ExpandMatchUrl($this->match);
         $this->Redirect($this->match->GetNavigateUrl());
     }
     # save data if valid
     if ($this->IsValid() and !$this->b_is_tournament) {
         # Check whether the user has permission to update the fixture as well as the result
         if ($this->b_user_is_match_admin or $this->b_user_is_match_owner) {
             # Get the ground name from the database. This is used when compiling an email about the updated match result.
             if ($this->match->GetGround() instanceof Ground and $this->match->GetGround()->GetId() and !$this->match->GetGround()->GetName()) {
                 require_once 'stoolball/ground-manager.class.php';
                 $ground_manager = new GroundManager($this->GetSettings(), $this->GetDataConnection());
                 $ground_manager->ReadById(array($this->match->GetGround()->GetId()));
                 if ($ground_manager->GetCount()) {
                     $this->match->SetGround($ground_manager->GetFirst());
                 }
                 unset($ground_manager);
             }
             $this->match_manager->SaveFixture($this->match);
             if ($this->b_user_is_match_admin) {
                 $this->match_manager->SaveSeasons($this->match, false);
             }
             $this->editor->SetNavigateUrl($this->match->GetEditNavigateUrl());
             # because edit URL may have changed
         }
         # Save the result
         $this->match_manager->SaveIfPlayed($this->match);
         $this->match_manager->SaveWhoWonTheToss($this->match);
         $this->match_manager->SaveWhoBattedFirst($this->match);
         # If match didn't happen or the teams aren't known yet, save and finish, otherwise go to next page
         $result = $this->match->Result()->GetResultType();
         if ($result == MatchResult::HOME_WIN_BY_FORFEIT or $result == MatchResult::AWAY_WIN_BY_FORFEIT or $result == MatchResult::CANCELLED or $result == MatchResult::POSTPONED or $check_match->GetStartTime() > gmdate('U') or $this->b_user_is_match_admin and (!$this->match->GetHomeTeamId() or !$this->match->GetAwayTeamId())) {
             # Match may have been updated so, first, send an email
             $this->match_manager->NotifyMatchModerator($this->match->GetId());
             http_response_code(303);
             $this->Redirect($this->match->GetNavigateUrl());
         } else {
             http_response_code(303);
             $this->Redirect($this->match->EditScorecardUrl());
         }
     }
 }
 protected function CreateControls()
 {
     $o_match = $this->GetDataObject();
     if (is_null($o_match)) {
         $o_match = new Match($this->GetSettings());
     }
     /* @var $o_match Match */
     /* @var $o_team Team */
     $b_got_home = !is_null($o_match->GetHomeTeam());
     $b_got_away = !is_null($o_match->GetAwayTeam());
     $b_is_new_match = !(bool) $o_match->GetId();
     $b_is_tournament_match = false;
     if ($this->i_match_type == MatchType::TOURNAMENT_MATCH) {
         $b_is_tournament_match = $this->tournament instanceof Match;
     } else {
         if ($o_match->GetMatchType() == MatchType::TOURNAMENT_MATCH and $o_match->GetTournament() instanceof Match) {
             $this->SetTournament($o_match->GetTournament());
             $this->SetMatchType($o_match->GetMatchType());
             $b_is_tournament_match = true;
         }
     }
     $o_match_outer_1 = new XhtmlElement('div');
     $o_match_outer_1->SetCssClass('MatchFixtureEdit');
     $o_match_outer_1->AddCssClass($this->GetCssClass());
     $this->SetCssClass('');
     $o_match_outer_1->SetXhtmlId($this->GetNamingPrefix());
     $o_match_outer_2 = new XhtmlElement('div');
     $o_match_box = new XhtmlElement('div');
     $this->AddControl($o_match_outer_1);
     $o_match_outer_1->AddControl($o_match_outer_2);
     $o_match_outer_2->AddControl($o_match_box);
     if ($this->GetShowHeading()) {
         $s_heading = str_replace('{0}', MatchType::Text($this->i_match_type), $this->GetHeading());
         # Add match type if required
         $o_title_inner_1 = new XhtmlElement('span', htmlentities($s_heading, ENT_QUOTES, "UTF-8", false));
         $o_title_inner_2 = new XhtmlElement('span', $o_title_inner_1);
         $o_title_inner_3 = new XhtmlElement('span', $o_title_inner_2);
         $o_match_box->AddControl(new XhtmlElement('h2', $o_title_inner_3, "medium large"));
     }
     # Offer choice of season if appropriate
     $season_count = $this->seasons->GetCount();
     if ($season_count == 1 and $this->i_match_type != MatchType::PRACTICE) {
         $o_season_id = new TextBox($this->GetNamingPrefix() . 'Season', $this->seasons->GetFirst()->GetId());
         $o_season_id->SetMode(TextBoxMode::Hidden());
         $o_match_box->AddControl($o_season_id);
     } elseif ($season_count > 1 and $this->i_match_type != MatchType::PRACTICE) {
         $o_season_id = new XhtmlSelect($this->GetNamingPrefix() . 'Season', '', $this->IsValidSubmit());
         foreach ($this->Seasons()->GetItems() as $season) {
             $o_season_id->AddControl(new XhtmlOption($season->GetCompetitionName(), $season->GetId()));
         }
         $o_match_box->AddControl(new FormPart('Competition', $o_season_id));
     }
     # Start date and time
     $match_time_known = (bool) $o_match->GetStartTime();
     if (!$match_time_known) {
         # if no date set, use specified default
         if ($this->i_default_time) {
             $o_match->SetStartTime($this->i_default_time);
             if ($b_is_tournament_match) {
                 $o_match->SetIsStartTimeKnown(false);
             }
         } else {
             # if no date set and no default, default to today at 6.30pm BST
             $i_now = gmdate('U');
             $o_match->SetStartTime(gmmktime(17, 30, 00, (int) gmdate('n', $i_now), (int) gmdate('d', $i_now), (int) gmdate('Y', $i_now)));
         }
     }
     $o_date = new DateControl($this->GetNamingPrefix() . 'Start', $o_match->GetStartTime(), $o_match->GetIsStartTimeKnown(), $this->IsValidSubmit());
     $o_date->SetShowTime(true);
     $o_date->SetRequireTime(false);
     $o_date->SetMinuteInterval(5);
     # if no date set and only one season to choose from, limit available dates to the length of that season
     if (!$match_time_known and $season_count == 1) {
         if ($this->Seasons()->GetFirst()->GetStartYear() == $this->Seasons()->GetFirst()->GetEndYear()) {
             $i_mid_season = gmmktime(0, 0, 0, 6, 30, $this->Seasons()->GetFirst()->GetStartYear());
         } else {
             $i_mid_season = gmmktime(0, 0, 0, 12, 31, $this->Seasons()->GetFirst()->GetStartYear());
         }
         $season_dates = Season::SeasonDates($i_mid_season);
         $season_start_month = gmdate('n', $season_dates[0]);
         $season_end_month = gmdate('n', $season_dates[1]);
         if ($season_start_month) {
             $o_date->SetMonthStart($season_start_month);
         }
         if ($season_end_month) {
             $o_date->SetMonthEnd($season_end_month + 1);
         }
         // TODO: need a better way to handle this, allowing overlap. Shirley has indoor matches until early April.
         $season_start_year = $this->Seasons()->GetFirst()->GetStartYear();
         $season_end_year = $this->Seasons()->GetFirst()->GetEndYear();
         if ($season_start_year) {
             $o_date->SetYearStart($season_start_year);
         }
         if ($season_end_year) {
             $o_date->SetYearEnd($season_end_year);
         }
     }
     if ($b_is_tournament_match) {
         $o_date->SetShowDate(false);
         $o_date->SetShowTime(false);
         $o_match_box->AddControl($o_date);
     } else {
         $o_date_part = new FormPart('When?', $o_date);
         $o_date_part->SetIsFieldset(true);
         $o_match_box->AddControl($o_date_part);
     }
     # Who's playing?
     if ($this->i_match_type == MatchType::PRACTICE and isset($this->context_team)) {
         $home_id = new TextBox($this->GetNamingPrefix() . 'Home', $this->context_team->GetId());
         $home_id->SetMode(TextBoxMode::Hidden());
         $away_id = new TextBox($this->GetNamingPrefix() . 'Away', $this->context_team->GetId());
         $away_id->SetMode(TextBoxMode::Hidden());
         $o_match_box->AddControl($home_id);
         $o_match_box->AddControl($away_id);
     } else {
         $o_home_list = new XhtmlSelect($this->GetNamingPrefix() . 'Home');
         $o_away_list = new XhtmlSelect($this->GetNamingPrefix() . 'Away');
         $first_real_team_index = 0;
         if ($this->b_user_is_admin) {
             # Option of not specifying teams is currently admin-only
             # Value of 0 is important because PHP sees it as boolean negative, but it can be used as the indexer of an array in JavaScript
             $o_home_list->AddControl(new XhtmlOption("Don't know yet", '0'));
             $o_away_list->AddControl(new XhtmlOption("Don't know yet", '0'));
             $first_real_team_index = 1;
         }
         foreach ($this->a_teams as $group_name => $teams) {
             foreach ($teams as $o_team) {
                 $home_option = new XhtmlOption($o_team->GetName(), $o_team->GetId());
                 if (is_string($group_name) and $group_name) {
                     $home_option->SetGroupName($group_name);
                 }
                 $o_home_list->AddControl($home_option);
                 $away_option = new XhtmlOption($o_team->GetName(), $o_team->GetId());
                 if (is_string($group_name) and $group_name) {
                     $away_option->SetGroupName($group_name);
                 }
                 $o_away_list->AddControl($away_option);
             }
         }
         $o_home_part = new FormPart('Home team', $o_home_list);
         $o_away_part = new FormPart('Away team', $o_away_list);
         $o_match_box->AddControl($o_home_part);
         $o_match_box->AddControl($o_away_part);
         if ($b_got_home) {
             $o_home_list->SelectOption($o_match->GetHomeTeamId());
         }
         if (!$b_got_home and $b_is_new_match) {
             // if no home team data, select the first team by default
             // unless editing a match, in which case it may be correct to have no teams (eg cup final)
             $o_home_list->SelectIndex($first_real_team_index);
         }
         if (!$b_got_away and $b_is_new_match) {
             // if no away team data, select the second team as the away team so that it's not the same as the first
             // unless editing a match, in which case it may be correct to have no teams (eg cup final).
             $o_away_list->SelectIndex($first_real_team_index + 1);
             // if there was a home team but not an away team, make sure we don't select the home team against itself
             if ($b_got_home and $o_away_list->GetSelectedValue() == (string) $o_match->GetHomeTeamId()) {
                 $o_away_list->SelectIndex($first_real_team_index);
             }
         } else {
             if ($b_got_away) {
                 $o_away_list->SelectOption($o_match->GetAwayTeamId());
             }
             if (!$b_is_new_match) {
                 # Note which away team was previously saved, even if it's "not known" - this is for JavaScript to know it shouldn't auto-change the away team
                 $away_saved = new TextBox($this->GetNamingPrefix() . 'SavedAway', $o_match->GetAwayTeamId());
                 $away_saved->SetMode(TextBoxMode::Hidden());
                 $o_match_box->AddControl($away_saved);
                 unset($away_saved);
             }
         }
     }
     # Where?
     # If tournament match, assume same ground as tournament. Otherwise ask the user for ground.
     if ($b_is_tournament_match) {
         $ground = new TextBox($this->GetNamingPrefix() . 'Ground', $this->tournament->GetGroundId() ? $this->tournament->GetGroundId() : $o_match->GetGroundId());
         $ground->SetMode(TextBoxMode::Hidden());
         $o_match_box->AddControl($ground);
     } else {
         $o_ground_list = new XhtmlSelect($this->GetNamingPrefix() . 'Ground');
         $o_ground_list->AddControl(new XhtmlOption("Don't know", -1));
         $o_ground_list->AddControl(new XhtmlOption('Not listed (type the address in the notes field)', -2));
         # Promote home grounds for this season to the top of the list
         $a_home_ground_ids = array();
         foreach ($this->a_teams as $teams) {
             foreach ($teams as $o_team) {
                 $a_home_ground_ids[$o_team->GetId()] = $o_team->GetGround()->GetId();
             }
         }
         $a_home_grounds = array();
         $a_other_grounds = array();
         /* @var $o_ground Ground */
         foreach ($this->a_grounds as $o_ground) {
             if (array_search($o_ground->GetId(), $a_home_ground_ids) > -1) {
                 $a_home_grounds[] = $o_ground;
             } else {
                 $a_other_grounds[] = $o_ground;
             }
         }
         # Add home grounds
         foreach ($a_home_grounds as $o_ground) {
             $option = new XhtmlOption($o_ground->GetNameAndTown(), $o_ground->GetId());
             $option->SetGroupName('Home grounds');
             $o_ground_list->AddControl($option);
         }
         # Add away grounds
         foreach ($a_other_grounds as $o_ground) {
             $option = new XhtmlOption($o_ground->GetNameAndTown(), $o_ground->GetId());
             $option->SetGroupName('Away grounds');
             $o_ground_list->AddControl($option);
         }
         # Select ground
         if ($o_match->GetGroundId()) {
             $o_ground_list->SelectOption($o_match->GetGroundId());
         } elseif ($this->i_match_type == MatchType::PRACTICE and isset($this->context_team)) {
             $o_ground_list->SelectOption($this->context_team->GetGround()->GetId());
         }
         $o_ground_part = new FormPart('Where?', $o_ground_list);
         $o_match_box->AddControl($o_ground_part);
         # Note which grounds belong to which teams, for use by match-fixture-edit-control.js to select a ground when the home team is changed
         # Format is 1,2;2,3;4,5
         # where ; separates each team, and for each team the first number identifies the team and the second is the ground
         $s_team_ground = '';
         foreach ($a_home_ground_ids as $i_team => $i_ground) {
             if ($s_team_ground) {
                 $s_team_ground .= ';';
             }
             $s_team_ground .= $i_team . ',' . $i_ground;
         }
         $o_hidden = new TextBox($this->GetNamingPrefix() . 'TeamGround', $s_team_ground);
         $o_hidden->SetMode(TextBoxMode::Hidden());
         $o_match_box->AddControl($o_hidden);
         unset($o_hidden);
         # Note which ground was previously saved - this is for JavaScript to know it shouldn't auto-change the ground
         if (!$b_is_new_match) {
             $o_hidden = new TextBox($this->GetNamingPrefix() . 'SavedGround', $o_match->GetGroundId());
             $o_hidden->SetMode(TextBoxMode::Hidden());
             $o_match_box->AddControl($o_hidden);
             unset($o_hidden);
         }
     }
     # Notes
     $o_notes = new TextBox($this->GetNamingPrefix() . 'Notes', $o_match->GetNotes());
     $o_notes->SetMode(TextBoxMode::MultiLine());
     $o_notes_part = new FormPart('Notes', $o_notes);
     $o_match_box->AddControl($o_notes_part);
     # Remember match type, tournament and short URL
     $o_type = new TextBox($this->GetNamingPrefix() . 'MatchType', $this->GetMatchType());
     $o_type->SetMode(TextBoxMode::Hidden());
     $o_match_box->AddControl($o_type);
     if ($b_is_tournament_match) {
         $tourn_box = new TextBox($this->GetNamingPrefix() . 'Tournament', $this->tournament->GetId());
         $tourn_box->SetMode(TextBoxMode::Hidden());
         $o_match_box->AddControl($tourn_box);
     }
     $o_short_url = new TextBox($this->GetNamingPrefix() . 'ShortUrl', $o_match->GetShortUrl());
     $o_short_url->SetMode(TextBoxMode::Hidden());
     $o_match_box->AddControl($o_short_url);
     # Note the context team - to be picked up by JavaScript to enable auto-changing of away team if
     # context team is not selected as home team
     if (isset($this->context_team)) {
         $context_team_box = new TextBox($this->GetNamingPrefix() . 'ContextTeam', $this->context_team->GetId());
         $context_team_box->SetMode(TextBoxMode::Hidden());
         $o_match_box->AddControl($context_team_box);
     }
 }