function OnLoadPageData()
 {
     /* @var Match $tournament */
     # check parameter
     if (!isset($_GET['match']) or !is_numeric($_GET['match'])) {
         $this->Redirect();
     }
     # get match
     $match_manager = new MatchManager($this->GetSettings(), $this->GetDataConnection());
     $match_manager->ReadByMatchId(array($_GET['match']));
     $match_manager->ExpandMatchScorecards();
     $this->match = $match_manager->GetFirst();
     unset($match_manager);
     # must have found a match
     if (!$this->match instanceof Match) {
         $this->page_not_found = true;
         return;
     }
     $result = $this->match->Result();
     $this->has_statistics = $result->HomeOvers()->GetCount() or $result->AwayOvers()->GetCount();
 }
 private function HowManyOversInTheMatch()
 {
     # Get number of overs in match, going on the bowling data rather than the official match length because
     # a match may be cut short for light or extended for a friendly.
     $home_overs = $this->match->Result()->HomeOvers()->GetCount();
     $away_overs = $this->match->Result()->AwayOvers()->GetCount();
     $overs = $home_overs;
     if ($away_overs > $home_overs) {
         $overs = $away_overs;
     }
     return $overs;
 }
 function OnLoadPageData()
 {
     /* @var $match_manager MatchManager */
     # get id of Match
     $i_id = $this->match_manager->GetItemId();
     # Get details of match but, if invalid, don't replace submitted details with saved ones
     if ($i_id and $this->IsValid()) {
         $this->match_manager->ReadByMatchId(array($i_id));
         $this->match_manager->ExpandMatchScorecards();
         $this->match = $this->match_manager->GetFirst();
         if ($this->match instanceof Match) {
             $this->b_user_is_match_owner = AuthenticationManager::GetUser()->GetId() == $this->match->GetAddedBy()->GetId();
             $this->b_is_tournament = $this->match->GetMatchType() == MatchType::TOURNAMENT;
         }
     }
     unset($this->match_manager);
     # Tournament or match in the future or not played is page not found
     $editable_results = array(MatchResult::UNKNOWN, MatchResult::HOME_WIN, MatchResult::AWAY_WIN, MatchResult::TIE, MatchResult::ABANDONED);
     if (!$this->match instanceof Match or $this->b_is_tournament or $this->match->GetStartTime() > gmdate('U') or !in_array($this->match->Result()->GetResultType(), $editable_results)) {
         http_response_code(404);
         $this->page_not_found = true;
     }
 }
 /**
  * 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 $o_match
     * @desc Save the result and player(s) of the match to the database
     */
    public function SaveHighlights(Match $o_match)
    {
        # To add a result there must always already be a match to update
        if (!$o_match->GetId()) {
            return;
        }
        require_once "stoolball/player-manager.class.php";
        $player_manager = new PlayerManager($this->GetSettings(), $this->GetDataConnection());
        # build query
        $s_match = $this->GetSettings()->GetTable('Match');
        $statistics = $this->GetSettings()->GetTable('PlayerMatch');
        $i_result = $o_match->Result()->GetResultType() <= 0 ? null : $o_match->Result()->GetResultType();
        $player_of_match = $player_manager->SaveOrMatchPlayer($o_match->Result()->GetPlayerOfTheMatch());
        $player_of_match_home = $player_manager->SaveOrMatchPlayer($o_match->Result()->GetPlayerOfTheMatchHome());
        $player_of_match_away = $player_manager->SaveOrMatchPlayer($o_match->Result()->GetPlayerOfTheMatchAway());
        # Check whether anything's changed and don't re-save if not
        $s_sql = 'SELECT match_id FROM ' . $s_match . ' ';
        $s_where = $this->SqlAddCondition("", 'match_result_id' . Sql::ProtectNumeric($i_result, true, true));
        $s_where = $this->SqlAddCondition($s_where, 'player_of_match_id ' . Sql::ProtectNumeric($player_of_match, true, true));
        $s_where = $this->SqlAddCondition($s_where, 'player_of_match_home_id ' . Sql::ProtectNumeric($player_of_match_home, true, true));
        $s_where = $this->SqlAddCondition($s_where, 'player_of_match_away_id ' . Sql::ProtectNumeric($player_of_match_away, true, true));
        $s_where = $this->SqlAddCondition($s_where, 'match_id = ' . Sql::ProtectNumeric($o_match->GetId()));
        $s_sql = $this->SqlAddWhereClause($s_sql, $s_where);
        $o_result = $this->GetDataConnection()->query($s_sql);
        if ($o_result->fetch()) {
            return;
        }
        # Should the match_title be regenerated?
        $s_sql = "SELECT custom_title FROM {$s_match} WHERE {$s_match}.match_id = " . Sql::ProtectNumeric($o_match->GetId());
        $o_result = $this->GetDataConnection()->query($s_sql);
        $o_row = $o_result->fetch();
        if (!is_null($o_row)) {
            $o_match->SetUseCustomTitle($o_row->custom_title);
        }
        # Save IDs of players affected by any change
        $affected_players = array();
        if (!is_null($player_of_match)) {
            $affected_players[] = $player_of_match;
        }
        if (!is_null($player_of_match_home)) {
            $affected_players[] = $player_of_match_home;
        }
        if (!is_null($player_of_match_away)) {
            $affected_players[] = $player_of_match_away;
        }
        $s_sql = "SELECT player_of_match_id, player_of_match_home_id, player_of_match_away_id FROM {$s_match} WHERE {$s_match}.match_id = " . Sql::ProtectNumeric($o_match->GetId());
        $o_result = $this->GetDataConnection()->query($s_sql);
        $row = $o_result->fetch();
        if (!is_null($row)) {
            if (!is_null($row->player_of_match_id)) {
                $affected_players[] = $row->player_of_match_id;
            }
            if (!is_null($row->player_of_match_home_id)) {
                $affected_players[] = $row->player_of_match_home_id;
            }
            if (!is_null($row->player_of_match_away_id)) {
                $affected_players[] = $row->player_of_match_away_id;
            }
        }
        # Update the main match record
        # All changes from here to master data are logged, because this method can be called from the public interface
        $sql = "UPDATE {$s_match} SET ";
        if (!$o_match->GetUseCustomTitle()) {
            $sql .= "match_title = " . Sql::ProtectString($this->GetDataConnection(), $o_match->GetTitle()) . ", ";
        }
        $sql .= 'match_result_id = ' . Sql::ProtectNumeric($i_result, true) . ",\r\n\t\t\tplayer_of_match_id = " . Sql::ProtectNumeric($player_of_match, true) . ', ' . "player_of_match_home_id = " . Sql::ProtectNumeric($player_of_match_home, true) . ', ' . "player_of_match_away_id = " . Sql::ProtectNumeric($player_of_match_away, true) . ', 
			update_search = 1,  
            date_changed = ' . gmdate('U') . ", \r\n            modified_by_id = " . Sql::ProtectNumeric(AuthenticationManager::GetUser()->GetId()) . ' ' . 'WHERE match_id = ' . Sql::ProtectNumeric($o_match->GetId());
        $this->LoggedQuery($sql);
        # Copy updated match to statistics
        require_once 'stoolball/statistics/statistics-manager.class.php';
        $statistics_manager = new StatisticsManager($this->GetSettings(), $this->GetDataConnection());
        $statistics_manager->UpdateMatchDataInStatistics($this, $o_match->GetId());
        # Save IDs of players affected by any change
        if (count($affected_players)) {
            $statistics_manager->UpdatePlayerOfTheMatchStatistics($o_match->GetId());
            $statistics_manager->DeleteObsoleteStatistics($o_match->GetId());
            $statistics_manager->UpdatePlayerStatistics($affected_players);
        }
        unset($statistics_manager);
        # Match data has changed so notify moderator
        $this->QueueForNotification($o_match->GetId(), false);
    }
 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());
         }
     }
 }
 /**
  * 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);
 }
    /**
     * Helper to build and send the email when a match has been added by a public user
     *
     * @param Match $o_match
     * @param User $o_user
     * @param bool $b_is_new_match
     * @param bool $b_is_deleted_match
     * @param string $s_email
     * @param Season[] $seasons
     */
    private function SendMatchUpdatedEmail(Match $o_match, User $o_user, $b_is_new_match, $b_is_deleted_match, $s_email, $seasons = null)
    {
        # text of email
        $s_season_list = '';
        if (is_array($seasons)) {
            $i_total_seasons = count($seasons);
            for ($i = 0; $i < $i_total_seasons; $i++) {
                if ($i == 0) {
                    $s_season_list = "'" . $seasons[$i]->GetCompetitionName() . "'";
                } else {
                    if ($i == $i_total_seasons - 1) {
                        $s_season_list .= " and '" . $seasons[$i]->GetCompetitionName() . "'";
                    } else {
                        $s_season_list .= ", '" . $seasons[$i]->GetCompetitionName() . "'";
                    }
                }
            }
        }
        $s_season = $s_season_list ? " in the {$s_season_list}" : '';
        $s_why = $s_season_list ? $s_season_list : 'matches';
        $new = $b_is_new_match ? 'new ' : '';
        $verb = $b_is_new_match ? 'added' : 'updated';
        if ($b_is_deleted_match) {
            $verb = 'deleted';
        }
        $match_text = $o_match->GetMatchType() == MatchType::TOURNAMENT ? 'tournament' : 'match';
        $s_title = html_entity_decode($o_match->GetTitle());
        $s_date = ucfirst($o_match->GetStartTimeFormatted());
        $s_ground = is_object($o_match->GetGround()) ? $o_match->GetGround()->GetNameAndTown() : '';
        $s_notes = $o_match->GetNotes();
        $s_domain = $this->settings->GetDomain();
        $s_url = 'https://' . $s_domain . $o_match->GetNavigateUrl();
        $s_contact_url = 'https://' . $s_domain . $this->settings->GetFolder('Contact');
        $s_home_name = $o_match->GetMatchType() == MatchType::TOURNAMENT ? '' : html_entity_decode($o_match->GetHomeTeam()->GetName());
        $s_away_name = $o_match->GetMatchType() == MatchType::TOURNAMENT ? '' : html_entity_decode($o_match->GetAwayTeam()->GetName());
        $s_bat_first = is_null($o_match->Result()->GetHomeBattedFirst()) ? 'Not known which team batted first' : ($o_match->Result()->GetHomeBattedFirst() ? $s_home_name : $s_away_name) . ' batted first';
        $s_home_runs = is_null($o_match->Result()->GetHomeRuns()) ? '(not known)' : $o_match->Result()->GetHomeRuns();
        $s_home_wickets = is_null($o_match->Result()->GetHomeWickets()) ? '(not known)' : $o_match->Result()->GetHomeWickets();
        if ($s_home_wickets == -1) {
            $s_home_wickets = 'all out';
        } else {
            $s_home_wickets = 'for ' . $s_home_wickets . ' wickets';
        }
        $s_away_runs = is_null($o_match->Result()->GetAwayRuns()) ? '(not known)' : $o_match->Result()->GetAwayRuns();
        $s_away_wickets = is_null($o_match->Result()->GetAwayWickets()) ? '(not known)' : $o_match->Result()->GetAwayWickets();
        if ($s_away_wickets == -1) {
            $s_away_wickets = 'all out';
        } else {
            $s_away_wickets = 'for ' . $s_away_wickets . ' wickets';
        }
        $s_user = $o_user->GetName();
        $s_body = wordwrap("A {$new}{$match_text} has been {$verb} on the Stoolball England website at {$s_domain}{$s_season}.\n\n" . "The {$match_text} was {$verb} by {$s_user}.\n\n" . "The {$match_text} details are as follows:\n\n" . "    {$s_title}\n" . "    {$s_date}\n" . "    {$s_ground}");
        if ($s_notes) {
            $s_notes = "\n\n" . wordwrap($s_notes, 70);
            $s_notes = str_replace("\n", "\n    ", $s_notes);
            $s_body .= $s_notes;
        }
        if ($o_match->GetStartTime() <= gmdate('U') and !$b_is_new_match and $o_match->GetMatchType() != MatchType::TOURNAMENT) {
            $s_body .= <<<EMAILBODY


\t{$s_bat_first}
EMAILBODY;
            if ($o_match->Result()->GetHomeBattedFirst() === false) {
                $s_body .= <<<EMAILBODY

\t{$s_away_name} score: {$s_away_runs} runs {$s_away_wickets}
\t{$s_home_name} score: {$s_home_runs} runs {$s_home_wickets}
EMAILBODY;
            } else {
                $s_body .= <<<EMAILBODY

\t{$s_home_name} score: {$s_home_runs} runs {$s_home_wickets}
\t{$s_away_name} score: {$s_away_runs} runs {$s_away_wickets}
EMAILBODY;
            }
        }
        $s_body .= "\n\n";
        if (!$b_is_deleted_match) {
            $s_body .= wordwrap("You can view the {$match_text} at {$s_url}\n\n");
        }
        $s_body .= wordwrap("You have received this email because you are the administrative contact for {$s_why} on {$s_domain}.\n\n" . "We let you know when a {$match_text} is {$verb} by a member of the public, so that you can check there's nothing wrong.\n\n" . "If this email has been sent to the wrong address, or if the {$match_text} details are wrong, please let us know using the contact form at {$s_contact_url}.\n\n");
        # send email, copy to me
        require_once 'Zend/Mail.php';
        $o_email = new Zend_Mail('UTF-8');
        $o_email->addTo($s_email);
        $o_email->setFrom('*****@*****.**', 'Stoolball England alerts');
        $o_email->setSubject(ucfirst($match_text) . " {$verb}: {$s_title}, {$s_date}");
        $o_email->setBodyText($s_body);
        try {
            $o_email->send();
        } catch (Zend_Mail_Transport_Exception $e) {
            # Do nothing - failure to send this email should not be a fatal error
        }
    }
 private function AddDateClasses(Match $match, $i_next_match_day, XhtmlElement $li)
 {
     if ($match->GetStartTime()) {
         $i_now = gmdate('U');
         $i_two_hours_ago = gmmktime(gmdate('H', $i_now), gmdate('i', $i_now), 0, gmdate('m', $i_now), gmdate('d', $i_now), gmdate('Y', $i_now)) - 7200;
         $i_match_time = $match->GetStartTime();
         $i_match_day = gmmktime(12, 0, 0, gmdate('m', $i_match_time), gmdate('d', $i_match_time), gmdate('Y', $i_match_time));
         if ($i_match_time <= $i_two_hours_ago) {
             $li->AddCssClass('matchPlayed');
         } else {
             if (!$i_next_match_day) {
                 $i_next_match_day = $i_match_day;
             }
             if ($i_match_day == $i_next_match_day && !$match->Result()->GetResultType()) {
                 $li->AddCssClass('matchNext');
             }
         }
     }
     return $i_next_match_day;
 }
 /**
  * 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;
 }
 /**
  * Creates a bowling scorecard for one innings with as much data as is available
  * @param Match $match
  * @param bool $is_home_innings
  * @return void
  */
 private function CreateBowlingCard(Match $match, $is_home_innings)
 {
     $overs_data = $is_home_innings ? $match->Result()->AwayOvers() : $match->Result()->HomeOvers();
     $bowling_data = $is_home_innings ? $match->Result()->AwayBowling() : $match->Result()->HomeBowling();
     $bowling_team = $is_home_innings ? $match->GetAwayTeam() : $match->GetHomeTeam();
     # First, bowler's figures
     if ($bowling_data->GetCount()) {
         $bowling_table = new XhtmlTable();
         $bowling_table->SetCaption(htmlentities($bowling_team->GetName() . "'s bowlers", ENT_QUOTES, "UTF-8", false));
         $bowling_table->SetCssClass("bowling scorecard");
         $over_header = new XhtmlCell(true, '<abbr title="Overs" class="small">Ov</abbr><span class="large">Overs</span>');
         $over_header->SetCssClass("numeric");
         $maidens_header = new XhtmlCell(true, '<abbr title="Maiden overs" class="small">Md</abbr><abbr title="Maiden overs" class="large">Mdns</abbr>');
         $maidens_header->SetCssClass("numeric");
         $runs_header = new XhtmlCell(true, "Runs");
         $runs_header->SetCssClass("numeric");
         $wickets_header = new XhtmlCell(true, '<abbr title="Wickets" class="small">Wk</abbr><abbr title="Wickets" class="large">Wkts</abbr>');
         $wickets_header->SetCssClass("numeric");
         $economy_header = new XhtmlCell(true, '<abbr title="Economy" class="small">Econ</abbr><span class="large">Economy</span>');
         $economy_header->SetCssClass("numeric");
         $average_header = new XhtmlCell(true, '<abbr title="Average" class="small">Avg</abbr><span class="large">Average</span>');
         $average_header->SetCssClass("numeric");
         $strike_header = new XhtmlCell(true, '<abbr title="Strike rate" class="small">S/R</abbr><span class="large">Strike rate</span>');
         $strike_header->SetCssClass("numeric");
         $bowling_headings = new XhtmlRow(array("Bowler", $over_header, $maidens_header, $runs_header, $wickets_header, $economy_header, $average_header, $strike_header));
         $bowling_headings->SetIsHeader(true);
         $bowling_table->AddRow($bowling_headings);
         $bowling_data->ResetCounter();
         while ($bowling_data->MoveNext()) {
             $bowling = $bowling_data->GetItem();
             /* @var $bowling Bowling */
             $player = new XhtmlCell(false, '<a property="schema:name" rel="schema:url" href="' . htmlentities($bowling->GetPlayer()->GetPlayerUrl(), ENT_QUOTES, "UTF-8", false) . '">' . htmlentities($bowling->GetPlayer()->GetName(), ENT_QUOTES, "UTF-8", false) . '</a>');
             $player->AddCssClass("bowler");
             $player->AddAttribute("typeof", "schema:Person");
             $player->AddAttribute("about", $bowling->GetPlayer()->GetLinkedDataUri());
             $over_data = new XhtmlCell(false, htmlentities($bowling->GetOvers(), ENT_QUOTES, "UTF-8", false));
             $over_data->SetCssClass("numeric");
             $maidens_data = new XhtmlCell(false, htmlentities($bowling->GetMaidens(), ENT_QUOTES, "UTF-8", false));
             $maidens_data->SetCssClass("numeric");
             $runs_data = new XhtmlCell(false, htmlentities($bowling->GetRunsConceded(), ENT_QUOTES, "UTF-8", false));
             $runs_data->SetCssClass("numeric");
             $wickets_data = new XhtmlCell(false, htmlentities($bowling->GetWickets(), ENT_QUOTES, "UTF-8", false));
             $wickets_data->SetCssClass("numeric");
             $economy = StoolballStatistics::BowlingEconomy($bowling->GetOvers(), $bowling->GetRunsConceded());
             $economy_data = new XhtmlCell(false, is_null($economy) ? "&#8211;" : htmlentities($economy, ENT_QUOTES, "UTF-8", false));
             $economy_data->SetCssClass("numeric");
             $average = StoolballStatistics::BowlingAverage($bowling->GetRunsConceded(), $bowling->GetWickets());
             $average_data = new XhtmlCell(false, is_null($average) ? "&#8211;" : htmlentities($average, ENT_QUOTES, "UTF-8", false));
             $average_data->SetCssClass("numeric");
             $strike = StoolballStatistics::BowlingStrikeRate($bowling->GetOvers(), $bowling->GetWickets());
             $strike_data = new XhtmlCell(false, is_null($strike) ? "&#8211;" : htmlentities($strike, ENT_QUOTES, "UTF-8", false));
             $strike_data->SetCssClass("numeric");
             $bowling_row = new XhtmlRow(array($player, $over_data, $maidens_data, $runs_data, $wickets_data, $economy_data, $average_data, $strike_data));
             $bowling_row->GetFirstCell()->SetCssClass("bowler");
             $bowling_table->AddRow($bowling_row);
         }
         $this->AddControl($bowling_table);
     }
     # Now over-by-over
     if ($overs_data->GetCount()) {
         $overs_table = new XhtmlTable();
         $overs_table->SetCaption(htmlentities($bowling_team->GetName() . "'s bowling, over-by-over", ENT_QUOTES, "UTF-8", false));
         $overs_table->SetCssClass("scorecard bowling-scorecard bowling overs");
         $balls_header = new XhtmlCell(true, "Balls");
         $balls_header->SetCssClass("numeric");
         $wides_header = new XhtmlCell(true, "Wides");
         $wides_header->SetCssClass("numeric");
         $no_balls_header = new XhtmlCell(true, "No balls");
         $no_balls_header->SetCssClass("numeric");
         $runs_in_over_header = new XhtmlCell(true, "Runs");
         $runs_in_over_header->SetCssClass("numeric");
         $total_header = new XhtmlCell(true, "Total");
         $total_header->SetCssClass("numeric");
         $overs_headings = new XhtmlRow(array("Bowler", $balls_header, $wides_header, $no_balls_header, $runs_in_over_header, $total_header));
         $overs_headings->SetIsHeader(true);
         $overs_table->AddRow($overs_headings);
         $overs_data->ResetCounter();
         $total = 0;
         while ($overs_data->MoveNext()) {
             $bowling = $overs_data->GetItem();
             /* @var $bowling Over */
             $player = new XhtmlCell(false, '<a property="schema:name" rel="schema:url" href="' . htmlentities($bowling->GetPlayer()->GetPlayerUrl(), ENT_QUOTES, "UTF-8", false) . '">' . htmlentities($bowling->GetPlayer()->GetName(), ENT_QUOTES, "UTF-8", false) . '</a>');
             $player->AddCssClass("bowler");
             $player->AddAttribute("typeof", "schema:Person");
             $player->AddAttribute("about", $bowling->GetPlayer()->GetLinkedDataUri());
             $balls_data = new XhtmlCell(false, htmlentities($bowling->GetBalls(), ENT_QUOTES, "UTF-8", false));
             $balls_data->SetCssClass("numeric");
             $wides_data = new XhtmlCell(false, htmlentities($bowling->GetWides(), ENT_QUOTES, "UTF-8", false));
             $wides_data->SetCssClass("numeric");
             $no_balls_data = new XhtmlCell(false, htmlentities($bowling->GetNoBalls(), ENT_QUOTES, "UTF-8", false));
             $no_balls_data->SetCssClass("numeric");
             $runs_in_over_data = new XhtmlCell(false, htmlentities($bowling->GetRunsInOver(), ENT_QUOTES, "UTF-8", false));
             $runs_in_over_data->SetCssClass("numeric");
             $total += $bowling->GetRunsInOver();
             $total_data = new XhtmlCell(false, htmlentities($total, ENT_QUOTES, "UTF-8", false));
             $total_data->SetCssClass("numeric");
             $bowling_row = new XhtmlRow(array($player, $balls_data, $wides_data, $no_balls_data, $runs_in_over_data, $total_data));
             $bowling_row->GetFirstCell()->SetCssClass("bowler");
             $overs_table->AddRow($bowling_row);
         }
         $this->AddControl($overs_table);
     }
 }
 /**
  * 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;
 }