/**
  * Builds a match object containing the result information posted by the control
  *
  */
 public function BuildPostedDataObject()
 {
     $match = new Match($this->GetSettings());
     $match->SetMatchType(MatchType::TOURNAMENT);
     # Get match id
     $s_key = $this->GetNamingPrefix() . 'item';
     if (isset($_POST[$s_key])) {
         $s_id = $_POST[$s_key];
         if (strlen($s_id)) {
             $match->SetId($s_id);
         }
     }
     # Get the title
     $s_key = $this->GetNamingPrefix() . 'Title';
     if (isset($_POST[$s_key])) {
         $match->SetTitle(strip_tags($_POST[$s_key]));
     }
     $s_key = $this->GetNamingPrefix() . 'Seasons';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $possibly_posted = explode(';', $_POST[$s_key]);
         foreach ($possibly_posted as $season_id) {
             $s_key = $this->GetNamingPrefix() . 'Season' . $season_id;
             if (isset($_POST[$s_key]) and $_POST[$s_key] == $season_id) {
                 $season = new Season($this->GetSettings());
                 $season->SetId($_POST[$s_key]);
                 $match->Seasons()->Add($season);
             }
         }
     }
     $this->SetDataObject($match);
 }
 /**
  * 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);
     }
 }
 /**
  * Builds a match object containing the result information posted by the control
  *
  */
 public function BuildPostedDataObject()
 {
     $tournament = new Match($this->GetSettings());
     $tournament->SetMatchType(MatchType::TOURNAMENT);
     # Get match id
     $s_key = $this->GetNamingPrefix() . 'item';
     if (isset($_POST[$s_key])) {
         $s_id = $_POST[$s_key];
         if (strlen($s_id)) {
             $tournament->SetId($s_id);
         }
     }
     # Get the title
     $s_key = $this->GetNamingPrefix() . 'Title';
     if (isset($_POST[$s_key])) {
         $tournament->SetTitle(strip_tags($_POST[$s_key]));
     }
     # Get the start date, because it's part of the title that has to be recreated for an internal postback
     $s_key = $this->GetNamingPrefix() . 'Start';
     if (isset($_POST[$s_key])) {
         $tournament->SetStartTime($_POST[$s_key]);
     }
     # Matches - get from aggregated editor
     $this->EnsureAggregatedEditors();
     $matches = $this->matches_editor->DataObjects()->GetItems();
     foreach ($matches as $match) {
         $tournament->AddMatchInTournament($match);
     }
     $this->SetDataObject($tournament);
 }
 /**
  * @return void
  * @desc Re-build from data posted by this control the data object this control is editing
  */
 function BuildPostedDataObject()
 {
     $match = new Match($this->GetSettings());
     $match->SetId($this->GetDataObjectId());
     # Get match date
     $s_key = $this->GetNamingPrefix() . 'Date';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key]) and is_numeric($_POST[$s_key])) {
         $match->SetStartTime($_POST[$s_key]);
     }
     # Get team names
     $s_key = $this->GetNamingPrefix() . 'Home';
     if (isset($_POST[$s_key])) {
         $team_data = explode(MatchHighlightsEditControl::DATA_SEPARATOR, $_POST[$s_key], 2);
         if (count($team_data) == 2) {
             $o_home = new Team($this->GetSettings());
             $o_home->SetId($team_data[0]);
             $o_home->SetName($team_data[1]);
             $match->SetHomeTeam($o_home);
         }
     }
     $s_key = $this->GetNamingPrefix() . 'Away';
     if (isset($_POST[$s_key])) {
         $team_data = explode(MatchHighlightsEditControl::DATA_SEPARATOR, $_POST[$s_key], 2);
         if (count($team_data) == 2) {
             $o_away = new Team($this->GetSettings());
             $o_away->SetId($team_data[0]);
             $o_away->SetName($team_data[1]);
             $match->SetAwayTeam($o_away);
         }
     }
     # Get the result
     $s_key = $this->GetNamingPrefix() . 'Result';
     if (isset($_POST[$s_key])) {
         $s_result = $_POST[$s_key];
         if (strlen($s_result)) {
             $match->Result()->SetResultType($s_result);
         }
     }
     # Get players of the match. Fields to use depend on which radio button was selected.
     $s_key = $this->GetNamingPrefix() . 'POM';
     if (isset($_POST[$s_key])) {
         $pom_type = (int) $_POST[$s_key];
         if ($pom_type == MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_OVERALL) {
             $s_key = $this->GetNamingPrefix() . 'Player';
             if (isset($_POST[$s_key]) and $_POST[$s_key]) {
                 $player = new Player($this->GetSettings());
                 $player->SetName($_POST[$s_key]);
                 $s_key = $this->GetNamingPrefix() . 'PlayerTeam';
                 if (isset($_POST[$s_key])) {
                     $player->Team()->SetId($_POST[$s_key]);
                 }
                 $match->Result()->SetPlayerOfTheMatch($player);
             }
         } else {
             if ($pom_type == MatchHighlightsEditControl::PLAYER_OF_THE_MATCH_HOME_AND_AWAY) {
                 $s_key = $this->GetNamingPrefix() . 'PlayerHome';
                 if (isset($_POST[$s_key]) and $_POST[$s_key]) {
                     $player = new Player($this->GetSettings());
                     $player->SetName($_POST[$s_key]);
                     $player->Team()->SetId($match->GetHomeTeamId());
                     $match->Result()->SetPlayerOfTheMatchHome($player);
                 }
                 $s_key = $this->GetNamingPrefix() . 'PlayerAway';
                 if (isset($_POST[$s_key]) and $_POST[$s_key]) {
                     $player = new Player($this->GetSettings());
                     $player->SetName($_POST[$s_key]);
                     $player->Team()->SetId($match->GetAwayTeamId());
                     $match->Result()->SetPlayerOfTheMatchAway($player);
                 }
             }
         }
     }
     $s_key = $this->GetNamingPrefix() . 'Comments';
     if (isset($_POST[$s_key])) {
         $match->SetNewComment($_POST[$s_key]);
     }
     $this->SetDataObject($match);
 }
 /**
  * Builds a match object containing the result information posted by the control
  *
  */
 public function BuildPostedDataObject()
 {
     $match = new Match($this->GetSettings());
     $match->SetMatchType(MatchType::TOURNAMENT);
     # Get match id
     $s_key = $this->GetNamingPrefix() . 'item';
     if (isset($_POST[$s_key])) {
         $s_id = $_POST[$s_key];
         if (strlen($s_id)) {
             $match->SetId($s_id);
         }
     }
     # Get the title
     $s_key = $this->GetNamingPrefix() . 'Title';
     if (isset($_POST[$s_key])) {
         $match->SetTitle(strip_tags($_POST[$s_key]));
     }
     # Get the qualification type
     $s_key = $this->GetNamingPrefix() . 'Qualify';
     if (isset($_POST[$s_key])) {
         $match->SetQualificationType($_POST[$s_key]);
     }
     # Get the player type
     $s_key = $this->GetNamingPrefix() . 'PlayerType';
     if (isset($_POST[$s_key])) {
         $match->SetPlayerType($_POST[$s_key]);
     }
     $s_key = $this->GetNamingPrefix() . "Players";
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $match->SetMaximumPlayersPerTeam($_POST[$s_key]);
     }
     # Get the number of overs
     $s_key = $this->GetNamingPrefix() . "Overs";
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $match->SetOvers($_POST[$s_key]);
     }
     # Get the short URL
     $s_key = $this->GetNamingPrefix() . 'ShortUrl';
     if (isset($_POST[$s_key])) {
         $match->SetShortUrl($_POST[$s_key]);
     }
     # Get the start date
     $s_key = $this->GetNamingPrefix() . 'Start';
     $match->SetStartTime(DateControl::GetPostedTimestampUtc($s_key));
     $match->SetIsStartTimeKnown(DateControl::GetIsTimePosted($s_key));
     # Get the initial team
     $team = new Team($this->GetSettings());
     $s_key = $this->GetNamingPrefix() . 'ContextTeam';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $team->SetId($_POST[$s_key]);
         $match->AddAwayTeam($team);
     }
     # Get the ground
     $s_key = $this->GetNamingPrefix() . 'Ground';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $o_ground = new Ground($this->GetSettings());
         $o_ground->SetId($_POST[$s_key]);
         $match->SetGround($o_ground);
     }
     # Get the notes
     $s_key = $this->GetNamingPrefix() . 'Notes';
     if (isset($_POST[$s_key])) {
         $match->SetNotes($_POST[$s_key]);
     }
     $this->SetDataObject($match);
 }
 /**
  * Checks whether the given match fixture data is already in the database; returns the duplicate match or null
  *
  * @param Match $match_to_compare
  * @param bool $b_user_is_match_admin
  * @return Match
  */
 private function GetDuplicateFixture(Match $match_to_compare, $b_user_is_match_admin)
 {
     # Make sure it's not a duplicate. If it is, return the duplicate match.
     $is_duplicate = false;
     $is_new_match = !(bool) $match_to_compare->GetId();
     $id_of_duplicate = null;
     $s_match = $this->GetSettings()->GetTable('Match');
     $s_mt = $this->GetSettings()->GetTable('MatchTeam');
     $i_tournament = is_null($match_to_compare->GetTournament()) ? null : $match_to_compare->GetTournament()->GetId();
     $i_ground = $match_to_compare->GetGroundId() > 0 ? $match_to_compare->GetGroundId() : null;
     $s_sql = "SELECT {$s_match}.match_id FROM {$s_match} INNER JOIN {$s_mt} ON {$s_match}.match_id = {$s_mt}.match_id AND {$s_mt}.team_role = " . TeamRole::Home();
     $s_where = $this->SqlAddCondition('', 'tournament_match_id' . Sql::ProtectNumeric($i_tournament, true, true));
     $s_where = $this->SqlAddCondition($s_where, 'ground_id' . Sql::ProtectNumeric($i_ground, true, true));
     $s_where = $this->SqlAddCondition($s_where, 'start_time = ' . Sql::ProtectNumeric($match_to_compare->GetStartTime()));
     $s_where = $this->SqlAddCondition($s_where, 'start_time_known = ' . Sql::ProtectBool($match_to_compare->GetIsStartTimeKnown()));
     $s_where = $this->SqlAddCondition($s_where, 'match_notes = ' . Sql::ProtectString($this->GetDataConnection(), $match_to_compare->GetNotes()));
     $s_where = $this->SqlAddCondition($s_where, "{$s_mt}.team_id" . Sql::ProtectNumeric($match_to_compare->GetHomeTeamId(), true, true));
     # If it's a new match we want to check that it's not a duplicate match type of one already added.
     # If it's an updated match only an admin can change that. If not an admin, data's not even available so don't compare.
     if ($is_new_match or $b_user_is_match_admin) {
         $s_where = $this->SqlAddCondition($s_where, 'match_type = ' . Sql::ProtectNumeric($match_to_compare->GetMatchType()));
     }
     # If it's a tournament the player type should be specified by the user so check whether it's changed.
     # For any other match it's inferred automatically from other metadata about the match as it's saved,
     # and we're already checking whether that other data has changed so don't check for player type.
     if ($match_to_compare->GetMatchType() == MatchType::TOURNAMENT) {
         $s_where = $this->SqlAddCondition($s_where, 'player_type_id' . Sql::ProtectNumeric($match_to_compare->GetPlayerType(), true, true));
     }
     # If there's an id we're comparing whether the existing match has changed.
     # If no id we're looking whether the match has already been added, probably by someone else.
     if (!$is_new_match) {
         $s_where = $this->SqlAddCondition($s_where, "{$s_match}.match_id" . Sql::ProtectNumeric($match_to_compare->GetId(), false, true));
         # Only compare title properties for an update to a match, not for a match being added. If a new match is being added
         # the same match may exist with a different title because a result has been filled in - we still want to treat that as
         # a duplicate and not add the new match. But if the match is being updated it can only come from the match editing screen,
         # where the existing title is visible. The title may have changed due to an updated result, but OK to treat this as a changed
         # fixture in that event - an email about the match update is going to be sent and the match marked as updated anyway, so no problem.
         $s_where = $this->SqlAddCondition($s_where, 'match_title = ' . Sql::ProtectString($this->GetDataConnection(), $match_to_compare->GetTitle(), false));
         $s_where = $this->SqlAddCondition($s_where, 'custom_title' . Sql::ProtectBool($match_to_compare->GetUseCustomTitle(), false, true));
         # A new match would have either no or a newly-generated short URL, which inevitably would be different from the existing match
         # had it already been entered. But if we're updating the match the short URL may have been changed deliberately and we want to
         # recognise that change, not throw it away as a duplicate.
         $s_where = $this->SqlAddCondition($s_where, 'short_url = ' . Sql::ProtectString($this->GetDataConnection(), $match_to_compare->GetShortUrl(), false));
     }
     $s_sql = $this->SqlAddWhereClause($s_sql, $s_where);
     $result = $this->GetDataConnection()->query($s_sql);
     if ($o_row = $result->fetch()) {
         $id_of_duplicate = $o_row->match_id;
         # if it's a new match, this gives info on the match as it already exists
         $is_duplicate = true;
     }
     $result->closeCursor();
     # If basic match details appear to be a duplicate, does it have the same away team(s) too?
     if ($is_duplicate) {
         $s_sql = "SELECT team_id FROM {$s_mt} WHERE match_id =  " . Sql::ProtectNumeric($id_of_duplicate) . " AND team_role = " . TeamRole::Away();
         $result = $this->GetDataConnection()->query($s_sql);
         $existing_away_team_ids = array();
         while ($row = $result->fetch()) {
             $existing_away_team_ids[] = (int) $row->team_id;
         }
         $result->closeCursor();
         if (count($existing_away_team_ids) != count($match_to_compare->GetAwayTeams())) {
             # Different number of teams...
             $is_duplicate = false;
         }
         # Same number of away teams... now are those away teams the same ones as in the match we're comparing?
         if ($is_duplicate) {
             foreach ($match_to_compare->GetAwayTeams() as $team) {
                 /* @var $team Team */
                 if (!in_array($team->GetId(), $existing_away_team_ids, true)) {
                     $is_duplicate = false;
                     break;
                 }
             }
         }
     }
     # If basic match details and away teams appear to be a duplicate, does it have the same season(s) too?
     if ($is_duplicate) {
         # 1. If the user isn't admin and is updating match, don't check. They're not allowed to change season data so it's not even available.
         # 2. If the user isn't admin and it's a new match, is the existing match in the given season - don't care if it's in others too
         # 3. If the user is an admin, we want to look for an exact match
         if ($b_user_is_match_admin or $is_new_match) {
             $s_sql = "SELECT season_id FROM " . $this->GetSettings()->GetTable('SeasonMatch') . " WHERE match_id =  " . Sql::ProtectNumeric($id_of_duplicate);
             $result = $this->GetDataConnection()->query($s_sql);
             $existing_season_ids = array();
             while ($row = $result->fetch()) {
                 $existing_season_ids[] = (int) $row->season_id;
             }
             $result->closeCursor();
             if (count($existing_season_ids) == $match_to_compare->Seasons()->GetCount() or !$b_user_is_match_admin and $is_new_match) {
                 # Same number of seasons...
             } else {
                 # Different number of seasons...
                 $is_duplicate = false;
             }
             # Disposed of result, now are those seasons are the same ones as in the match we're comparing?
             if ($is_duplicate) {
                 foreach ($match_to_compare->Seasons() as $season) {
                     /* @var $season Season */
                     if (!in_array($season->GetId(), $existing_season_ids, true)) {
                         $is_duplicate = false;
                         break;
                     }
                 }
             }
         }
     }
     # Return the duplicate if one was found, otherwise return null
     if ($is_duplicate) {
         $match_to_compare->SetId($id_of_duplicate);
         return $match_to_compare;
     } else {
         return null;
     }
 }
 /**
  * Builds a match object containing the result information posted by the control
  *
  */
 public function BuildPostedDataObject()
 {
     $o_match = new Match($this->GetSettings());
     $o_match->SetId($this->GetDataObjectId());
     # Get match date
     $s_key = $this->GetNamingPrefix() . 'Date';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key]) and is_numeric($_POST[$s_key])) {
         $o_match->SetStartTime($_POST[$s_key]);
     }
     # Get team names
     $s_key = $this->GetNamingPrefix() . 'Home';
     if (isset($_POST[$s_key])) {
         $team_data = explode(";", $_POST[$s_key], 2);
         if (count($team_data) == 2) {
             $o_home = new Team($this->GetSettings());
             $o_home->SetId($team_data[0]);
             $o_home->SetName($team_data[1]);
             $o_match->SetHomeTeam($o_home);
         }
     }
     $s_key = $this->GetNamingPrefix() . 'Away';
     if (isset($_POST[$s_key])) {
         $team_data = explode(";", $_POST[$s_key], 2);
         if (count($team_data) == 2) {
             $o_away = new Team($this->GetSettings());
             $o_away->SetId($team_data[0]);
             $o_away->SetName($team_data[1]);
             $o_match->SetAwayTeam($o_away);
         }
     }
     # Get who batted first
     $s_key = $this->GetNamingPrefix() . 'BatFirst';
     if (isset($_POST[$s_key])) {
         $s_batted = $_POST[$s_key];
         if ($s_batted == 'home') {
             $o_match->Result()->SetHomeBattedFirst(true);
         } else {
             if ($s_batted == 'away') {
                 $o_match->Result()->SetHomeBattedFirst(false);
             }
         }
     }
     # Get the result
     $s_key = $this->GetNamingPrefix() . 'Result';
     if (isset($_POST[$s_key])) {
         $s_result = $_POST[$s_key];
         if (strlen($s_result)) {
             $o_match->Result()->SetResultType($s_result);
         }
     }
     # Get the home score
     $s_key = $this->GetNamingPrefix() . 'HomeRuns';
     if (isset($_POST[$s_key])) {
         $s_home_runs = $_POST[$s_key];
         if (strlen($s_home_runs)) {
             $o_match->Result()->SetHomeRuns($s_home_runs);
         }
     }
     $s_key = $this->GetNamingPrefix() . 'HomeWickets';
     if (isset($_POST[$s_key])) {
         $s_home_wickets = $_POST[$s_key];
         if (strlen($s_home_wickets)) {
             $o_match->Result()->SetHomeWickets($s_home_wickets);
         }
     }
     # Get the away score
     $s_key = $this->GetNamingPrefix() . 'AwayRuns';
     if (isset($_POST[$s_key])) {
         $s_away_runs = $_POST[$s_key];
         if (strlen($s_away_runs)) {
             $o_match->Result()->SetAwayRuns($s_away_runs);
         }
     }
     $s_key = $this->GetNamingPrefix() . 'AwayWickets';
     if (isset($_POST[$s_key])) {
         $s_away_wickets = $_POST[$s_key];
         if (strlen($s_away_wickets)) {
             $o_match->Result()->SetAwayWickets($s_away_wickets);
         }
     }
     $s_key = $this->GetNamingPrefix() . 'Comments';
     if (isset($_POST[$s_key])) {
         $o_match->SetNewComment($_POST[$s_key]);
     }
     $this->SetDataObject($o_match);
 }
 /**
  * Builds a match object containing the result information posted by the control
  *
  */
 public function BuildPostedDataObject()
 {
     $o_match = new Match($this->GetSettings());
     # Get match id
     $s_key = $this->GetNamingPrefix() . 'item';
     if (isset($_POST[$s_key])) {
         $s_id = $_POST[$s_key];
         if (strlen($s_id)) {
             $o_match->SetId($s_id);
         }
     }
     # Get the short URL
     $s_key = $this->GetNamingPrefix() . 'ShortUrl';
     if (isset($_POST[$s_key])) {
         $o_match->SetShortUrl($_POST[$s_key]);
     }
     # Get the start date
     $s_key = $this->GetNamingPrefix() . 'Start';
     $o_match->SetStartTime(DateControl::GetPostedTimestampUtc($s_key));
     $o_match->SetIsStartTimeKnown(DateControl::GetIsTimePosted($s_key));
     # Get the home team
     # Test for (int)$_POST[$s_key] deliberately excludes "Not known" value, which is 0
     $o_home = new Team($this->GetSettings());
     $s_key = $this->GetNamingPrefix() . 'Home';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key]) and (int) $_POST[$s_key]) {
         $o_home->SetId($_POST[$s_key]);
         $o_match->SetHomeTeam($o_home);
     }
     # Get the away team
     # Test for (int)$_POST[$s_key] deliberately excludes "Not known" value, which is 0
     $o_away = new Team($this->GetSettings());
     $s_key = $this->GetNamingPrefix() . 'Away';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key]) and (int) $_POST[$s_key]) {
         $o_away->SetId($_POST[$s_key]);
         $o_match->SetAwayTeam($o_away);
     }
     # Get the ground
     $s_key = $this->GetNamingPrefix() . 'Ground';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $o_ground = new Ground($this->GetSettings());
         $o_ground->SetId($_POST[$s_key]);
         $o_match->SetGround($o_ground);
     }
     # Get the notes
     $s_key = $this->GetNamingPrefix() . 'Notes';
     if (isset($_POST[$s_key])) {
         $o_match->SetNotes($_POST[$s_key]);
     }
     # Get the match type
     $s_key = $this->GetNamingPrefix() . 'MatchType';
     if (isset($_POST[$s_key]) and is_numeric($_POST[$s_key])) {
         $o_match->SetMatchType($_POST[$s_key]);
     }
     # Get the tournament
     if ($o_match->GetMatchType() == MatchType::TOURNAMENT_MATCH) {
         $s_key = $this->GetNamingPrefix() . 'Tournament';
         if (isset($_POST[$s_key]) and is_numeric($_POST[$s_key])) {
             $tournament = new Match($this->GetSettings());
             $tournament->SetMatchType(MatchType::TOURNAMENT);
             $tournament->SetId($_POST[$s_key]);
             $o_match->SetTournament($tournament);
         }
     }
     # Get the season
     $s_key = $this->GetNamingPrefix() . 'Season';
     if (isset($_POST[$s_key]) and strlen($_POST[$s_key])) {
         $o_season = new Season($this->GetSettings());
         $o_season->SetId($_POST[$s_key]);
         $o_match->Seasons()->Add($o_season);
     }
     $this->SetDataObject($o_match);
 }
 /**
  * Populates the collection of business objects from raw data
  *
  * @return bool
  * @param MySqlRawData $o_result
  */
 protected function BuildItems(MySqlRawData $o_result)
 {
     $this->Clear();
     $o_match_builder = new CollectionBuilder();
     $o_team_builder = new CollectionBuilder();
     while ($o_row = $o_result->fetch()) {
         if (!$o_match_builder->IsDone($o_row->match_id)) {
             if (isset($o_match)) {
                 $this->Add($o_match);
                 $o_team_builder->Reset();
             }
             # create new
             $o_match = new Match($this->GetSettings());
             $o_match->SetId($o_row->match_id);
             if (isset($o_row->start_time)) {
                 $o_match->SetStartTime($o_row->start_time);
             }
             if (isset($o_row->home_runs)) {
                 $o_match->Result()->SetHomeRuns($o_row->home_runs);
             }
             if (isset($o_row->away_runs)) {
                 $o_match->Result()->SetAwayRuns($o_row->away_runs);
             }
             if (isset($o_row->match_result_id)) {
                 $o_match->Result()->SetResultType($o_row->match_result_id);
             }
             if (isset($o_row->home_team_id) and !is_null($o_row->home_team_id)) {
                 $o_home = new Team($this->o_settings);
                 $o_home->SetId($o_row->home_team_id);
                 if (isset($o_row->home_team_name)) {
                     $o_home->SetName($o_row->home_team_name);
                 }
                 if (isset($o_row->home_short_url)) {
                     $o_home->SetShortUrl($o_row->home_short_url);
                 }
                 $o_match->SetHomeTeam($o_home);
                 unset($o_home);
             }
             if (isset($o_row->ground_id)) {
                 $o_ground = new Ground($this->GetSettings());
                 $o_ground->SetId($o_row->ground_id);
                 $o_match->SetGround($o_ground);
                 unset($o_ground);
             }
         }
         # Add away teams
         if (isset($o_row->away_team_id) && !$o_team_builder->IsDone($o_row->away_team_id)) {
             $o_away = new Team($this->o_settings);
             $o_away->SetId($o_row->away_team_id);
             if (isset($o_row->away_team_name)) {
                 $o_away->SetName($o_row->away_team_name);
             }
             if (isset($o_row->away_short_url)) {
                 $o_away->SetShortUrl($o_row->away_short_url);
             }
             $o_match->AddAwayTeam($o_away);
             unset($o_away);
         }
     }
     # Add final match
     if (isset($o_match)) {
         $this->Add($o_match);
     }
     return true;
 }
 /**
  * Builds data posted on pages 2/3 back into a match object
  * @return Match
  */
 private function BuildPostedScorecard()
 {
     $match = new Match($this->GetSettings());
     $match->SetId($this->GetDataObjectId());
     # Must have data on which team is which, otherwise none of the rest makes sense
     # Team ids are essential for saving data, while team names and match title are
     # purely so they can be redisplayed if the page is invalid
     $key = "teams";
     if (!isset($_POST[$key]) or strpos($_POST[$key], ScorecardEditControl::DATA_SEPARATOR) === false) {
         return $match;
     }
     $teams = explode(ScorecardEditControl::DATA_SEPARATOR, $_POST[$key], 6);
     if (count($teams) != 6) {
         return $match;
     }
     switch ($teams[0]) {
         case "0":
             $match->Result()->SetHomeBattedFirst(false);
             $home_batting = $this->GetCurrentPage() == 3;
             break;
         case "1":
             $match->Result()->SetHomeBattedFirst(true);
             $home_batting = $this->GetCurrentPage() == 2;
             break;
         default:
             $home_batting = $this->GetCurrentPage() == 2;
     }
     $home_team = new Team($this->GetSettings());
     $home_team->SetId($teams[1]);
     $home_team->SetName($teams[2]);
     $match->SetHomeTeam($home_team);
     $away_team = new Team($this->GetSettings());
     $away_team->SetId($teams[3]);
     $away_team->SetName($teams[4]);
     $match->SetAwayTeam($away_team);
     $match->SetTitle($teams[5]);
     # Read posted batting data
     $key = "batRows";
     if (isset($_POST[$key])) {
         # This controls not only which fields are read, but also which are redisplayed on an invalid postback or for the next innings.
         $match->SetMaximumPlayersPerTeam(intval($_POST[$key]));
     }
     for ($i = 1; $i <= $match->GetMaximumPlayersPerTeam(); $i++) {
         $key = "batName{$i}";
         if (isset($_POST[$key])) {
             # The row exists - has it been filled in?
             if (trim($_POST[$key])) {
                 # Read the batter data in this row
                 $player = new Player($this->GetSettings());
                 $player->SetName($_POST[$key]);
                 $player->Team()->SetId($home_batting ? $home_team->GetId() : $away_team->GetId());
                 $key = "batHowOut{$i}";
                 $how_out = (isset($_POST[$key]) and is_numeric($_POST[$key])) ? (int) $_POST[$key] : null;
                 $key = "batOutBy{$i}";
                 $dismissed_by = null;
                 if (isset($_POST[$key]) and trim($_POST[$key])) {
                     $dismissed_by = new Player($this->GetSettings());
                     $dismissed_by->SetName($_POST[$key]);
                     $dismissed_by->Team()->SetId($home_batting ? $away_team->GetId() : $home_team->GetId());
                 }
                 $key = "batBowledBy{$i}";
                 $bowler = null;
                 if (isset($_POST[$key]) and trim($_POST[$key])) {
                     $bowler = new Player($this->GetSettings());
                     $bowler->SetName($_POST[$key]);
                     $bowler->Team()->SetId($home_batting ? $away_team->GetId() : $home_team->GetId());
                 }
                 # Correct caught and bowled if marked as caught
                 if ($how_out == Batting::CAUGHT and !is_null($dismissed_by) and !is_null($bowler) and trim($dismissed_by->GetName()) == trim($bowler->GetName())) {
                     $how_out = Batting::CAUGHT_AND_BOWLED;
                     $dismissed_by = null;
                 }
                 $key = "batRuns{$i}";
                 $runs = (isset($_POST[$key]) and is_numeric($_POST[$key])) ? (int) $_POST[$key] : null;
                 $key = "batBalls{$i}";
                 $balls = (isset($_POST[$key]) and is_numeric($_POST[$key])) ? (int) $_POST[$key] : null;
                 # Add that batting performance to the match result
                 $batting = new Batting($player, $how_out, $dismissed_by, $bowler, $runs, $balls);
                 if ($home_batting) {
                     $match->Result()->HomeBatting()->Add($batting);
                 } else {
                     $match->Result()->AwayBatting()->Add($batting);
                 }
             }
         }
     }
     $key = "batByes";
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         $player = new Player($this->GetSettings());
         $player->SetPlayerRole(Player::BYES);
         $player->Team()->SetId($home_batting ? $home_team->GetId() : $away_team->GetId());
         $batting = new Batting($player, null, null, null, (int) $_POST[$key]);
         if ($home_batting) {
             $match->Result()->HomeBatting()->Add($batting);
         } else {
             $match->Result()->AwayBatting()->Add($batting);
         }
     }
     $key = "batWides";
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         $player = new Player($this->GetSettings());
         $player->SetPlayerRole(Player::WIDES);
         $player->Team()->SetId($home_batting ? $home_team->GetId() : $away_team->GetId());
         $batting = new Batting($player, null, null, null, (int) $_POST[$key]);
         if ($home_batting) {
             $match->Result()->HomeBatting()->Add($batting);
         } else {
             $match->Result()->AwayBatting()->Add($batting);
         }
     }
     $key = "batNoBalls";
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         $player = new Player($this->GetSettings());
         $player->SetPlayerRole(Player::NO_BALLS);
         $player->Team()->SetId($home_batting ? $home_team->GetId() : $away_team->GetId());
         $batting = new Batting($player, null, null, null, (int) $_POST[$key]);
         if ($home_batting) {
             $match->Result()->HomeBatting()->Add($batting);
         } else {
             $match->Result()->AwayBatting()->Add($batting);
         }
     }
     $key = "batBonus";
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         $player = new Player($this->GetSettings());
         $player->SetPlayerRole(Player::BONUS_RUNS);
         $player->Team()->SetId($home_batting ? $home_team->GetId() : $away_team->GetId());
         $batting = new Batting($player, null, null, null, (int) $_POST[$key]);
         if ($home_batting) {
             $match->Result()->HomeBatting()->Add($batting);
         } else {
             $match->Result()->AwayBatting()->Add($batting);
         }
     }
     $key = "batTotal";
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         if ($home_batting) {
             $match->Result()->SetHomeRuns($_POST[$key]);
         } else {
             $match->Result()->SetAwayRuns($_POST[$key]);
         }
     }
     $key = "batWickets";
     if (isset($_POST[$key]) and is_numeric($_POST[$key])) {
         if ($home_batting) {
             $match->Result()->SetHomeWickets($_POST[$key]);
         } else {
             $match->Result()->SetAwayWickets($_POST[$key]);
         }
     }
     # Read posted bowling data
     $key = "bowlerRows";
     if (isset($_POST[$key])) {
         # This controls not only which fields are read, but also which are redisplayed on an invalid postback or for the next innings.
         $match->SetOvers(intval($_POST[$key]));
     }
     for ($i = 1; $i <= $match->GetOvers(); $i++) {
         $key = "bowlerName{$i}";
         if (isset($_POST[$key])) {
             # The row exists - has it been filled in?
             if (trim($_POST[$key])) {
                 # Read the bowler data in this row
                 # strlen test allows 0 but not empty string, because is_numeric allows empty string
                 $player = new Player($this->GetSettings());
                 $player->SetName($_POST[$key]);
                 $player->Team()->SetId($home_batting ? $away_team->GetId() : $home_team->GetId());
                 $key = "bowlerBalls{$i}";
                 $balls = (isset($_POST[$key]) and is_numeric($_POST[$key]) and strlen(trim($_POST[$key]))) ? (int) $_POST[$key] : null;
                 $key = "bowlerNoBalls{$i}";
                 $no_balls = (isset($_POST[$key]) and is_numeric($_POST[$key]) and strlen(trim($_POST[$key]))) ? (int) $_POST[$key] : null;
                 $key = "bowlerWides{$i}";
                 $wides = (isset($_POST[$key]) and is_numeric($_POST[$key]) and strlen(trim($_POST[$key]))) ? (int) $_POST[$key] : null;
                 $key = "bowlerRuns{$i}";
                 $runs = (isset($_POST[$key]) and is_numeric($_POST[$key]) and strlen(trim($_POST[$key]))) ? (int) $_POST[$key] : null;
                 # Add that over to the match result
                 $bowling = new Over($player);
                 $bowling->SetBalls($balls);
                 $bowling->SetNoBalls($no_balls);
                 $bowling->SetWides($wides);
                 $bowling->SetRunsInOver($runs);
                 if ($home_batting) {
                     $match->Result()->AwayOvers()->Add($bowling);
                 } else {
                     $match->Result()->HomeOvers()->Add($bowling);
                 }
             }
         }
     }
     return $match;
 }