269 lines
10 KiB
PHP
269 lines
10 KiB
PHP
<?php
|
||
/**
|
||
* MSIN-4574 — Auto-push / cron ChronoTrack.
|
||
*/
|
||
|
||
/**
|
||
* MSIN-4328 — push différentiel complet pour un event (cron auto).
|
||
*/
|
||
function fxChronotrackApiSyncRunAutoPushForEvent($intEveId) {
|
||
$intEveId = intval($intEveId);
|
||
$arrPrep = fxChronotrackApiSyncPushPrepare($intEveId);
|
||
if (($arrPrep['state'] ?? '') !== 'ok') {
|
||
// Rien à pousser = succès « idle »
|
||
$strMsg = (string)($arrPrep['message'] ?? 'prepare failed');
|
||
if (stripos($strMsg, 'Aucun changement') !== false || intval($arrPrep['pending_push'] ?? -1) === 0) {
|
||
fxChronotrackApiSyncLog($intEveId, 0, 'auto_push', 'ok', 'idle — ' . $strMsg);
|
||
return array('state' => 'ok', 'message' => $strMsg, 'pushed_ok' => 0, 'idle' => true);
|
||
}
|
||
fxChronotrackApiSyncLog($intEveId, 0, 'auto_push', 'error', $strMsg);
|
||
return $arrPrep;
|
||
}
|
||
|
||
$intOffset = 0;
|
||
$intLimit = MSIN_API_CHRONOTRACK_SYNC_CHUNK_SIZE;
|
||
$intOkSum = 0;
|
||
$intErrSum = 0;
|
||
$intLoops = 0;
|
||
$intMaxLoops = 500;
|
||
|
||
while ($intLoops < $intMaxLoops) {
|
||
$intLoops++;
|
||
$arrChunk = fxChronotrackApiSyncPushEvent($intEveId, array(
|
||
'offset' => $intOffset,
|
||
'limit' => $intLimit,
|
||
));
|
||
$intOkSum += intval($arrChunk['pushed_ok'] ?? 0);
|
||
$intErrSum += intval($arrChunk['pushed_error'] ?? 0);
|
||
if (!empty($arrChunk['done'])) {
|
||
break;
|
||
}
|
||
// Identité finie → drain dossards en sous-lots
|
||
if (!empty($arrChunk['identity_done']) && intval($arrChunk['bib_pending'] ?? 0) > 0) {
|
||
$intBibLoops = 0;
|
||
while ($intBibLoops < $intMaxLoops) {
|
||
$intBibLoops++;
|
||
$arrBib = fxChronotrackApiSyncPushBibsPhase($intEveId, array(
|
||
'limit' => MSIN_API_CHRONOTRACK_SYNC_BIB_CHUNK_SIZE,
|
||
));
|
||
$intOkSum += intval($arrBib['pushed_ok'] ?? 0);
|
||
$intErrSum += intval($arrBib['pushed_error'] ?? 0);
|
||
if (!empty($arrBib['done'])) {
|
||
break;
|
||
}
|
||
if (($arrBib['state'] ?? '') === 'error' && intval($arrBib['pushed_ok'] ?? 0) === 0) {
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
if (($arrChunk['state'] ?? '') === 'error' && intval($arrChunk['pushed_ok'] ?? 0) === 0) {
|
||
break;
|
||
}
|
||
$intOffset = intval($arrChunk['next_offset'] ?? ($intOffset + $intLimit));
|
||
}
|
||
|
||
$strState = ($intErrSum === 0) ? 'ok' : (($intOkSum > 0) ? 'partial' : 'error');
|
||
$strMsg = 'auto push ok=' . $intOkSum . ' err=' . $intErrSum
|
||
. ' total_job=' . intval($arrPrep['total'] ?? 0);
|
||
fxChronotrackApiSyncLog($intEveId, 0, 'auto_push', ($strState === 'ok') ? 'ok' : 'error', $strMsg);
|
||
|
||
return array(
|
||
'state' => $strState,
|
||
'message' => $strMsg,
|
||
'pushed_ok' => $intOkSum,
|
||
'pushed_error' => $intErrSum,
|
||
'idle' => false,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* MSIN-4328 — passage cron : events auto ON, fréquence / fin respectées.
|
||
* Chaque décision (run / skip / expire) écrit un log pour l’événement — sinon
|
||
* « Voir les logs » reste vide alors que le CrowdJob tourne vraiment.
|
||
*/
|
||
function fxChronotrackApiSyncRunAutoCron() {
|
||
if (!fxChronotrackApiSettingsConfigured()) {
|
||
return array(
|
||
'state' => 'error',
|
||
'message' => fxChronotrackApiSettingsErrorMessage(),
|
||
'ran' => 0,
|
||
'skipped' => 0,
|
||
'enabled_configs' => 0,
|
||
);
|
||
}
|
||
|
||
$tabConfigs = fxChronotrackApiConfigListAutoSyncEnabled();
|
||
$intRan = 0;
|
||
$intSkipped = 0;
|
||
$intExpired = 0;
|
||
$tabDetails = array();
|
||
$intNow = time();
|
||
$intEnabled = count($tabConfigs);
|
||
|
||
foreach ($tabConfigs as $arrCfg) {
|
||
$intEveId = intval($arrCfg['eve_id'] ?? 0);
|
||
if ($intEveId <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$strUntil = trim((string)($arrCfg['auto_sync_until'] ?? ''));
|
||
if ($strUntil !== '' && $strUntil !== '0000-00-00 00:00:00') {
|
||
$intUntil = strtotime($strUntil);
|
||
if ($intUntil !== false && $intNow > $intUntil) {
|
||
fxChronotrackApiConfigDisableAutoSync($intEveId);
|
||
fxChronotrackApiSyncLog(
|
||
$intEveId,
|
||
0,
|
||
'auto_sync',
|
||
'ok',
|
||
'Échéance atteinte (' . $strUntil . ') — sync auto désactivée'
|
||
);
|
||
$intExpired++;
|
||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'expired');
|
||
continue;
|
||
}
|
||
} else {
|
||
// Pas de fin = on ne tourne pas (UI exige une fin à l’enregistrement)
|
||
$intSkipped++;
|
||
fxChronotrackApiSyncLog(
|
||
$intEveId,
|
||
0,
|
||
'auto_cron',
|
||
'error',
|
||
'Skip: date/heure de fin manquante (réenregistrer la sync auto)'
|
||
);
|
||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_no_until');
|
||
continue;
|
||
}
|
||
|
||
$intInterval = intval($arrCfg['auto_sync_interval_min'] ?? 15);
|
||
if (!in_array($intInterval, fxChronotrackApiConfigAutoSyncIntervals(), true)) {
|
||
$intInterval = 15;
|
||
}
|
||
$strLast = trim((string)($arrCfg['last_auto_run_at'] ?? ''));
|
||
if ($strLast !== '' && $strLast !== '0000-00-00 00:00:00') {
|
||
$intLast = strtotime($strLast);
|
||
if ($intLast !== false && ($intNow - $intLast) < ($intInterval * 60)) {
|
||
$intSkipped++;
|
||
// Trace légère: 1 seule fois par fenêtre d’intervalle (évite 1440 lignes/jour).
|
||
// Déjà logué ailleurs au run — ici on ne spam pas.
|
||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_interval');
|
||
continue;
|
||
}
|
||
}
|
||
|
||
$arrRes = fxChronotrackApiSyncRunAutoPushForEvent($intEveId);
|
||
fxChronotrackApiConfigTouchAutoRun($intEveId);
|
||
$intRan++;
|
||
$tabDetails[] = array(
|
||
'eve_id' => $intEveId,
|
||
'action' => 'run',
|
||
'result' => $arrRes['state'] ?? 'error',
|
||
'message' => $arrRes['message'] ?? '',
|
||
'ok' => intval($arrRes['pushed_ok'] ?? 0),
|
||
);
|
||
}
|
||
|
||
$strMsg = 'cron auto — configs_on=' . $intEnabled
|
||
. ' ran=' . $intRan . ' skipped=' . $intSkipped . ' expired=' . $intExpired;
|
||
if ($intEnabled === 0) {
|
||
$strMsg .= ' (aucun event avec sync auto ON sur cette base)';
|
||
}
|
||
|
||
return array(
|
||
'state' => 'ok',
|
||
'message' => $strMsg,
|
||
'ran' => $intRan,
|
||
'skipped' => $intSkipped,
|
||
'expired' => $intExpired,
|
||
'enabled_configs' => $intEnabled,
|
||
'details' => $tabDetails,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* MSIN-4328 — état sync auto + logs pour un événement (diag UI, pas d’essai-erreur SSL).
|
||
*/
|
||
function fxChronotrackApiSyncAutoDiag($intEveId) {
|
||
global $objDatabase;
|
||
|
||
$intEveId = intval($intEveId);
|
||
$arrCfg = fxChronotrackApiConfigGet($intEveId);
|
||
if ($arrCfg === null) {
|
||
return array('state' => 'error', 'message' => 'Événement non lié à ChronoTrack');
|
||
}
|
||
|
||
$blnColsOk = true;
|
||
$strColNote = '';
|
||
$sqlCol = "SELECT COUNT(*) AS n FROM information_schema.COLUMNS"
|
||
. " WHERE TABLE_SCHEMA = DATABASE()"
|
||
. " AND TABLE_NAME = 'api_chronotrack_config'"
|
||
. " AND COLUMN_NAME = 'auto_sync_enabled'";
|
||
$arrCol = $objDatabase->fxGetRow($sqlCol);
|
||
if (intval($arrCol['n'] ?? 0) < 1) {
|
||
$blnColsOk = false;
|
||
$strColNote = 'Colonnes auto_sync absentes — exécuter sql/MSIN-4328-chronotrack-auto-sync-config.sql';
|
||
}
|
||
|
||
$sqlLog = "SELECT COUNT(*) AS n FROM api_chronotrack_sync_log WHERE eve_id = " . $intEveId;
|
||
$arrLogCnt = $objDatabase->fxGetRow($sqlLog);
|
||
$intLogCnt = intval($arrLogCnt['n'] ?? 0);
|
||
|
||
$arrLastLog = $objDatabase->fxGetRow(
|
||
"SELECT log_id, action, status, message, created_at FROM api_chronotrack_sync_log"
|
||
. " WHERE eve_id = " . $intEveId
|
||
. " ORDER BY log_id DESC LIMIT 1"
|
||
);
|
||
|
||
$blnOn = (intval($arrCfg['auto_sync_enabled'] ?? 0) === 1);
|
||
$intInterval = intval($arrCfg['auto_sync_interval_min'] ?? 15);
|
||
$strUntil = trim((string)($arrCfg['auto_sync_until'] ?? ''));
|
||
$strLastRun = trim((string)($arrCfg['last_auto_run_at'] ?? ''));
|
||
$strSyncStatus = trim((string)($arrCfg['sync_status'] ?? ''));
|
||
$intNow = time();
|
||
$strWould = 'inconnu';
|
||
if (!$blnColsOk) {
|
||
$strWould = 'bloqué: SQL auto_sync manquant';
|
||
} elseif ($strSyncStatus === MSIN_API_CHRONOTRACK_SYNC_FERME) {
|
||
$strWould = 'ne tourne pas: événement Fermé';
|
||
} elseif ($strSyncStatus !== MSIN_API_CHRONOTRACK_SYNC_ACTIF) {
|
||
// MSIN-4574 — Lié ≠ Actif pour le cron
|
||
$strWould = 'ne tourne pas: statut « '
|
||
. fxChronotrackApiConfigStatusLabel($strSyncStatus)
|
||
. ' » — passer en Actif (Cycle de vie)';
|
||
} elseif (!$blnOn) {
|
||
$strWould = 'ne tourne pas: sync auto OFF';
|
||
} elseif ($strUntil === '' || $strUntil === '0000-00-00 00:00:00') {
|
||
$strWould = 'ne tourne pas: date de fin manquante';
|
||
} elseif (strtotime($strUntil) !== false && $intNow > strtotime($strUntil)) {
|
||
$strWould = 'ne tourne pas: date de fin dépassée (' . $strUntil . ')';
|
||
} elseif ($strLastRun !== '' && $strLastRun !== '0000-00-00 00:00:00'
|
||
&& strtotime($strLastRun) !== false
|
||
&& ($intNow - strtotime($strLastRun)) < ($intInterval * 60)) {
|
||
$strWould = 'en attente d’intervalle (dernier passage ' . $strLastRun
|
||
. ', fréquence ' . $intInterval . ' min)';
|
||
} else {
|
||
$strWould = 'devrait pousser au prochain appel de auto_chronotrack_sync.php';
|
||
}
|
||
|
||
return array(
|
||
'state' => 'ok',
|
||
'message' => $strWould,
|
||
'diag' => array(
|
||
'cols_ok' => $blnColsOk,
|
||
'cols_note' => $strColNote,
|
||
'auto_enabled' => $blnOn,
|
||
'sync_status' => $strSyncStatus,
|
||
'interval_min' => $intInterval,
|
||
'until' => $strUntil !== '' ? $strUntil : null,
|
||
'last_auto_run_at' => $strLastRun !== '' ? $strLastRun : null,
|
||
'log_count' => $intLogCnt,
|
||
'last_log' => is_array($arrLastLog) ? $arrLastLog : null,
|
||
'host' => isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '',
|
||
'would' => $strWould,
|
||
),
|
||
);
|
||
}
|
||
|