hasRole('Admin') && !$user->hasRole('SuperUser')) { header('Location: import_dashboard.php'); exit; } $db = DBHandlerSelect::getInstance(); $pdo = $db->getConnection(); /* * Nome file del motore generico condiviso da tutte le routine engine. * Deve corrispondere al file presente in routines/. */ $engineFilename = '_engine.php'; /* * CSRF token. */ if (empty($_SESSION['routine_admin_csrf'])) { $_SESSION['routine_admin_csrf'] = bin2hex(random_bytes(32)); } $csrfToken = $_SESSION['routine_admin_csrf']; function cleanInput($value) { return trim((string)($value ?? '')); } function redirectWithMessage($type, $message) { $_SESSION['routine_admin_flash'] = [ 'type' => $type, 'message' => $message ]; header('Location: ' . $_SERVER['PHP_SELF']); exit; } /* * Gestione azioni POST. */ if ($_SERVER['REQUEST_METHOD'] === 'POST') { try { $postedToken = $_POST['csrf_token'] ?? ''; if (!hash_equals($csrfToken, $postedToken)) { throw new Exception('Token di sicurezza non valido.'); } $action = cleanInput($_POST['action'] ?? ''); if ($action === 'create' || $action === 'update') { $name = cleanInput($_POST['name'] ?? ''); $description = cleanInput($_POST['description'] ?? ''); $engine = (int)($_POST['engine'] ?? 0) === 1 ? 1 : 0; $headerrow = (int)($_POST['headerrow'] ?? 1); $filename = cleanInput($_POST['filename'] ?? ''); if ($name === '') { throw new Exception('Il nome della routine è obbligatorio.'); } if ($headerrow < 1) { $headerrow = 1; } /* * Se è una routine a motore, il filename è forzato al file del motore. * Se è legacy, serve un filename di file reale. */ if ($engine === 1) { $filename = $GLOBALS['engineFilename']; } else { if ($filename === '') { throw new Exception('Per una routine di tipo File indica il nome del file (es. fendi.php).'); } } if ($action === 'create') { // instruction è NOT NULL nello schema: valorizziamo sempre. $instruction = $engine === 1 ? 'Routine gestita dal motore generico (routine_step).' : ('Routine su file: ' . $filename); $stmt = $pdo->prepare(" INSERT INTO routine (name, description, instruction, filename, engine, headerrow) VALUES (:name, :descr, :instr, :fn, :engine, :hr) "); $stmt->execute([ ':name' => $name, ':descr' => ($description !== '' ? $description : null), ':instr' => $instruction, ':fn' => $filename, ':engine' => $engine, ':hr' => $headerrow, ]); redirectWithMessage('success', 'Routine creata correttamente.'); } else { $idroutine = (int)($_POST['idroutine'] ?? 0); if ($idroutine <= 0) { throw new Exception('ID routine non valido.'); } $stmt = $pdo->prepare(" UPDATE routine SET name = :name, description = :descr, filename = :fn, engine = :engine, headerrow = :hr WHERE idroutine = :id "); $stmt->execute([ ':name' => $name, ':descr' => ($description !== '' ? $description : null), ':fn' => $filename, ':engine' => $engine, ':hr' => $headerrow, ':id' => $idroutine, ]); redirectWithMessage('success', 'Routine aggiornata correttamente.'); } } if ($action === 'delete') { $idroutine = (int)($_POST['idroutine'] ?? 0); if ($idroutine <= 0) { throw new Exception('ID routine non valido.'); } // Rimuove prima gli eventuali step collegati, poi la routine. $stmt = $pdo->prepare("DELETE FROM routine_step WHERE idroutine = :id"); $stmt->execute([':id' => $idroutine]); $stmt = $pdo->prepare("DELETE FROM routine WHERE idroutine = :id"); $stmt->execute([':id' => $idroutine]); redirectWithMessage('success', 'Routine eliminata correttamente.'); } throw new Exception('Azione non valida.'); } catch (Exception $e) { redirectWithMessage('error', $e->getMessage()); } } /* * Caricamento routine + conteggio step. */ $stmt = $pdo->query(" SELECT r.idroutine, r.name, r.description, r.filename, r.engine, r.headerrow, (SELECT COUNT(*) FROM routine_step s WHERE s.idroutine = r.idroutine) AS step_count FROM routine r ORDER BY r.name ASC "); $routines = $stmt->fetchAll(PDO::FETCH_ASSOC); $flash = $_SESSION['routine_admin_flash'] ?? null; unset($_SESSION['routine_admin_flash']); ?>