400,
'today' => 0,
'last_date' => date('Y-m-d'),
'last_update' => time()
];
if (!file_exists(COUNTER_FILE)) {
return $defaultData;
}
$retries = 0;
while ($retries < MAX_RETRIES) {
$fp = fopen(COUNTER_FILE, 'r');
if ($fp) {
if (flock($fp, LOCK_SH)) { // Verrou partagé pour la lecture
$content = fread($fp, filesize(COUNTER_FILE) ?: 1);
flock($fp, LOCK_UN);
fclose($fp);
$data = json_decode($content, true);
if ($data && is_array($data)) {
return $data;
}
return $defaultData;
}
fclose($fp);
}
$retries++;
usleep(RETRY_DELAY);
}
return $defaultData;
}
/**
* Sauvegarder les données du compteur avec verrouillage
*/
function saveCounterData($data) {
$data['last_update'] = time();
$json = json_encode($data, JSON_PRETTY_PRINT);
$retries = 0;
while ($retries < MAX_RETRIES) {
$fp = fopen(COUNTER_FILE, 'c'); // 'c' = ouvre pour écriture, crée si nécessaire
if ($fp) {
if (flock($fp, LOCK_EX)) { // Verrou exclusif pour l'écriture
ftruncate($fp, 0); // Vide le fichier
fwrite($fp, $json);
fflush($fp);
flock($fp, LOCK_UN);
fclose($fp);
return true;
}
fclose($fp);
}
$retries++;
usleep(RETRY_DELAY);
}
return false;
}
/**
* Charger le log des visiteurs avec verrouillage
*/
function loadVisitorsLog() {
if (!file_exists(VISITORS_FILE)) {
return [];
}
$retries = 0;
while ($retries < MAX_RETRIES) {
$fp = fopen(VISITORS_FILE, 'r');
if ($fp) {
if (flock($fp, LOCK_SH)) { // Verrou partagé
$content = fread($fp, filesize(VISITORS_FILE) ?: 1);
flock($fp, LOCK_UN);
fclose($fp);
$data = json_decode($content, true);
return $data ?? [];
}
fclose($fp);
}
$retries++;
usleep(RETRY_DELAY);
}
return [];
}
/**
* Sauvegarder le log des visiteurs avec verrouillage
*/
function saveVisitorsLog($visitors) {
// Nettoyer les entrées de plus de 30 jours
$cutoff = strtotime('-30 days');
foreach ($visitors as $id => $info) {
if (isset($info['last_visit']) && $info['last_visit'] < $cutoff) {
unset($visitors[$id]);
}
}
$json = json_encode($visitors, JSON_PRETTY_PRINT);
$retries = 0;
while ($retries < MAX_RETRIES) {
$fp = fopen(VISITORS_FILE, 'c');
if ($fp) {
if (flock($fp, LOCK_EX)) { // Verrou exclusif
ftruncate($fp, 0);
fwrite($fp, $json);
fflush($fp);
flock($fp, LOCK_UN);
fclose($fp);
return true;
}
fclose($fp);
}
$retries++;
usleep(RETRY_DELAY);
}
return false;
}
/**
* Vérifier si le visiteur est nouveau aujourd'hui
*/
function isNewVisitToday($visitorId, $visitorsLog, $today) {
if (!isset($visitorsLog[$visitorId])) {
return true;
}
$lastVisitDate = $visitorsLog[$visitorId]['last_visit_date'] ?? '';
return $lastVisitDate !== $today;
}
// ====================
// TRAITEMENT PRINCIPAL
// ====================
try {
// Charger les données
$counterData = loadCounterData();
$visitorsLog = loadVisitorsLog();
$today = date('Y-m-d');
// Réinitialiser le compteur quotidien si on change de jour
if ($counterData['last_date'] !== $today) {
$counterData['today'] = 0;
$counterData['last_date'] = $today;
}
// Identifier le visiteur
$visitorId = getVisitorId();
$isNewToday = isNewVisitToday($visitorId, $visitorsLog, $today);
// Incrémenter les compteurs si c'est une nouvelle visite aujourd'hui
if ($isNewToday) {
$counterData['total']++;
$counterData['today']++;
// Mettre à jour le log des visiteurs
$visitorsLog[$visitorId] = [
'last_visit' => time(),
'last_visit_date' => $today,
'ip' => getVisitorIP(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
];
// Sauvegarder avec vérification
$counterSaved = saveCounterData($counterData);
$visitorsSaved = saveVisitorsLog($visitorsLog);
if (!$counterSaved || !$visitorsSaved) {
throw new Exception('Erreur lors de la sauvegarde des données');
}
}
// Retourner les données
echo json_encode([
'status' => 'success',
'total' => (int)$counterData['total'],
'today' => (int)$counterData['today'],
'date' => $today,
'is_new_visitor' => $isNewToday,
'timestamp' => time()
]);
} catch (Exception $e) {
// En cas d'erreur, retourner des valeurs par défaut
http_response_code(500);
echo json_encode([
'status' => 'error',
'message' => 'Erreur serveur',
'total' => 380,
'today' => 1,
'error_details' => $e->getMessage()
]);
}
?>