function CreateControls()
 {
     $match = $this->GetDataObject();
     /* @var $match Match */
     $this->b_user_is_match_owner = ($match->GetAddedBy() instanceof User and AuthenticationManager::GetUser()->GetId() == $match->GetAddedBy()->GetId());
     $this->AddCssClass('legacy-form');
     if ($this->b_user_is_match_admin) {
         # Add match title editing
         $b_new = !$match->GetId();
         $title = new TextBox('title', $b_new ? '' : $match->GetTitle());
         $title->SetMaxLength(100);
         $this->AddControl(new FormPart('Match title', $title));
         $o_generate = new CheckBox('defaultTitle', 'Use default title', 1);
         if ($b_new) {
             $o_generate->SetChecked(true);
         } else {
             $o_generate->SetChecked(!$match->GetUseCustomTitle());
         }
         $this->AddControl($o_generate);
         # Add match type
         if ($match->GetMatchType() != MatchType::TOURNAMENT_MATCH) {
             $o_type_list = new XhtmlSelect('type');
             $o_type_list->AddControl(new XhtmlOption(MatchType::Text(MatchType::LEAGUE), MatchType::LEAGUE));
             $o_type_list->AddControl(new XhtmlOption(MatchType::Text(MatchType::PRACTICE), MatchType::PRACTICE));
             $o_type_list->AddControl(new XhtmlOption(MatchType::Text(MatchType::FRIENDLY), MatchType::FRIENDLY));
             $o_type_list->AddControl(new XhtmlOption(MatchType::Text(MatchType::CUP), MatchType::CUP));
             $o_type_list->SelectOption($match->GetMatchType());
             $this->AddControl(new FormPart('Type of match', $o_type_list));
         }
     }
     if ($this->b_user_is_match_owner or $this->b_user_is_match_admin) {
         $this->EnsureAggregatedEditors();
         $this->fixture_editor->SetDataObject($match);
         $this->AddControl($this->fixture_editor);
     }
     if ($this->b_user_is_match_admin) {
         # add season
         if (!$this->IsPostback()) {
             $this->season_editor->DataObjects()->SetItems($match->Seasons()->GetItems());
         }
         $this->AddControl($this->season_editor);
         # Hidden data on teams, for use by match-fixture-edit-control.js to re-sort teams when the season is changed
         # Format is 1,2,3,4,5;2,3,4,5,6
         # where ; separates each team, and for each team the first number identifies the team and subsequent numbers identify the season
         /* @var $o_team Team */
         /* @var $o_comp Competition */
         $s_team_season = '';
         # Build a list of all seasons, so that the "Not known yet" option can be added to all seasons
         $all_seasons = array();
         foreach ($this->fixture_editor->GetTeams() as $group) {
             foreach ($group as $o_team) {
                 if (!$o_team instanceof Team) {
                     continue;
                 }
                 # Add team id
                 if ($s_team_season) {
                     $s_team_season .= ';';
                 }
                 $s_team_season .= $o_team->GetId();
                 # add team seasons
                 foreach ($o_team->Seasons() as $team_in_season) {
                     $s_team_season .= ',' . $team_in_season->GetSeasonId();
                     $all_seasons[] = $team_in_season->GetSeasonId();
                 }
             }
         }
         # Add the "Don't know yet" option with all seasons
         $all_seasons = array_unique($all_seasons);
         $s_team_season = "0," . implode(",", $all_seasons) . ";{$s_team_season}";
         # Put it in a hidden field accessible to JavaScript.
         $o_ts = new TextBox($this->GetNamingPrefix() . 'TeamSeason', $s_team_season);
         $o_ts->SetMode(TextBoxMode::Hidden());
         $this->AddControl($o_ts);
     }
     $got_home_team = !is_null($match->GetHomeTeam());
     $got_away_team = !is_null($match->GetAwayTeam());
     $b_got_teams = ($got_home_team and $got_away_team);
     $b_future = ($match->GetId() and $match->GetStartTime() > gmdate('U'));
     // 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', "Result of this match");
     $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 batted first?
     if (!$b_future) {
         $match_box->AddControl('<h3>If the match went ahead:</h3>');
         $toss = $this->SelectOneOfTwoTeams($this->GetNamingPrefix() . 'Toss', $match, $match->Result()->GetTossWonBy() === TeamRole::Home(), $match->Result()->GetTossWonBy() === TeamRole::Away());
         $toss_part = new FormPart('Who won the toss?', $toss);
         $match_box->AddControl($toss_part);
         $bat_first = $this->SelectOneOfTwoTeams($this->GetNamingPrefix() . 'BatFirst', $match, $match->Result()->GetHomeBattedFirst() === true, $match->Result()->GetHomeBattedFirst() === false);
         $bat_part = new FormPart('Who batted first?', $bat_first);
         $match_box->AddControl($bat_part);
     }
     # Who won?
     $o_winner = new XhtmlSelect($this->GetNamingPrefix() . 'Result');
     if ($b_future) {
         $o_winner->AddControl(new XhtmlOption('The match will go ahead', ''));
     } else {
         # This option means "no change", therefore it has to have the current value for the match result even though that's
         # a different value from match to match. If it's not there the submitted match doesn't have result info, so when admin
         # saves fixture it regenerates its title as "Team A v Team B", which doesn't match the existing title so gets saved to db.
         # Can't be exactly the current value though, because otherwise a cancelled match has two options with the same value,
         # so re-selecting the option doesn't work. Instead change it to a negative number, which can be converted back when submitted.
         $o_winner->AddControl(new XhtmlOption('Not applicable &#8211; match went ahead', $match->Result()->GetResultType() * -1));
     }
     $result_types = array(MatchResult::HOME_WIN_BY_FORFEIT, MatchResult::AWAY_WIN_BY_FORFEIT, MatchResult::POSTPONED, MatchResult::CANCELLED, MatchResult::ABANDONED);
     foreach ($result_types as $result_type) {
         if (!$b_future or MatchResult::PossibleInAdvance($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));
             }
         }
     }
     $o_winner->SelectOption($match->Result()->GetResultType());
     if (!$b_future) {
         $match_box->AddControl('<h3 class="ifNotPlayed">Or, if the match was not played:</h3>');
     }
     $o_win_part = new FormPart($b_future ? 'Will it happen?' : 'Why not?', $o_winner);
     $match_box->AddControl($o_win_part);
     # Show audit data
     if ($match->GetLastAudit() != null) {
         require_once "data/audit-control.class.php";
         $match_box->AddControl(new AuditControl($match->GetLastAudit(), "match"));
     }
     # Remember short URL
     $o_short_url = new TextBox($this->GetNamingPrefix() . 'ShortUrl', $match->GetShortUrl());
     if ($this->b_user_is_match_admin) {
         $o_url_part = new FormPart('Short URL', $o_short_url);
         $this->AddControl($o_url_part);
         $this->AddControl(new CheckBox($this->GetNamingPrefix() . 'RegenerateUrl', 'Regenerate short URL', 1, !$match->GetUseCustomShortUrl(), $this->IsValidSubmit()));
     } else {
         $o_short_url->SetMode(TextBoxMode::Hidden());
         $this->AddControl($o_short_url);
     }
     if ($b_future and !$this->b_user_is_match_admin and !$this->b_user_is_match_owner) {
         $this->SetButtonText("Save result");
     }
 }
 /**
  * Creates, and re-populates on postback, a checkbox to manage one property of a related data item
  *
  * @param bool $b_validated_value
  * @param string $s_name
  * @param int $i_row_count
  * @param int $i_total_rows
  * @return TextBox
  */
 protected function CreateCheckbox($b_validated_value, $s_name, $i_row_count, $i_total_rows)
 {
     require_once 'xhtml/forms/checkbox.class.php';
     # Establish current status
     $b_is_add_row = is_null($i_row_count);
     $b_repopulate_add_row = (!$this->IsValid() or $this->DeleteClicked() or $this->IsUnrelatedInternalPostback());
     # Create checkbox
     $checkbox = new CheckBox($this->GetNamingPrefix() . $s_name . $i_row_count, '', 1);
     # Repopulate the previous value
     # If this is the row used to add a new related item...
     if ($b_is_add_row) {
         # ...if we repopulate, it's because validation has either failed or not occurred
         if ($b_repopulate_add_row) {
             $checkbox->SetChecked(isset($_POST[$checkbox->GetXhtmlId()]));
         }
     } else {
         if ($this->IsValid()) {
             if ($this->AddClicked() and $i_row_count == $this->i_row_added) {
                 # If a new row was posted, is valid, and is now displayed here, need to get the posted value from the add row
                 $s_checkbox_in_add_row = substr($checkbox->GetXhtmlId(), 0, strlen($checkbox->GetXhtmlId()) - strlen($i_row_count));
                 $checkbox->SetChecked(isset($_POST[$s_checkbox_in_add_row]));
             } else {
                 # Even though the editor as a whole is valid, this row wasn't validated
                 # so just restore the previous value
                 if ($this->IsPostback()) {
                     $checkbox->SetChecked(isset($_POST[$checkbox->GetXhtmlId()]));
                 } else {
                     # Won't be in $_POST when page is first loaded
                     $checkbox->SetChecked($b_validated_value);
                 }
             }
         } else {
             # Repopulate with the exact value posted, as validation has failed
             $checkbox->SetChecked(isset($_POST[$checkbox->GetXhtmlId()]));
         }
     }
     # Return checkbox so that other things can be done to it - eg add a CSS class
     return $checkbox;
 }