diff --git a/public/userarea/include/navbar.php b/public/userarea/include/navbar.php index 2b5f6d3..101588c 100644 --- a/public/userarea/include/navbar.php +++ b/public/userarea/include/navbar.php @@ -103,6 +103,14 @@ +
  • + +
    + +
    + +
    +
  • diff --git a/public/userarea/warm_cache.php b/public/userarea/warm_cache.php index 85152d9..ed5a632 100644 --- a/public/userarea/warm_cache.php +++ b/public/userarea/warm_cache.php @@ -6,6 +6,11 @@ $startTime = microtime(true); $isCli = (php_sapi_name() === 'cli'); +$isStream = (!$isCli && isset($_GET['stream'])); + +// Analisi incluse? Default SÌ (il cron non passa il parametro → fa tutto). +// Solo una richiesta HTTP con analisi=0 le salta. +$includeAnalisi = !(!$isCli && isset($_GET['analisi']) && $_GET['analisi'] === '0'); if (!$isCli) { // When called via HTTP, require auth @@ -15,7 +20,17 @@ if (!$isCli) { echo json_encode(['error' => 'Unauthorized']); exit; } - header('Content-Type: application/json'); + + if ($isStream) { + // Streaming mode: send progress line-by-line (Server-Sent Events) + set_time_limit(0); + header('Content-Type: text/event-stream'); + header('Cache-Control: no-cache'); + header('X-Accel-Buffering: no'); // disable nginx buffering + while (ob_get_level() > 0) ob_end_flush(); + } else { + header('Content-Type: application/json'); + } } require_once dirname(__DIR__, 2) . '/vendor/autoload.php'; @@ -23,15 +38,38 @@ require_once __DIR__ . '/class/VisualLimsApiClient.class.php'; require_once __DIR__ . '/class/db-functions.php'; $cacheDir = __DIR__ . '/cache'; -if (!is_dir($cacheDir)) mkdir($cacheDir, 0777, true); +if (!is_dir($cacheDir)) mkdir($cacheDir, 0755, true); $log = []; + +// Prevent two runs at the same time (e.g. cron + manual click) +$lockHandle = fopen($cacheDir . '/.warm.lock', 'w'); +if ($lockHandle === false || !flock($lockHandle, LOCK_EX | LOCK_NB)) { + $busyMsg = 'Un aggiornamento è già in corso in questo momento. Riprova tra poco.'; + if ($isCli) { + echo $busyMsg . PHP_EOL; + } elseif ($isStream) { + header('Content-Type: text/event-stream'); + echo "event: busy\ndata: " . $busyMsg . "\n\n"; + @flush(); + } else { + echo json_encode(['success' => false, 'busy' => true, 'message' => $busyMsg]); + } + exit; +} + function warmLog(string $msg, bool $isCli) { - global $log; + global $log, $isStream; $line = date('H:i:s') . " $msg"; $log[] = $line; - if ($isCli) echo $line . PHP_EOL; + if ($isCli) { + echo $line . PHP_EOL; + } elseif (!empty($isStream)) { + echo "data: " . str_replace("\n", ' ', $line) . "\n\n"; + @ob_flush(); + @flush(); + } } try { @@ -115,30 +153,38 @@ try { // 6. Analisi — only for matrici actually used by parts (warming all ~2500 matrici // would mean one API call each; the used set is a few dozen). - $stmt = $pdo->query("SELECT DISTINCT idmatrice FROM identification_parts WHERE idmatrice IS NOT NULL AND idmatrice > 0 ORDER BY idmatrice ASC"); - $matriceIds = $stmt->fetchAll(PDO::FETCH_COLUMN); - warmLog("[analisi] Fetching for " . count($matriceIds) . " matrici in use...", $isCli); + if (!$includeAnalisi) { + warmLog('[analisi] Saltate su richiesta.', $isCli); + } else { + $stmt = $pdo->query("SELECT DISTINCT idmatrice FROM identification_parts WHERE idmatrice IS NOT NULL AND idmatrice > 0 ORDER BY idmatrice ASC"); + $matriceIds = $stmt->fetchAll(PDO::FETCH_COLUMN); + warmLog("[analisi] Fetching for " . count($matriceIds) . " matrici in use...", $isCli); - foreach ($matriceIds as $mid) { - $mid = (int)$mid; - // Same query as get_analisi_matrice_filter.php with web_only=1 (what the analysis modal requests) - $filter = rawurlencode("Matrice/IdMatrice eq $mid and SelezionabileSuWeb eq true"); - try { - $data = $api->get("Analisi?\$filter={$filter}"); - $values = $data['value'] ?? []; - file_put_contents($cacheDir . '/analisi_matrice_' . $mid . '.json', json_encode(['value' => $values])); - warmLog("[analisi] Matrice $mid: " . count($values) . " analisi", $isCli); - } catch (Exception $e) { - warmLog("[analisi] Matrice $mid: ERROR " . $e->getMessage(), $isCli); + foreach ($matriceIds as $mid) { + $mid = (int)$mid; + // Same query as get_analisi_matrice_filter.php with web_only=1 (what the analysis modal requests) + $filter = rawurlencode("Matrice/IdMatrice eq $mid and SelezionabileSuWeb eq true"); + try { + $data = $api->get("Analisi?\$filter={$filter}"); + $values = $data['value'] ?? []; + file_put_contents($cacheDir . '/analisi_matrice_' . $mid . '.json', json_encode(['value' => $values])); + warmLog("[analisi] Matrice $mid: " . count($values) . " analisi", $isCli); + } catch (Exception $e) { + warmLog("[analisi] Matrice $mid: ERROR " . $e->getMessage(), $isCli); + } } - } + } // fine if includeAnalisi $elapsed = round(microtime(true) - $startTime, 1); - warmLog("Done in {$elapsed}s", $isCli); + warmLog("Aggiornamento completato in {$elapsed}s", $isCli); } catch (Exception $e) { - warmLog("FATAL: " . $e->getMessage(), $isCli); + $elapsed = round(microtime(true) - $startTime, 1); + warmLog("ERRORE: " . $e->getMessage(), $isCli); } -if (!$isCli) { +if ($isStream) { + echo "event: done\ndata: " . json_encode(['elapsed' => $elapsed ?? 0]) . "\n\n"; + @flush(); +} elseif (!$isCli) { echo json_encode(['success' => true, 'log' => $log]); } diff --git a/public/userarea/warm_cache_run.php b/public/userarea/warm_cache_run.php new file mode 100644 index 0000000..d9953d9 --- /dev/null +++ b/public/userarea/warm_cache_run.php @@ -0,0 +1,519 @@ +hasRole('Admin') && !$user->hasRole('SuperUser')) { + * header('Location: import_dashboard.php'); + * exit; + * } + */ +?> + + + + + + + + + + Aggiornamento dati - <?= htmlspecialchars($titlewebsite ?? 'SmartTRF', ENT_QUOTES, 'UTF-8'); ?> + + + + + +
    + + + +
    +
    + +
    +
    + +
    +
    +
    +
    Aggiornamento dati dal gestionale
    +

    + Ricarica clienti, matrici, analisi e le altre liste dal software di laboratorio. + Da usare quando sono state fatte modifiche sul gestionale e vuoi vederle subito + senza aspettare l'aggiornamento automatico. +

    +
    +
    + +
    + +
    + + +
    + + +
    + L'operazione può richiedere da qualche secondo a un paio di minuti. +
    + + +
    +
    + Aggiornamento in corso… + 0s +
    + +
    +
    0%
    +
    + +
      + +
    + + + +
    +
    
    +                            
    +
    + + +
    + + +
    + +
    +
    + +
    +
    + +
    + + +
    + + + + + + + \ No newline at end of file