togethere.cloud/public_html/api/getMatches.php

233 lines
7.9 KiB
PHP

<?php
// Włączenie raportowania błędów dla debugowania
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
// Ochrona panelu administracyjnego - tylko admini
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/session_bootstrap.php';
// Sprawdzenie czy użytkownik jest zalogowany
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
http_response_code(401);
echo json_encode([
'success' => false,
'error' => 'Unauthorized - brak autoryzacji'
], JSON_UNESCAPED_UNICODE);
exit;
}
// Sprawdzenie czy użytkownik ma rolę admina
if (!isset($_SESSION['role']) || $_SESSION['role'] !== 'admin') {
http_response_code(403);
echo json_encode([
'success' => false,
'error' => 'Forbidden - tylko admini mają dostęp'
], JSON_UNESCAPED_UNICODE);
exit;
}
// Funkcja do zwracania błędów jako JSON
function returnError($message, $code = 500) {
http_response_code($code);
echo json_encode([
'success' => false,
'error' => $message
], JSON_UNESCAPED_UNICODE);
exit;
}
try {
$pdo = og_session_get_pdo();
if (!$pdo instanceof PDO) {
throw new PDOException('Nie udało się zainicjalizować połączenia z bazą danych.');
}
// Parametry z requestu
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
$limit = isset($_GET['limit']) ? min(100, max(1, (int)$_GET['limit'])) : 50;
$offset = ($page - 1) * $limit;
// Sortowanie
$sortBy = isset($_GET['sortBy']) ? $_GET['sortBy'] : 'StartTime';
$sortOrder = isset($_GET['sortOrder']) && strtoupper($_GET['sortOrder']) === 'DESC' ? 'DESC' : 'ASC';
// Dozwolone kolumny do sortowania (bezpieczeństwo)
$allowedSortColumns = ['ID', 'Team1_ID', 'Team2_ID', 'StartTime', 'Status', 'Score', 'Platform', 'MatchType', 'created_at', 'updated_at'];
if (!in_array($sortBy, $allowedSortColumns)) {
$sortBy = 'StartTime';
}
// Filtrowanie
$filters = [];
$params = [];
// Filtr po statusie meczu
if (isset($_GET['status']) && $_GET['status'] !== '') {
$filters[] = "Status = :status";
$params[':status'] = $_GET['status'];
}
// Filtr po platformie
if (isset($_GET['platform']) && $_GET['platform'] !== '') {
$filters[] = "Platform = :platform";
$params[':platform'] = $_GET['platform'];
}
// Filtr po typie meczu
if (isset($_GET['matchType']) && $_GET['matchType'] !== '') {
$filters[] = "MatchType = :matchType";
$params[':matchType'] = $_GET['matchType'];
}
// Filtr po dacie rozpoczęcia (od)
if (isset($_GET['startTime_from']) && $_GET['startTime_from'] !== '') {
$filters[] = "StartTime >= :startTime_from";
$params[':startTime_from'] = $_GET['startTime_from'];
}
// Filtr po dacie rozpoczęcia (do)
if (isset($_GET['startTime_to']) && $_GET['startTime_to'] !== '') {
$filters[] = "StartTime <= :startTime_to";
$params[':startTime_to'] = $_GET['startTime_to'];
}
// Filtr po ID drużyny 1
if (isset($_GET['team1_id']) && $_GET['team1_id'] !== '') {
$filters[] = "Team1_ID = :team1_id";
$params[':team1_id'] = (int)$_GET['team1_id'];
}
// Filtr po ID drużyny 2
if (isset($_GET['team2_id']) && $_GET['team2_id'] !== '') {
$filters[] = "Team2_ID = :team2_id";
$params[':team2_id'] = (int)$_GET['team2_id'];
}
// Budowanie WHERE clause
$whereClause = '';
if (count($filters) > 0) {
$whereClause = 'WHERE ' . implode(' AND ', $filters);
}
// OPTYMALIZACJA: Fast approximate count z limitem 100k
// Sprawdzenie czy count jest w cache (ważny 5 minut)
$cacheKey = 'matches_count_' . md5(serialize($params));
$totalRecords = 0;
$isApproximate = false;
if (isset($_SESSION[$cacheKey]) &&
isset($_SESSION[$cacheKey . '_time']) &&
(time() - $_SESSION[$cacheKey . '_time']) < 300) {
// Cache hit - użyj zapisanej wartości
$totalRecords = $_SESSION[$cacheKey];
$isApproximate = $_SESSION[$cacheKey . '_approx'] ?? false;
} else {
// Cache miss - policz z limitem
// OPTYMALIZACJA: Limit count do 100k dla wydajności
$countSql = "SELECT COUNT(*) as total FROM (
SELECT 1 FROM matches $whereClause LIMIT 100000
) as limited_count";
$countStmt = $pdo->prepare($countSql);
try {
$countStmt->execute($params);
$totalRecords = $countStmt->fetch(PDO::FETCH_ASSOC)['total'];
// Jeśli osiągnięto limit, sprawdź czy jest więcej
if ($totalRecords >= 100000) {
$checkMoreSql = "SELECT EXISTS(
SELECT 1 FROM matches $whereClause LIMIT 100001
) as has_more";
$checkStmt = $pdo->prepare($checkMoreSql);
$checkStmt->execute($params);
if ($checkStmt->fetch(PDO::FETCH_ASSOC)['has_more']) {
$isApproximate = true;
$totalRecords = 100000; // Pokazuj 100k+
}
}
// Zapisz w cache na 5 minut
$_SESSION[$cacheKey] = $totalRecords;
$_SESSION[$cacheKey . '_time'] = time();
$_SESSION[$cacheKey . '_approx'] = $isApproximate;
} catch (PDOException $e) {
returnError('Błąd podczas zliczania rekordów: ' . $e->getMessage());
}
}
$totalPages = $totalRecords > 0 ? ceil($totalRecords / $limit) : 1;
// Pobieranie meczów
$sql = "SELECT
ID,
Team1_ID,
Team2_ID,
StartTime,
EndTime,
Status,
Score,
Platform,
MatchType,
Rate,
Participants,
created_at,
updated_at
FROM matches
$whereClause
ORDER BY $sortBy $sortOrder
LIMIT :limit OFFSET :offset";
$stmt = $pdo->prepare($sql);
// Bindowanie parametrów filtrów
foreach ($params as $key => $value) {
$stmt->bindValue($key, $value);
}
// Bindowanie limit i offset
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
try {
$stmt->execute();
$matches = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
returnError('Błąd podczas pobierania meczów: ' . $e->getMessage());
}
// Formatowanie odpowiedzi
$response = [
'success' => true,
'data' => $matches,
'pagination' => [
'currentPage' => $page,
'totalPages' => $totalPages,
'totalRecords' => (int)$totalRecords,
'totalRecordsApproximate' => $isApproximate,
'totalRecordsDisplay' => $isApproximate ? '100,000+' : number_format($totalRecords, 0, ',', ' '),
'recordsPerPage' => $limit,
'hasNextPage' => $page < $totalPages,
'hasPreviousPage' => $page > 1
],
'filters' => [
'sortBy' => $sortBy,
'sortOrder' => $sortOrder,
'appliedFilters' => array_keys($params)
]
];
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
} catch (PDOException $e) {
returnError('Błąd połączenia z bazą danych: ' . $e->getMessage());
} catch (Exception $e) {
returnError('Nieoczekiwany błąd: ' . $e->getMessage());
}
?>