Files
ms1inscription-v5/php/chronotrack_api/fx_chronotrack_config.php

365 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* MSIN API ChronoTrack — config par eve_id (lien event, statut, mapping épreuves).
*/
function fxChronotrackApiConfigGet($intEveId) {
global $objDatabase;
$intEveId = intval($intEveId);
if ($intEveId <= 0) {
return null;
}
$sql = "SELECT * FROM api_chronotrack_config WHERE eve_id = " . $intEveId . " LIMIT 1";
return $objDatabase->fxGetRow($sql);
}
function fxChronotrackApiConfigStatusLabel($strStatus) {
switch ($strStatus) {
case MSIN_API_CHRONOTRACK_SYNC_ACTIF:
return 'Actif';
case MSIN_API_CHRONOTRACK_SYNC_FERME:
return 'Fermé';
case MSIN_API_CHRONOTRACK_SYNC_LIE:
default:
return 'Lié';
}
}
function fxChronotrackApiConfigSaveLink($intEveId, $intCtEventId, $strCtEventName, $strCtEventDate, $intUsaId) {
global $objDatabase;
$intEveId = intval($intEveId);
$intCtEventId = intval($intCtEventId);
if ($intEveId <= 0 || $intCtEventId <= 0) {
return array('state' => 'error', 'message' => 'Identifiants invalides');
}
$arrExisting = fxChronotrackApiConfigGet($intEveId);
if ($arrExisting !== null && $arrExisting['sync_status'] === MSIN_API_CHRONOTRACK_SYNC_FERME) {
return array('state' => 'error', 'message' => 'Événement fermé — réouverture non autorisée depuis cette interface.');
}
$strName = $objDatabase->fxEscape(trim($strCtEventName));
$strDateSql = 'NULL';
if (trim($strCtEventDate) !== '') {
$intTs = strtotime($strCtEventDate);
if ($intTs !== false) {
$strDateSql = "'" . $objDatabase->fxEscape(date('Y-m-d H:i:s', $intTs)) . "'";
}
}
if ($arrExisting === null) {
$sql = "INSERT INTO api_chronotrack_config SET eve_id = " . $intEveId
. ", ct_event_id = " . $intCtEventId
. ", ct_event_name = '" . $strName . "'"
. ", ct_event_date = " . $strDateSql
. ", sync_status = '" . MSIN_API_CHRONOTRACK_SYNC_LIE . "'"
. ", linked_at = '" . fxGetDateTime() . "'"
. ", linked_by_usa_id = " . intval($intUsaId)
. ", updated_at = '" . fxGetDateTime() . "'";
} else {
$sql = "UPDATE api_chronotrack_config SET ct_event_id = " . $intCtEventId
. ", ct_event_name = '" . $strName . "'"
. ", ct_event_date = " . $strDateSql
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId
. " AND sync_status <> '" . MSIN_API_CHRONOTRACK_SYNC_FERME . "'";
}
if (!$objDatabase->fxQuery($sql)) {
return array('state' => 'error', 'message' => 'Erreur SQL enregistrement lien');
}
return array('state' => 'ok');
}
function fxChronotrackApiConfigSetStatus($intEveId, $strStatus, $intUsaId) {
global $objDatabase;
$intEveId = intval($intEveId);
$arrExisting = fxChronotrackApiConfigGet($intEveId);
if ($arrExisting === null) {
return array('state' => 'error', 'message' => 'Aucun lien ChronoTrack pour cet événement');
}
if ($arrExisting['sync_status'] === MSIN_API_CHRONOTRACK_SYNC_FERME) {
if ($strStatus !== MSIN_API_CHRONOTRACK_SYNC_LIE) {
return array('state' => 'error', 'message' => 'Événement fermé — seule la réouverture (Lié) est permise.');
}
}
$strStatus = trim($strStatus);
if (!in_array($strStatus, array(MSIN_API_CHRONOTRACK_SYNC_LIE, MSIN_API_CHRONOTRACK_SYNC_ACTIF, MSIN_API_CHRONOTRACK_SYNC_FERME), true)) {
return array('state' => 'error', 'message' => 'Statut invalide');
}
$strExtra = '';
if ($strStatus === MSIN_API_CHRONOTRACK_SYNC_ACTIF) {
$strExtra = ", activated_at = '" . fxGetDateTime() . "'";
}
if ($strStatus === MSIN_API_CHRONOTRACK_SYNC_FERME) {
$strExtra = ", closed_at = '" . fxGetDateTime() . "', closed_by_usa_id = " . intval($intUsaId);
}
if ($strStatus === MSIN_API_CHRONOTRACK_SYNC_LIE && $arrExisting['sync_status'] === MSIN_API_CHRONOTRACK_SYNC_FERME) {
$strExtra = ", closed_at = NULL, closed_by_usa_id = NULL";
}
$sql = "UPDATE api_chronotrack_config SET sync_status = '" . $objDatabase->fxEscape($strStatus) . "'"
. $strExtra
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId;
if (!$objDatabase->fxQuery($sql)) {
return array('state' => 'error', 'message' => 'Erreur SQL changement statut');
}
return array('state' => 'ok');
}
/**
* MSIN-4328 — mémorise la fin dun push réussi (référence pour par_maj).
*/
function fxChronotrackApiConfigSetLastPush($intEveId, $intOkCount) {
global $objDatabase;
$intEveId = intval($intEveId);
if ($intEveId <= 0) {
return false;
}
$sql = "UPDATE api_chronotrack_config SET last_push_at = '" . fxGetDateTime() . "'"
. ", last_push_ok_count = " . max(0, intval($intOkCount))
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId;
return (bool)$objDatabase->fxQuery($sql);
}
/**
* MSIN-4328 — fréquences autorisées (minutes), phase A.
*/
function fxChronotrackApiConfigAutoSyncIntervals() {
return array(1, 5, 15, 30, 60);
}
/**
* MSIN-4328 — enregistre la config sync auto (UI). Le cron (phase B) lira ces champs.
*/
function fxChronotrackApiConfigSaveAutoSync($intEveId, $blnEnabled, $intIntervalMin, $strUntil) {
global $objDatabase;
$intEveId = intval($intEveId);
$arrExisting = fxChronotrackApiConfigGet($intEveId);
if ($arrExisting === null) {
return array('state' => 'error', 'message' => 'Événement non lié à ChronoTrack');
}
if (($arrExisting['sync_status'] ?? '') === MSIN_API_CHRONOTRACK_SYNC_FERME) {
return array('state' => 'error', 'message' => 'Événement fermé — sync auto impossible.');
}
$blnEnabled = $blnEnabled ? 1 : 0;
$intIntervalMin = intval($intIntervalMin);
if (!in_array($intIntervalMin, fxChronotrackApiConfigAutoSyncIntervals(), true)) {
$intIntervalMin = 15;
}
$strUntilSql = 'NULL';
$strUntil = trim((string)$strUntil);
if ($strUntil !== '') {
// Accepte "YYYY-MM-DDTHH:MM" (input datetime-local) ou "YYYY-MM-DD HH:MM[:SS]"
$strUntilNorm = str_replace('T', ' ', $strUntil);
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $strUntilNorm)) {
$strUntilNorm .= ':00';
}
$intTs = strtotime($strUntilNorm);
if ($intTs === false) {
return array('state' => 'error', 'message' => 'Date / heure de fin invalide');
}
if ($blnEnabled && $intTs <= time()) {
return array('state' => 'error', 'message' => 'La date/heure de fin doit être dans le futur');
}
$strUntilSql = "'" . $objDatabase->fxEscape(date('Y-m-d H:i:s', $intTs)) . "'";
} elseif ($blnEnabled) {
return array('state' => 'error', 'message' => 'Indiquez une date et une heure de fin pour activer la sync auto');
}
$sql = "UPDATE api_chronotrack_config SET auto_sync_enabled = " . $blnEnabled
. ", auto_sync_interval_min = " . $intIntervalMin
. ", auto_sync_until = " . $strUntilSql
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId;
if (!$objDatabase->fxQuery($sql)) {
return array('state' => 'error', 'message' => 'Erreur SQL enregistrement sync auto');
}
$arrFresh = fxChronotrackApiConfigGet($intEveId);
return array(
'state' => 'ok',
'message' => $blnEnabled
? ('Sync auto enregistrée (toutes les ' . $intIntervalMin . ' min jusquau '
. trim((string)($arrFresh['auto_sync_until'] ?? '')) . '). Cron : auto_chronotrack_sync.php')
: 'Sync auto désactivée.',
'auto_sync' => array(
'enabled' => intval($arrFresh['auto_sync_enabled'] ?? 0) === 1,
'interval_min' => intval($arrFresh['auto_sync_interval_min'] ?? 15),
'until' => ($arrFresh['auto_sync_until'] ?? null),
'last_run_at' => ($arrFresh['last_auto_run_at'] ?? null),
),
);
}
/**
* MSIN-4328 — events avec sync auto ON (pas fermés).
*/
function fxChronotrackApiConfigListAutoSyncEnabled() {
global $objDatabase;
$sql = "SELECT c.*"
. " FROM api_chronotrack_config c"
. " WHERE IFNULL(c.auto_sync_enabled, 0) = 1"
. " AND c.sync_status <> '" . $objDatabase->fxEscape(MSIN_API_CHRONOTRACK_SYNC_FERME) . "'"
. " ORDER BY c.eve_id ASC";
$arrRows = $objDatabase->fxGetResults($sql);
$tabOut = array();
if (!is_array($arrRows)) {
return $tabOut;
}
for ($i = 1; $i <= count($arrRows); $i++) {
$tabOut[] = $arrRows[$i];
}
return $tabOut;
}
/**
* MSIN-4328 — horodatage dernier passage cron auto.
*/
function fxChronotrackApiConfigTouchAutoRun($intEveId) {
global $objDatabase;
$intEveId = intval($intEveId);
if ($intEveId <= 0) {
return false;
}
$sql = "UPDATE api_chronotrack_config SET last_auto_run_at = '" . fxGetDateTime() . "'"
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId;
return (bool)$objDatabase->fxQuery($sql);
}
/**
* MSIN-4328 — coupe la sync auto (échéance atteinte).
*/
function fxChronotrackApiConfigDisableAutoSync($intEveId) {
global $objDatabase;
$intEveId = intval($intEveId);
if ($intEveId <= 0) {
return false;
}
$sql = "UPDATE api_chronotrack_config SET auto_sync_enabled = 0"
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId;
return (bool)$objDatabase->fxQuery($sql);
}
function fxChronotrackApiRaceMapGetForEvent($intEveId) {
global $objDatabase;
$sql = "SELECT * FROM api_chronotrack_race_map WHERE eve_id = " . intval($intEveId);
$arrRows = $objDatabase->fxGetResults($sql);
$arrMap = array();
if ($arrRows !== null) {
for ($i = 1; $i <= count($arrRows); $i++) {
$arrMap[intval($arrRows[$i]['epr_id'])] = $arrRows[$i];
}
}
return $arrMap;
}
function fxChronotrackApiMs1EpreuvesForEvent($intEveId, $strLangue = 'fr') {
global $objDatabase;
$strLangue = ($strLangue === 'en') ? 'en' : 'fr';
$sql = "SELECT epr_id, epr_nom_" . $strLangue . " AS epr_nom, epr_type_" . $strLangue . " AS epr_type, epr_date"
. " FROM inscriptions_epreuves WHERE eve_id = " . intval($intEveId)
. " ORDER BY epr_date, epr_nom_" . $strLangue;
return $objDatabase->fxGetResults($sql);
}
function fxChronotrackApiRaceMapSave($intEveId, $arrMapInput) {
global $objDatabase;
$intEveId = intval($intEveId);
$arrExisting = fxChronotrackApiConfigGet($intEveId);
if ($arrExisting === null) {
return array('state' => 'error', 'message' => 'Lier d\'abord un événement ChronoTrack');
}
if ($arrExisting['sync_status'] === MSIN_API_CHRONOTRACK_SYNC_FERME) {
return array('state' => 'error', 'message' => 'Événement fermé — mapping en lecture seule');
}
if (!is_array($arrMapInput)) {
return array('state' => 'error', 'message' => 'Mapping invalide');
}
foreach ($arrMapInput as $intEprId => $arrRace) {
$intEprId = intval($intEprId);
$intCtRaceId = intval($arrRace['ct_race_id'] ?? 0);
$strCtRaceName = trim((string)($arrRace['ct_race_name'] ?? ''));
if ($intEprId <= 0) {
continue;
}
if ($intCtRaceId <= 0) {
$sqlDel = "DELETE FROM api_chronotrack_race_map WHERE eve_id = " . $intEveId . " AND epr_id = " . $intEprId;
$objDatabase->fxQuery($sqlDel);
continue;
}
$sqlExists = "SELECT map_id FROM api_chronotrack_race_map WHERE eve_id = " . $intEveId
. " AND epr_id = " . $intEprId . " LIMIT 1";
if ($objDatabase->fxGetRow($sqlExists) !== null) {
$sql = "UPDATE api_chronotrack_race_map SET ct_race_id = " . $intCtRaceId
. ", ct_race_name = '" . $objDatabase->fxEscape($strCtRaceName) . "'"
. ", updated_at = '" . fxGetDateTime() . "'"
. " WHERE eve_id = " . $intEveId . " AND epr_id = " . $intEprId;
} else {
$sql = "INSERT INTO api_chronotrack_race_map SET eve_id = " . $intEveId
. ", epr_id = " . $intEprId
. ", ct_race_id = " . $intCtRaceId
. ", ct_race_name = '" . $objDatabase->fxEscape($strCtRaceName) . "'"
. ", updated_at = '" . fxGetDateTime() . "'";
}
$objDatabase->fxQuery($sql);
}
return array('state' => 'ok');
}
function fxChronotrackApiMs1EventRow($intEveId, $strLangue = 'fr') {
global $objDatabase;
$strLangue = ($strLangue === 'en') ? 'en' : 'fr';
$sql = "SELECT eve_id, eve_nom_" . $strLangue . " AS eve_nom, eve_date_debut, eve_date_fin"
. " FROM inscriptions_evenements WHERE eve_id = " . intval($intEveId) . " LIMIT 1";
return $objDatabase->fxGetRow($sql);
}
function fxChronotrackApiListActiveConfigs($arrStatuses = null) {
global $objDatabase;
if ($arrStatuses === null) {
$arrStatuses = array(MSIN_API_CHRONOTRACK_SYNC_LIE, MSIN_API_CHRONOTRACK_SYNC_ACTIF);
}
$arrEsc = array();
foreach ($arrStatuses as $strStatus) {
$arrEsc[] = "'" . $objDatabase->fxEscape($strStatus) . "'";
}
$sql = "SELECT c.*, e.eve_nom_fr AS eve_nom"
. " FROM api_chronotrack_config c"
. " INNER JOIN inscriptions_evenements e ON e.eve_id = c.eve_id"
. " WHERE c.sync_status IN (" . implode(',', $arrEsc) . ")"
. " ORDER BY c.sync_status DESC, c.updated_at DESC";
return $objDatabase->fxGetResults($sql);
}