Files
xamxam/app/public/admin/actions/cleanup-stats.php

193 lines
5.7 KiB
PHP

<?php
/**
* Temp file statistics endpoint (admin).
*
* GET /admin/actions/cleanup-stats.php
*
* Returns JSON with counts and sizes of tmp/filepond/ and tmp/_trash/,
* broken down by stale (will be cleaned) vs active (still session-bound).
*/
require_once __DIR__ . '/../../../bootstrap.php';
require_once __DIR__ . '/../../../src/AdminAuth.php';
AdminAuth::requireLogin();
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
exit;
}
$storageRoot = STORAGE_ROOT;
$filepondDir = $storageRoot . '/tmp/filepond';
$trashDir = $storageRoot . '/tmp/_trash';
$maxAgeFilepond = 7200; // 2h
$maxAgeTrash = 2592000; // 30d
$sessionSavePath = session_save_path();
if (!$sessionSavePath || $sessionSavePath === '') {
$sessionSavePath = sys_get_temp_dir();
}
$now = time();
// ── FilePond stats ───────────────────────────────────────────────────────
$fpStaleCount = 0;
$fpStaleSize = 0;
$fpActiveCount = 0;
$fpActiveSize = 0;
if (is_dir($filepondDir)) {
$items = @scandir($filepondDir);
if ($items !== false) {
foreach ($items as $item) {
if ($item === '.' || $item === '..' || $item === '.gitkeep') {
continue;
}
$dirPath = $filepondDir . '/' . $item;
if (!is_dir($dirPath)) {
continue;
}
$size = dirSizeRecursive($dirPath);
$mtime = filemtime($dirPath);
$ageMinutes = (int)(($now - $mtime) / 60);
$stale = false;
// Session-based detection
$manifestPath = $dirPath . '/manifest.json';
if (file_exists($manifestPath)) {
$manifest = json_decode(file_get_contents($manifestPath), true);
if (is_array($manifest) && !empty($manifest['session_id'])) {
$sessionFile = $sessionSavePath . '/sess_' . $manifest['session_id'];
if (!file_exists($sessionFile)) {
$stale = true;
}
}
}
// Time-based fallback
if (!$stale && $ageMinutes > ($maxAgeFilepond / 60)) {
$stale = true;
}
if ($stale) {
$fpStaleCount++;
$fpStaleSize += $size;
} else {
$fpActiveCount++;
$fpActiveSize += $size;
}
}
}
}
// ── Trash stats ──────────────────────────────────────────────────────────
require_once __DIR__ . '/../../../src/Database.php';
$db = new Database();
$pdo = $db->getPDO();
$existingFileIds = [];
$stmt = $pdo->query('SELECT id FROM thesis_files');
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$existingFileIds[(int)$row['id']] = true;
}
$trStaleCount = 0;
$trStaleSize = 0;
$trActiveCount = 0;
$trActiveSize = 0;
if (is_dir($trashDir)) {
$items = @scandir($trashDir);
if ($items !== false) {
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
$filePath = $trashDir . '/' . $item;
if (!is_file($filePath)) {
continue;
}
$size = filesize($filePath);
$mtime = filemtime($filePath);
$ageDays = (int)(($now - $mtime) / 86400);
$stale = false;
if (preg_match('/^(\d+)_/', $item, $m)) {
$dbId = (int)$m[1];
if (!isset($existingFileIds[$dbId])) {
$stale = true;
}
}
if (!$stale && $ageDays > ($maxAgeTrash / 86400)) {
$stale = true;
}
if ($stale) {
$trStaleCount++;
$trStaleSize += $size;
} else {
$trActiveCount++;
$trActiveSize += $size;
}
}
}
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'filepond_stale_count' => $fpStaleCount,
'filepond_stale_size' => $fpStaleSize,
'filepond_stale_human' => humanBytes($fpStaleSize),
'filepond_active_count' => $fpActiveCount,
'filepond_active_size' => $fpActiveSize,
'filepond_active_human' => humanBytes($fpActiveSize),
'trash_stale_count' => $trStaleCount,
'trash_stale_size' => $trStaleSize,
'trash_stale_human' => humanBytes($trStaleSize),
'trash_active_count' => $trActiveCount,
'trash_active_size' => $trActiveSize,
'trash_active_human' => humanBytes($trActiveSize),
]);
// ── Helpers ───────────────────────────────────────────────────────────────
function dirSizeRecursive(string $dir): int
{
$size = 0;
if (!is_dir($dir)) {
return 0;
}
$items = @scandir($dir);
if ($items === false) {
return 0;
}
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
$path = $dir . '/' . $item;
if (is_dir($path)) {
$size += dirSizeRecursive($path);
} else {
$size += filesize($path);
}
}
return $size;
}
function humanBytes(int $bytes): string
{
if ($bytes > 1073741824) {
return number_format($bytes / 1073741824, 1) . ' GB';
}
if ($bytes > 1048576) {
return number_format($bytes / 1048576, 1) . ' MB';
}
return number_format($bytes / 1024, 1) . ' KB';
}