409 lines
17 KiB
PHP
409 lines
17 KiB
PHP
<?php
|
|
|
|
class UserActivityService
|
|
{
|
|
private PDO $pdo;
|
|
private string $schema;
|
|
private array $tableCache = [];
|
|
private array $columnsCache = [];
|
|
|
|
public function __construct(PDO $pdo)
|
|
{
|
|
$this->pdo = $pdo;
|
|
$this->schema = (string)$this->pdo->query('SELECT DATABASE()')->fetchColumn();
|
|
}
|
|
|
|
public function getMyMatches(int $userId): array
|
|
{
|
|
if (!$this->hasTable('matches')) {
|
|
return [];
|
|
}
|
|
|
|
$matchesColumns = $this->getColumns('matches');
|
|
|
|
$idCol = $this->pickColumn($matchesColumns, ['ID', 'id', 'match_id']);
|
|
$team1Col = $this->pickColumn($matchesColumns, ['Team1_ID', 'team1_id']);
|
|
$team2Col = $this->pickColumn($matchesColumns, ['Team2_ID', 'team2_id']);
|
|
$startCol = $this->pickColumn($matchesColumns, ['StartTime', 'start_time', 'date', 'match_date']);
|
|
$statusCol = $this->pickColumn($matchesColumns, ['Status', 'status']);
|
|
$scoreCol = $this->pickColumn($matchesColumns, ['Score', 'score', 'result']);
|
|
$participantsCol = $this->pickColumn($matchesColumns, ['Participants', 'participants', 'user_ids', 'player_ids']);
|
|
$leagueNameCol = $this->pickColumn($matchesColumns, ['LeagueName', 'league_name', 'league', 'League']);
|
|
$matchTypeCol = $this->pickColumn($matchesColumns, ['MatchType', 'match_type']);
|
|
|
|
if (!$idCol) {
|
|
return [];
|
|
}
|
|
|
|
$select = ["m.`{$idCol}` AS match_id"];
|
|
if ($team1Col) {
|
|
$select[] = "m.`{$team1Col}` AS team1_id";
|
|
}
|
|
if ($team2Col) {
|
|
$select[] = "m.`{$team2Col}` AS team2_id";
|
|
}
|
|
if ($startCol) {
|
|
$select[] = "m.`{$startCol}` AS match_date";
|
|
}
|
|
if ($statusCol) {
|
|
$select[] = "m.`{$statusCol}` AS match_status";
|
|
}
|
|
if ($scoreCol) {
|
|
$select[] = "m.`{$scoreCol}` AS match_score";
|
|
}
|
|
if ($leagueNameCol) {
|
|
$select[] = "m.`{$leagueNameCol}` AS league_name";
|
|
}
|
|
if ($matchTypeCol) {
|
|
$select[] = "m.`{$matchTypeCol}` AS match_type";
|
|
}
|
|
if ($participantsCol) {
|
|
$select[] = "m.`{$participantsCol}` AS participants_raw";
|
|
}
|
|
|
|
$teamIds = $this->resolveUserTeamIds($userId);
|
|
$where = [];
|
|
$params = [':user_id' => $userId];
|
|
|
|
if ($team1Col && $team2Col) {
|
|
$teamChecks = ['(m.`' . $team1Col . '` = :user_id OR m.`' . $team2Col . '` = :user_id)'];
|
|
foreach ($teamIds as $index => $teamId) {
|
|
$key = ':team_' . $index;
|
|
$params[$key] = $teamId;
|
|
$teamChecks[] = '(m.`' . $team1Col . '` = ' . $key . ' OR m.`' . $team2Col . '` = ' . $key . ')';
|
|
}
|
|
$where[] = '(' . implode(' OR ', $teamChecks) . ')';
|
|
}
|
|
|
|
if ($participantsCol) {
|
|
$where[] = "CONCAT(',', REPLACE(REPLACE(REPLACE(COALESCE(m.`{$participantsCol}`, ''), '[', ''), ']', ''), ' ', ''), ',') LIKE :participant_like";
|
|
$params[':participant_like'] = '%,' . $userId . ',%';
|
|
}
|
|
|
|
if (empty($where)) {
|
|
return [];
|
|
}
|
|
|
|
$orderBy = $startCol ? "m.`{$startCol}` DESC" : "m.`{$idCol}` DESC";
|
|
$sql = 'SELECT ' . implode(', ', $select) . ' FROM `matches` m WHERE ' . implode(' OR ', $where) . ' ORDER BY ' . $orderBy . ' LIMIT 500';
|
|
$stmt = $this->pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$result = [];
|
|
foreach ($rows as $row) {
|
|
$opponent = '';
|
|
if (isset($row['team1_id'], $row['team2_id'])) {
|
|
$team1Id = (int)$row['team1_id'];
|
|
$team2Id = (int)$row['team2_id'];
|
|
$opponentTeamId = $team1Id === $userId ? $team2Id : $team1Id;
|
|
if (in_array($team1Id, $teamIds, true)) {
|
|
$opponentTeamId = $team2Id;
|
|
}
|
|
if (in_array($team2Id, $teamIds, true)) {
|
|
$opponentTeamId = $team1Id;
|
|
}
|
|
$opponent = $opponentTeamId > 0 ? 'Drużyna #' . $opponentTeamId : '';
|
|
}
|
|
|
|
$result[] = [
|
|
'match_id' => (int)$row['match_id'],
|
|
'opponent' => $opponent,
|
|
'date' => !empty($row['match_date']) ? gmdate('Y-m-d\\TH:i:s\\Z', strtotime((string)$row['match_date'])) : null,
|
|
'status' => $this->normalizeStatus($row['match_status'] ?? ''),
|
|
'score' => $row['match_score'] ?? '',
|
|
'league' => $row['league_name'] ?? ($row['match_type'] ?? '')
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getMyTournaments(int $userId): array
|
|
{
|
|
if (!$this->hasTable('tournaments')) {
|
|
return [];
|
|
}
|
|
|
|
$tColumns = $this->getColumns('tournaments');
|
|
|
|
$idCol = $this->pickColumn($tColumns, ['id', 'ID', 'tournament_id']);
|
|
$nameCol = $this->pickColumn($tColumns, ['name', 'title', 'tournament_name']);
|
|
$startDateCol = $this->pickColumn($tColumns, ['start_date', 'startDate', 'start_time', 'created_at']);
|
|
$statusCol = $this->pickColumn($tColumns, ['status', 'state']);
|
|
$playedCol = $this->pickColumn($tColumns, ['matches_played', 'played_matches']);
|
|
$totalCol = $this->pickColumn($tColumns, ['total_matches', 'matches_total', 'matches_count']);
|
|
|
|
if (!$idCol) {
|
|
return [];
|
|
}
|
|
|
|
$membership = $this->resolveMembership('tournament');
|
|
$rows = [];
|
|
|
|
if ($membership !== null) {
|
|
$sql = "SELECT
|
|
t.`{$idCol}` AS tournament_id,
|
|
" . ($nameCol ? "t.`{$nameCol}`" : "''") . " AS tournament_name,
|
|
" . ($startDateCol ? "t.`{$startDateCol}`" : "NULL") . " AS start_date,
|
|
" . ($statusCol ? "t.`{$statusCol}`" : "''") . " AS tournament_status,
|
|
" . ($playedCol ? "COALESCE(t.`{$playedCol}`, 0)" : '0') . " AS matches_played,
|
|
" . ($totalCol ? "COALESCE(t.`{$totalCol}`, 0)" : '0') . " AS total_matches
|
|
FROM `{$membership['table']}` rel
|
|
INNER JOIN `tournaments` t ON t.`{$idCol}` = rel.`{$membership['entityColumn']}`
|
|
WHERE rel.`{$membership['userColumn']}` = :user_id
|
|
ORDER BY tournament_id DESC
|
|
LIMIT 500";
|
|
|
|
$stmt = $this->pdo->prepare($sql);
|
|
$stmt->execute([':user_id' => $userId]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} else {
|
|
$participantsCol = $this->pickColumn($tColumns, ['participants', 'user_ids', 'player_ids']);
|
|
if (!$participantsCol) {
|
|
return [];
|
|
}
|
|
|
|
$sql = "SELECT
|
|
t.`{$idCol}` AS tournament_id,
|
|
" . ($nameCol ? "t.`{$nameCol}`" : "''") . " AS tournament_name,
|
|
" . ($startDateCol ? "t.`{$startDateCol}`" : "NULL") . " AS start_date,
|
|
" . ($statusCol ? "t.`{$statusCol}`" : "''") . " AS tournament_status,
|
|
" . ($playedCol ? "COALESCE(t.`{$playedCol}`, 0)" : '0') . " AS matches_played,
|
|
" . ($totalCol ? "COALESCE(t.`{$totalCol}`, 0)" : '0') . " AS total_matches
|
|
FROM `tournaments` t
|
|
WHERE CONCAT(',', REPLACE(REPLACE(REPLACE(COALESCE(t.`{$participantsCol}`, ''), '[', ''), ']', ''), ' ', ''), ',') LIKE :participant_like
|
|
ORDER BY tournament_id DESC
|
|
LIMIT 500";
|
|
|
|
$stmt = $this->pdo->prepare($sql);
|
|
$stmt->execute([':participant_like' => '%,' . $userId . ',%']);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
return array_map(function (array $row): array {
|
|
return [
|
|
'tournament_id' => (int)$row['tournament_id'],
|
|
'name' => (string)($row['tournament_name'] ?? ''),
|
|
'start_date' => !empty($row['start_date']) ? substr((string)$row['start_date'], 0, 10) : null,
|
|
'status' => $this->normalizeStatus($row['tournament_status'] ?? ''),
|
|
'matches_played' => (int)($row['matches_played'] ?? 0),
|
|
'total_matches' => (int)($row['total_matches'] ?? 0)
|
|
];
|
|
}, $rows);
|
|
}
|
|
|
|
public function getMyLeagues(int $userId): array
|
|
{
|
|
if (!$this->hasTable('leagues')) {
|
|
return [];
|
|
}
|
|
|
|
$lColumns = $this->getColumns('leagues');
|
|
|
|
$idCol = $this->pickColumn($lColumns, ['id', 'ID', 'league_id']);
|
|
$nameCol = $this->pickColumn($lColumns, ['name', 'title', 'league_name']);
|
|
$seasonCol = $this->pickColumn($lColumns, ['season', 'season_name']);
|
|
$rankCol = $this->pickColumn($lColumns, ['rank', 'tier', 'division']);
|
|
$statusCol = $this->pickColumn($lColumns, ['status', 'state']);
|
|
$playedCol = $this->pickColumn($lColumns, ['matches_played', 'played_matches']);
|
|
$pointsCol = $this->pickColumn($lColumns, ['points', 'score_points']);
|
|
|
|
if (!$idCol) {
|
|
return [];
|
|
}
|
|
|
|
$membership = $this->resolveMembership('league');
|
|
$rows = [];
|
|
|
|
if ($membership !== null) {
|
|
$sql = "SELECT
|
|
l.`{$idCol}` AS league_id,
|
|
" . ($nameCol ? "l.`{$nameCol}`" : "''") . " AS league_name,
|
|
" . ($seasonCol ? "l.`{$seasonCol}`" : "''") . " AS season_name,
|
|
" . ($rankCol ? "l.`{$rankCol}`" : "''") . " AS league_rank,
|
|
" . ($statusCol ? "l.`{$statusCol}`" : "''") . " AS league_status,
|
|
" . ($playedCol ? "COALESCE(l.`{$playedCol}`, 0)" : '0') . " AS matches_played,
|
|
" . ($pointsCol ? "COALESCE(l.`{$pointsCol}`, 0)" : '0') . " AS points_total
|
|
FROM `{$membership['table']}` rel
|
|
INNER JOIN `leagues` l ON l.`{$idCol}` = rel.`{$membership['entityColumn']}`
|
|
WHERE rel.`{$membership['userColumn']}` = :user_id
|
|
ORDER BY league_id DESC
|
|
LIMIT 500";
|
|
|
|
$stmt = $this->pdo->prepare($sql);
|
|
$stmt->execute([':user_id' => $userId]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} else {
|
|
$participantsCol = $this->pickColumn($lColumns, ['participants', 'user_ids', 'player_ids']);
|
|
if (!$participantsCol) {
|
|
return [];
|
|
}
|
|
|
|
$sql = "SELECT
|
|
l.`{$idCol}` AS league_id,
|
|
" . ($nameCol ? "l.`{$nameCol}`" : "''") . " AS league_name,
|
|
" . ($seasonCol ? "l.`{$seasonCol}`" : "''") . " AS season_name,
|
|
" . ($rankCol ? "l.`{$rankCol}`" : "''") . " AS league_rank,
|
|
" . ($statusCol ? "l.`{$statusCol}`" : "''") . " AS league_status,
|
|
" . ($playedCol ? "COALESCE(l.`{$playedCol}`, 0)" : '0') . " AS matches_played,
|
|
" . ($pointsCol ? "COALESCE(l.`{$pointsCol}`, 0)" : '0') . " AS points_total
|
|
FROM `leagues` l
|
|
WHERE CONCAT(',', REPLACE(REPLACE(REPLACE(COALESCE(l.`{$participantsCol}`, ''), '[', ''), ']', ''), ' ', ''), ',') LIKE :participant_like
|
|
ORDER BY league_id DESC
|
|
LIMIT 500";
|
|
|
|
$stmt = $this->pdo->prepare($sql);
|
|
$stmt->execute([':participant_like' => '%,' . $userId . ',%']);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
return array_map(function (array $row): array {
|
|
return [
|
|
'league_id' => (int)$row['league_id'],
|
|
'name' => (string)($row['league_name'] ?? ''),
|
|
'season' => (string)($row['season_name'] ?? ''),
|
|
'rank' => (string)($row['league_rank'] ?? ''),
|
|
'status' => $this->normalizeStatus($row['league_status'] ?? ''),
|
|
'matches_played' => (int)($row['matches_played'] ?? 0),
|
|
'points' => (int)($row['points_total'] ?? 0)
|
|
];
|
|
}, $rows);
|
|
}
|
|
|
|
private function resolveUserTeamIds(int $userId): array
|
|
{
|
|
$candidates = [
|
|
['table' => 'team_members', 'team' => 'team_id', 'user' => 'user_id'],
|
|
['table' => 'teams_users', 'team' => 'team_id', 'user' => 'user_id'],
|
|
['table' => 'user_teams', 'team' => 'team_id', 'user' => 'user_id'],
|
|
['table' => 'team_user', 'team' => 'team_id', 'user' => 'user_id']
|
|
];
|
|
|
|
foreach ($candidates as $candidate) {
|
|
if (!$this->hasTable($candidate['table'])) {
|
|
continue;
|
|
}
|
|
|
|
$columns = $this->getColumns($candidate['table']);
|
|
if (!in_array($candidate['team'], $columns, true) || !in_array($candidate['user'], $columns, true)) {
|
|
continue;
|
|
}
|
|
|
|
$stmt = $this->pdo->prepare('SELECT `' . $candidate['team'] . '` FROM `' . $candidate['table'] . '` WHERE `' . $candidate['user'] . '` = :user_id');
|
|
$stmt->execute([':user_id' => $userId]);
|
|
$ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
|
|
$ids = array_values(array_unique(array_map('intval', $ids)));
|
|
return array_values(array_filter($ids, fn($id) => $id > 0));
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
private function resolveMembership(string $entity): ?array
|
|
{
|
|
$map = [
|
|
'tournament' => [
|
|
['table' => 'tournament_members', 'entity' => 'tournament_id', 'user' => 'user_id'],
|
|
['table' => 'tournaments_users', 'entity' => 'tournament_id', 'user' => 'user_id'],
|
|
['table' => 'user_tournaments', 'entity' => 'tournament_id', 'user' => 'user_id'],
|
|
['table' => 'tournament_participants', 'entity' => 'tournament_id', 'user' => 'user_id']
|
|
],
|
|
'league' => [
|
|
['table' => 'league_members', 'entity' => 'league_id', 'user' => 'user_id'],
|
|
['table' => 'leagues_users', 'entity' => 'league_id', 'user' => 'user_id'],
|
|
['table' => 'user_leagues', 'entity' => 'league_id', 'user' => 'user_id'],
|
|
['table' => 'league_participants', 'entity' => 'league_id', 'user' => 'user_id']
|
|
]
|
|
];
|
|
|
|
if (!isset($map[$entity])) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($map[$entity] as $candidate) {
|
|
if (!$this->hasTable($candidate['table'])) {
|
|
continue;
|
|
}
|
|
|
|
$columns = $this->getColumns($candidate['table']);
|
|
if (!in_array($candidate['entity'], $columns, true) || !in_array($candidate['user'], $columns, true)) {
|
|
continue;
|
|
}
|
|
|
|
return [
|
|
'table' => $candidate['table'],
|
|
'entityColumn' => $candidate['entity'],
|
|
'userColumn' => $candidate['user']
|
|
];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function hasTable(string $table): bool
|
|
{
|
|
if (array_key_exists($table, $this->tableCache)) {
|
|
return $this->tableCache[$table];
|
|
}
|
|
|
|
$stmt = $this->pdo->prepare('SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = :schema AND table_name = :table');
|
|
$stmt->execute([
|
|
':schema' => $this->schema,
|
|
':table' => $table
|
|
]);
|
|
|
|
$exists = (int)$stmt->fetchColumn() > 0;
|
|
$this->tableCache[$table] = $exists;
|
|
|
|
return $exists;
|
|
}
|
|
|
|
private function getColumns(string $table): array
|
|
{
|
|
if (isset($this->columnsCache[$table])) {
|
|
return $this->columnsCache[$table];
|
|
}
|
|
|
|
if (!$this->hasTable($table)) {
|
|
$this->columnsCache[$table] = [];
|
|
return [];
|
|
}
|
|
|
|
$stmt = $this->pdo->prepare('SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table');
|
|
$stmt->execute([
|
|
':schema' => $this->schema,
|
|
':table' => $table
|
|
]);
|
|
|
|
$columns = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
$this->columnsCache[$table] = is_array($columns) ? $columns : [];
|
|
|
|
return $this->columnsCache[$table];
|
|
}
|
|
|
|
private function pickColumn(array $columns, array $candidates): ?string
|
|
{
|
|
foreach ($candidates as $candidate) {
|
|
if (in_array($candidate, $columns, true)) {
|
|
return $candidate;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function normalizeStatus(string $status): string
|
|
{
|
|
$status = mb_strtolower(trim($status));
|
|
|
|
return match ($status) {
|
|
'planned', 'planowany', 'zaplanowany' => 'zaplanowany',
|
|
'live', 'ongoing', 'trwający', 'in_progress' => 'trwający',
|
|
'end', 'ended', 'finished', 'zakończony' => 'zakończony',
|
|
default => $status
|
|
};
|
|
}
|
|
}
|