public function OnLoadPageData()
 {
     $player_manager = new PlayerManager($this->GetSettings(), $this->GetDataConnection());
     $player_manager->ReadPlayersInTeam(array($this->team->GetId()));
     $this->players = $player_manager->GetItems();
     unset($player_manager);
     if (count($this->players)) {
         $this->team = $this->players[0]->Team();
     }
 }
    public function OnLoadPageData()
    {
        # Read all the players from all specified teams
        require_once "stoolball/player-manager.class.php";
        $player_manager = new PlayerManager($this->GetSettings(), $this->GetDataConnection());
        $player_manager->ReadPlayersForAutocomplete($this->team_ids);
        $players = $player_manager->GetItems();
        unset($player_manager);
        if (count($players)) {
            # Sort player names into team-by-team array
            $player_data_by_team = array();
            $team_by_player_name = array();
            foreach ($players as $player) {
                /* @var $player Player */
                # Remember the teams each name is in
                $escaped_name = str_replace("'", "\\'", Html::Encode($player->GetName()));
                # escape single quotes because this will become JS string
                if (!array_key_exists($escaped_name, $team_by_player_name)) {
                    $team_by_player_name[$escaped_name] = array();
                }
                $team_by_player_name[$escaped_name][] = $player->Team()->GetId();
                # Build up the data to display in the autocomplete dropdown
                if (!array_key_exists($player->Team()->GetId(), $player_data_by_team)) {
                    $player_data_by_team[$player->Team()->GetId()] = array();
                }
                $prompt_start = " (";
                if ($player->GetTotalMatches() == 1) {
                    $prompt_start .= "1 match";
                } else {
                    if ($player->GetTotalMatches() > 1) {
                        $prompt_start .= Html::Encode($player->GetTotalMatches() . " matches");
                    }
                }
                $prompt_team = Html::Encode(" for " . $player->Team()->GetName());
                $prompt_end = "";
                if ($player->GetFirstPlayedDate()) {
                    $first_year = gmdate("Y", $player->GetFirstPlayedDate());
                    $last_year = gmdate("Y", $player->GetLastPlayedDate());
                    $prompt_end .= " " . $first_year;
                    if ($first_year != $last_year) {
                        $prompt_end .= "–" . gmdate("y", $player->GetLastPlayedDate());
                    }
                }
                $prompt_end .= ")";
                $player_data_by_team[$player->Team()->GetId()][] = "{label:\"" . $escaped_name . "\",dates:\"" . str_replace("'", "\\'", $prompt_start . $prompt_end) . "\",team:\"" . str_replace("'", "\\'", $prompt_start . $prompt_team . $prompt_end) . "\"}";
                # escape single quotes for JS string
            }
            # Write those names as a JS array
            ?>
var stoolballAutoSuggest = (function() {

	var playersByTeam = [<?php 
            echo implode(",", $this->team_ids);
            ?>
];
	var teamsByPlayer = [];
<?php 
            foreach ($player_data_by_team as $team_id => $player_data) {
                echo "\tplayersByTeam[{$team_id}] = [" . implode(",", $player_data) . "];\n";
            }
            foreach ($team_by_player_name as $player_name => $team_ids) {
                echo "\tteamsByPlayer['{$player_name}'] = ['" . implode("','", $team_ids) . "'];\n";
            }
            ?>

	function enableSuggestions()
	{
		// find out which team(s) the player could come from
		var classes = this.className.split(" ");
		var suggestions = [];
		var showTeam = false;

		for (key in classes)
		{
			if (classes[key].match(/^team[0-9]+$/))
			{
				var players = playersByTeam[classes[key].substring(4)];
				if (typeof players == 'undefined') continue;

				if (suggestions.length > 0) showTeam = true;
				suggestions = suggestions.concat(players);
			}
		}

		// hook up the autocomplete to work with just the player's name, not their supporting info
		var input = $(this);
		if (!input.hasClass("autocomplete"))
		{
			input.autocomplete({source:suggestions}).data( "autocomplete" )._renderItem = function( ul, item ) {
				return $( "<li></li>" )
					.data( "item.autocomplete", item )
					.append(showTeam ? "<a>" + item.label + " " + item.team + "</a>" : "<a>" + item.label + " " + item.dates + "</a>" )
					.appendTo( ul )};
			input.change(selectTeamForPlayer).blur(addPlayerSuggestion);
		}
		else
		{
			input.autocomplete("option","source",suggestions);
		}
	}

	function selectTeamForPlayer(e)
   	{
   		// first, get value from "this" while it refers to the textbox
		var playerName = $.trim(this.value);

   		// if the next control selects the player's team (ie: player of the match), try to match it automatically.
		$("select.playerTeam", this.parentNode).each(function()
		{
			// expecting "don't know", "home" and "away"
			if (this.options.length == 3)
			{
				if (playerName.length == 0)
				{
					this.options[0].selected = true;
					return;
				}

				// see if there's a matching player name
				var teams = teamsByPlayer[playerName];
				if (typeof teams == 'undefined') return;

				// are they in the available teams?
				var couldBeHome = false;
				var couldBeAway = false;
				for (key in teams)
				{
					if (teams[key] == this.options[1].value) couldBeHome = true;
					if (teams[key] == this.options[2].value) couldBeAway = true;
				}

				// select only if sure which one it is
				if (couldBeHome && !couldBeAway) this.options[1].selected = true;
				if (!couldBeHome && couldBeAway) this.options[2].selected = true;
			}
		});
   	}

   	function addPlayerSuggestion(e)
   	{
		// if box blank, no new player
		this.value = $.trim(this.value);
		if (this.value.length == 0) return;

		// Identify teams associated with this box
		var classes = this.className.split(" ");
		var teamIds = [];

		for (key in classes)
		{
			if (classes[key].match(/^team[0-9]+$/))
			{
				teamIds[teamIds.length] = classes[key].substring(4);
			}
		}

		// see if any of those teams do not currently contain this player
		for (var i = 0; i < teamIds.length; i++)
		{
			// get array of players for the team
			var players = playersByTeam[teamIds[i]];
			if (typeof players == 'undefined') players = playersByTeam[teamIds[i]] = [];

			var newPlayer = true;
			var len = players.length;
			for (var j = 0; j < len; j++)
			{
				if (players[j].label == this.value)
				{
					newPlayer = false;
					break;
				}
			}

			if (newPlayer)
			{
				// Add the new player
				playersByTeam[teamIds[i]].unshift({label: this.value, dates:" (this match)",team:" (this match)"});
				teamsByPlayer[players[j].value] = [teamIds[i]];

				// Remove and re-connect autocomplete
				$("input.player.team" + teamIds[i], "form").each(enableSuggestions);
			}
		}
   	}
   	
   	return { enablePlayerSuggestions: enableSuggestions };
})();
$(function() {
    
    // find anywhere a player's name should be entered
    $("input.player", "form").each(stoolballAutoSuggest.enablePlayerSuggestions);

});
			<?php 
        }
        exit;
    }
 private function IndexPlayers()
 {
     require_once "data/process-manager.class.php";
     $this->process = new ProcessManager("players", 500);
     if ($this->process->ReadyToDeleteAll()) {
         $this->SearchIndexer()->DeleteFromIndexByType("player");
     }
     # Get all players, but exclude unused extras
     $player = $this->GetSettings()->GetTable('Player');
     $player_batch = $this->GetDataConnection()->query("SELECT player_id FROM {$player} WHERE total_matches >= 1 ORDER BY player_id" . $this->process->GetQueryLimit());
     $player_ids = array();
     while ($row = $player_batch->fetch()) {
         $player_ids[] = $row->player_id;
     }
     if (count($player_ids)) {
         require_once 'stoolball/player-manager.class.php';
         require_once 'search/player-search-adapter.class.php';
         $manager = new PlayerManager($this->GetSettings(), $this->GetDataConnection());
         foreach ($player_ids as $player_id) {
             $manager->ReadPlayerById($player_id);
             $players = $manager->GetItems();
             foreach ($players as $player) {
                 $adapter = new PlayerSearchAdapter($player);
                 $this->SearchIndexer()->Index($adapter->GetSearchableItem());
                 $this->process->OneMoreDone();
             }
         }
         $this->SearchIndexer()->CommitChanges();
         unset($manager);
     }
 }
 /**
  * @access public
  * @return void
  * @param int[] $a_ids
  * @desc Delete from the db the Teams matching the supplied ids
  */
 public function Delete($a_ids)
 {
     # check parameter
     $this->ValidateNumericArray($a_ids);
     if (!count($a_ids)) {
         throw new Exception('No teams to delete');
     }
     $s_ids = join(', ', $a_ids);
     # Get more information on the teams
     $teams = array();
     $s_sql = "SELECT team_id, short_url, owner_role_id FROM nsa_team WHERE team_id IN ({$s_ids})";
     $result = $this->GetDataConnection()->query($s_sql);
     while ($row = $result->fetch()) {
         $team = new Team($this->GetSettings());
         $team->SetId($row->team_id);
         $team->SetShortUrl($row->short_url);
         $team->SetOwnerRoleId($row->owner_role_id);
         $teams[] = $team;
     }
     $result->closeCursor();
     # Check that current user is an admin or a team owner
     require_once "authentication/authentication-manager.class.php";
     $user = AuthenticationManager::GetUser();
     foreach ($teams as $team) {
         /* @var $team Team */
         if (!$user->Permissions()->HasPermission(PermissionType::MANAGE_TEAMS, $team->GetLinkedDataUri())) {
             throw new Exception("Unauthorised");
         }
     }
     # delete owner role
     $authentication_manager = new AuthenticationManager($this->GetSettings(), $this->GetDataConnection(), null);
     foreach ($teams as $team) {
         /* @var $team Team */
         if ($team->GetOwnerRoleId()) {
             $authentication_manager->DeleteRole($team->GetOwnerRoleId());
         }
     }
     unset($authentication_manager);
     # delete from short URL cache
     require_once 'http/short-url-manager.class.php';
     $o_url_manager = new ShortUrlManager($this->GetSettings(), $this->GetDataConnection());
     foreach ($teams as $team) {
         /* @var $team Team */
         $o_url_manager->Delete($team->GetShortUrl());
     }
     unset($o_url_manager);
     # Delete relationships to matches
     $s_match_link = $this->GetSettings()->GetTable('MatchTeam');
     $s_sql = 'DELETE FROM ' . $s_match_link . ' WHERE team_id IN (' . $s_ids . ') ';
     $this->GetDataConnection()->query($s_sql);
     # Delete relationships to competitions
     $s_season_link = $this->GetSettings()->GetTable('TeamSeason');
     $s_sql = 'DELETE FROM ' . $s_season_link . ' WHERE team_id IN (' . $s_ids . ') ';
     $this->GetDataConnection()->query($s_sql);
     # Delete players
     require_once "player-manager.class.php";
     $player_manager = new PlayerManager($this->GetSettings(), $this->GetDataConnection());
     $player_manager->ReadPlayersInTeam($a_ids);
     $players = $player_manager->GetItems();
     if (count($players)) {
         $player_ids = array();
         foreach ($players as $player) {
             $player_ids[] = $player->GetId();
         }
         $player_manager->Delete($player_ids);
     }
     unset($player_manager);
     # delete team(s)
     $s_sql = 'DELETE FROM nsa_team WHERE team_id IN (' . $s_ids . ') ';
     $this->GetDataConnection()->query($s_sql);
     return $this->GetDataConnection()->GetAffectedRows();
 }