194 lines
7.6 KiB
PHP
194 lines
7.6 KiB
PHP
<?php
|
|
ob_start();
|
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/session_bootstrap.php';
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
// Admin only
|
|
if (empty($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true
|
|
|| empty($_SESSION['role']) || $_SESSION['role'] !== 'admin') {
|
|
ob_clean();
|
|
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
$pdo = og_session_get_pdo();
|
|
if (!$pdo) {
|
|
ob_clean();
|
|
echo json_encode(['success' => false, 'error' => 'DB unavailable']);
|
|
exit;
|
|
}
|
|
|
|
// ── Auto-create match_results if missing ─────────────────────────────────────
|
|
try {
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS match_results (
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
match_key VARCHAR(100) NOT NULL DEFAULT '',
|
|
match_id BIGINT UNSIGNED NULL,
|
|
discipline VARCHAR(50) NOT NULL DEFAULT '',
|
|
mode VARCHAR(50) NOT NULL DEFAULT '1v1',
|
|
winner_user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
|
loser_user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
|
winner_username VARCHAR(100) NOT NULL DEFAULT '',
|
|
loser_username VARCHAR(100) NOT NULL DEFAULT '',
|
|
score VARCHAR(200) NOT NULL DEFAULT '',
|
|
sets_winner TINYINT NOT NULL DEFAULT 0,
|
|
sets_loser TINYINT NOT NULL DEFAULT 0,
|
|
reason VARCHAR(50) NOT NULL DEFAULT '',
|
|
ended_at DATETIME NULL,
|
|
payload_json LONGTEXT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE KEY uniq_match_key (discipline, mode, match_key),
|
|
INDEX idx_winner (winner_user_id),
|
|
INDEX idx_loser (loser_user_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
|
} catch (Exception $e) {
|
|
// table may already exist with different schema -- ignore
|
|
}
|
|
|
|
// ── Check which optional columns exist in matches ────────────────────────────
|
|
function matchesHasColumn(PDO $pdo, string $col): bool {
|
|
static $cache = [];
|
|
if (!isset($cache[$col])) {
|
|
$cache[$col] = (int)$pdo->query(
|
|
"SELECT COUNT(*) FROM information_schema.columns
|
|
WHERE table_schema = DATABASE() AND table_name = 'matches' AND column_name = " . $pdo->quote($col)
|
|
)->fetchColumn() > 0;
|
|
}
|
|
return $cache[$col];
|
|
}
|
|
|
|
// ── Helper: fetch matches by status with usernames ────────────────────────────
|
|
function fetchMatchesByStatus(PDO $pdo, string $status): array {
|
|
$disciplineExpr = matchesHasColumn($pdo, 'Discipline')
|
|
? "COALESCE(m.Discipline, 'ping-pong')"
|
|
: "'ping-pong'";
|
|
|
|
$sql = "SELECT
|
|
m.id,
|
|
{$disciplineExpr} AS discipline,
|
|
m.Status AS status,
|
|
COALESCE(m.Score, '0:0') AS score,
|
|
m.StartTime AS started_at,
|
|
m.EndTime AS ended_at,
|
|
m.Team1_ID AS user1_id,
|
|
m.Team2_ID AS user2_id,
|
|
COALESCE(u1.username, '') AS user1_username,
|
|
COALESCE(u2.username, '') AS user2_username
|
|
FROM matches m
|
|
LEFT JOIN users u1 ON u1.id = m.Team1_ID
|
|
LEFT JOIN users u2 ON u2.id = m.Team2_ID
|
|
WHERE m.Status = :status
|
|
ORDER BY m.StartTime DESC
|
|
LIMIT 200";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute([':status' => $status]);
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// ── Fetch live / planned / ended sessions ────────────────────────────────────
|
|
try {
|
|
$live = fetchMatchesByStatus($pdo, 'live');
|
|
$planned = fetchMatchesByStatus($pdo, 'planned');
|
|
$ended = fetchMatchesByStatus($pdo, 'end');
|
|
} catch (Exception $e) {
|
|
ob_clean();
|
|
echo json_encode(['success' => false, 'error' => 'matches_query: ' . $e->getMessage()]);
|
|
exit;
|
|
}
|
|
|
|
// ── Paginated / filtered match_results ───────────────────────────────────────
|
|
$page = max(1, (int)($_GET['page'] ?? 1));
|
|
$limit = min(100, max(1, (int)($_GET['limit'] ?? 25)));
|
|
$offset = ($page - 1) * $limit;
|
|
|
|
$allowedSort = ['id','discipline','mode','winner_username','loser_username','score','reason','ended_at','created_at'];
|
|
$sortBy = in_array($_GET['sortBy'] ?? '', $allowedSort) ? $_GET['sortBy'] : 'ended_at';
|
|
$sortOrder = strtoupper($_GET['sortOrder'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
|
|
|
|
// Filters
|
|
$filters = [];
|
|
$params = [];
|
|
|
|
if (!empty($_GET['user'])) {
|
|
$like = '%' . $_GET['user'] . '%';
|
|
$filters[] = '(r.winner_username LIKE :user1 OR r.loser_username LIKE :user2)';
|
|
$params[':user1'] = $like;
|
|
$params[':user2'] = $like;
|
|
}
|
|
if (!empty($_GET['discipline'])) {
|
|
$filters[] = 'r.discipline = :discipline';
|
|
$params[':discipline'] = $_GET['discipline'];
|
|
}
|
|
if (!empty($_GET['mode'])) {
|
|
$filters[] = 'r.mode = :mode';
|
|
$params[':mode'] = $_GET['mode'];
|
|
}
|
|
if (!empty($_GET['reason'])) {
|
|
$filters[] = 'r.reason = :reason';
|
|
$params[':reason'] = $_GET['reason'];
|
|
}
|
|
if (!empty($_GET['date_from'])) {
|
|
$filters[] = 'r.ended_at >= :date_from';
|
|
$params[':date_from'] = $_GET['date_from'] . ' 00:00:00';
|
|
}
|
|
if (!empty($_GET['date_to'])) {
|
|
$filters[] = 'r.ended_at <= :date_to';
|
|
$params[':date_to'] = $_GET['date_to'] . ' 23:59:59';
|
|
}
|
|
|
|
$where = $filters ? 'WHERE ' . implode(' AND ', $filters) : '';
|
|
|
|
$totalRecords = 0;
|
|
$totalPages = 1;
|
|
$results = [];
|
|
|
|
try {
|
|
// Count
|
|
$countSql = "SELECT COUNT(*) FROM match_results r $where";
|
|
$countStmt = $pdo->prepare($countSql);
|
|
$countStmt->execute($params);
|
|
$totalRecords = (int)$countStmt->fetchColumn();
|
|
$totalPages = $totalRecords > 0 ? (int)ceil($totalRecords / $limit) : 1;
|
|
|
|
// Rows
|
|
$rowsSql = "SELECT r.id, r.match_id, r.discipline, r.mode,
|
|
r.winner_user_id, r.winner_username,
|
|
r.loser_user_id, r.loser_username,
|
|
r.score, r.sets_winner, r.sets_loser,
|
|
r.reason, r.ended_at, r.created_at
|
|
FROM match_results r
|
|
$where
|
|
ORDER BY r.`$sortBy` $sortOrder
|
|
LIMIT :limit OFFSET :offset";
|
|
$rowsStmt = $pdo->prepare($rowsSql);
|
|
foreach ($params as $k => $v) {
|
|
$rowsStmt->bindValue($k, $v);
|
|
}
|
|
$rowsStmt->bindValue(':limit', $limit, PDO::PARAM_INT);
|
|
$rowsStmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
|
$rowsStmt->execute();
|
|
$results = $rowsStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (Exception $e) {
|
|
ob_clean();
|
|
echo json_encode(['success' => false, 'error' => 'results_query: ' . $e->getMessage()]);
|
|
exit;
|
|
}
|
|
|
|
ob_clean();
|
|
echo json_encode([
|
|
'success' => true,
|
|
'live' => $live,
|
|
'planned' => $planned,
|
|
'ended_sessions' => $ended,
|
|
'results' => $results,
|
|
'pagination' => [
|
|
'currentPage' => $page,
|
|
'totalPages' => $totalPages,
|
|
'totalRecords' => $totalRecords,
|
|
'recordsPerPage' => $limit,
|
|
'hasNextPage' => $page < $totalPages,
|
|
'hasPreviousPage' => $page > 1,
|
|
],
|
|
], JSON_UNESCAPED_UNICODE);
|