diff --git a/public/certificate.php b/public/certificate.php new file mode 100644 index 0000000..9ba4133 --- /dev/null +++ b/public/certificate.php @@ -0,0 +1,52 @@ +getConnection(); +$id = (int) ($_GET['id'] ?? 0); + +$st = $pdo->prepare("SELECT * FROM certificateuserprofile WHERE idcertificateuserprofile = ? AND idschool = ?"); +$st->execute([$id, $idschool]); +$cert = $st->fetch(); + +$allowed = $cert && ((int) $cert['iduser'] === (int) $iduserlogin || SchoolContext::isStaff()); +if (!$allowed) { + http_response_code(404); + exit('Documento non trovato.'); +} + +// Percorsi possibili: archivio privato (futuro) e cartella storica pubblica +$name = basename((string) $cert['filenamedocument']); +$candidates = [ + dirname(__DIR__) . '/storage/app/certificates/' . (int) $cert['idschool'] . '/' . $name, + __DIR__ . '/user/document/' . $name, +]; +$path = null; +foreach ($candidates as $c) { + if (is_file($c)) { + $path = $c; + break; + } +} +if (!$path) { + http_response_code(404); + exit('File non disponibile.'); +} + +$mime = (new finfo(FILEINFO_MIME_TYPE))->file($path); +if (!in_array($mime, ['application/pdf', 'image/jpeg', 'image/png'], true)) { + http_response_code(415); + exit('Formato non supportato.'); +} + +header('Content-Type: ' . $mime); +header('Content-Length: ' . filesize($path)); +header('Content-Disposition: inline; filename="certificato-' . $id . '.' . pathinfo($name, PATHINFO_EXTENSION) . '"'); +header('X-Content-Type-Options: nosniff'); +header('Cache-Control: private, no-store'); +readfile($path); +exit; diff --git a/public/process.php b/public/process.php index 9cf3412..7b904e9 100644 --- a/public/process.php +++ b/public/process.php @@ -1,56 +1,52 @@ connect_error) { - die("Connessione fallita: " . $conn->connect_error); +/** + * Salvataggio profilo allievo (userprofile) per la scuola corrente. + * L'utente è SEMPRE quello loggato (nessun iduser dal form). + */ +if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + header('Location: userprofile.php'); + exit; } -if (isset($_POST['submit'])) { - $iduser = $_POST['iduser']; - $datebirth = $_POST['datebirth']; - $yogafor = $_POST['yogafor']; - $healthissue = $_POST['healthissue']; - $generalcomment = $_POST['generalcomment']; - $kind = $_POST['kind']; +$pdo = DBHandlerSelect::getInstance()->getConnection(); +$iduser = (int) $iduserlogin; -if ($kind=='insert') { - // Inserimento dei dati nel database - $sql = "INSERT INTO userprofile (iduser, datebirth, yogafor, healthissue, generalcomment) - VALUES ('$iduser', '$datebirth', '$yogafor', '$healthissue', '$generalcomment') - ON DUPLICATE KEY UPDATE - datebirth = '$datebirth', yogafor = '$yogafor', healthissue = '$healthissue', generalcomment = '$generalcomment'"; +$datebirth = trim((string) ($_POST['datebirth'] ?? '')); +if ($datebirth !== '' && !DateTime::createFromFormat('Y-m-d', $datebirth)) { + header('Location: userprofile.php?message=baddate'); + exit; +} - if ($conn->query($sql) === TRUE) { - echo "Dati inseriti/aggiornati con successo."; +$data = [ + ':datebirth' => $datebirth !== '' ? $datebirth : null, + ':yogafor' => trim((string) ($_POST['yogafor'] ?? '')), + ':healthissue' => trim((string) ($_POST['healthissue'] ?? '')), + ':generalcomment' => trim((string) ($_POST['generalcomment'] ?? '')), + ':iduser' => $iduser, + ':idschool' => $idschool, +]; + +try { + $st = $pdo->prepare("SELECT iduserprofile FROM userprofile WHERE iduser = ? AND idschool = ? LIMIT 1"); + $st->execute([$iduser, $idschool]); + + if ($st->fetchColumn()) { + $pdo->prepare( + "UPDATE userprofile + SET datebirth = :datebirth, yogafor = :yogafor, healthissue = :healthissue, generalcomment = :generalcomment + WHERE iduser = :iduser AND idschool = :idschool" + )->execute($data); } else { - echo "Errore nell'esecuzione della query: " . $conn->error; + $pdo->prepare( + "INSERT INTO userprofile (iduser, idschool, datebirth, yogafor, healthissue, generalcomment) + VALUES (:iduser, :idschool, :datebirth, :yogafor, :healthissue, :generalcomment)" + )->execute($data); } - - - - - - - header("Location: userprofile.php?message=success"); - exit(); - -} else { - // Update dei dati nel database - $sql = "UPDATE userprofile SET datebirth = '$datebirth', yogafor = '$yogafor', healthissue = '$healthissue', generalcomment = '$generalcomment' - WHERE iduser='$iduser'"; - - - if ($conn->query($sql) === TRUE) { - echo "Dati inseriti/aggiornati con successo."; - } else { - echo "Errore nell'esecuzione della query: " . $conn->error; - } - header("Location: userprofile.php?message=success"); - exit(); + header('Location: userprofile.php?message=success'); +} catch (Throwable $ex) { + error_log('process.php (user ' . $iduser . '): ' . $ex->getMessage()); + header('Location: userprofile.php?message=error'); } - -} - -$conn->close(); -?> \ No newline at end of file +exit; diff --git a/public/userprofile.php b/public/userprofile.php index 2aad169..ff7964d 100644 --- a/public/userprofile.php +++ b/public/userprofile.php @@ -2,7 +2,8 @@ require_once('include/headscript.php'); /** - * Connessione unica PDO (singleton). $iduserlogin dalla sessione autenticata. + * Profilo allievo per la scuola corrente (dati personali e di salute). + * Il salvataggio avviene in process.php. I certificati si gestiscono in userprofiledoc.php. */ $pdo = DBHandlerSelect::getInstance()->getConnection(); $iduserlogin = (int) $iduserlogin; @@ -12,101 +13,28 @@ function e($value): string return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); } -$message = isset($_GET['message']) ? $_GET['message'] : ''; -$uploadFeedback = null; // ['type' => 'success'|'error', 'text' => '...'] +$message = $_GET['message'] ?? ''; -/* ------------------------------------------------------------------------- - * Gestione upload certificato (POST) — con validazione robusta - * ---------------------------------------------------------------------- */ -$allowedExt = ['pdf', 'jpg', 'jpeg', 'png']; -$allowedMime = ['application/pdf', 'image/jpeg', 'image/png']; -$maxBytes = 8 * 1024 * 1024; // 8 MB -$uploadDir = 'user/document/'; +$stmtProfile = $pdo->prepare("SELECT * FROM userprofile WHERE iduser = ? AND idschool = ? LIMIT 1"); +$stmtProfile->execute([$iduserlogin, $idschool]); +$rowdata = $stmtProfile->fetch() ?: []; -if ( - $_SERVER['REQUEST_METHOD'] === 'POST' - && isset($_FILES['fileToUpload']) - && $_FILES['fileToUpload']['error'] === UPLOAD_ERR_OK -) { +$datebirthFromDatabase = $rowdata['datebirth'] ?? ''; +$yogaforFromDatabase = $rowdata['yogafor'] ?? ''; +$healthissueFromDatabase = $rowdata['healthissue'] ?? ''; +$generalcommentFromDatabase = $rowdata['generalcomment'] ?? ''; +$isUpdate = !empty($rowdata); - $file = $_FILES['fileToUpload']; - $documentDescription = trim($_POST['documentDescription'] ?? ''); - $expiryDate = trim($_POST['expiryDate'] ?? ''); +// Numero certificati validi (per il riquadro di collegamento) +$stmtCert = $pdo->prepare( + "SELECT COUNT(*) FROM certificateuserprofile + WHERE iduser = ? AND idschool = ? AND (expirydatedocument IS NULL OR expirydatedocument >= CURDATE())" +); +$stmtCert->execute([$iduserlogin, $idschool]); +$validCertificates = (int) $stmtCert->fetchColumn(); - // 1) Dimensione - if ($file['size'] > $maxBytes) { - $uploadFeedback = ['type' => 'error', 'text' => 'Il file supera la dimensione massima di 8 MB.']; - } else { - // 2) Estensione - $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); - // 3) Tipo MIME reale (non ci fidiamo dell'estensione dichiarata) - $finfo = new finfo(FILEINFO_MIME_TYPE); - $realMime = $finfo->file($file['tmp_name']); - - if (!in_array($ext, $allowedExt, true) || !in_array($realMime, $allowedMime, true)) { - $uploadFeedback = ['type' => 'error', 'text' => 'Formato non consentito. Carica un PDF, JPG o PNG.']; - } else { - // 4) Nome file sicuro generato dal server (niente input utente nel percorso) - $safeName = bin2hex(random_bytes(16)) . '.' . $ext; - $destination = $uploadDir . $safeName; - - if (!is_dir($uploadDir)) { - @mkdir($uploadDir, 0755, true); - } - - if (move_uploaded_file($file['tmp_name'], $destination)) { - // 5) INSERT con prepared statement - $sql = "INSERT INTO certificateuserprofile - (iduser, documentdescription, filenamedocument, expirydatedocument) - VALUES (:iduser, :descr, :fname, :expiry)"; - $stmt = $pdo->prepare($sql); - $ok = $stmt->execute([ - ':iduser' => $iduserlogin, - ':descr' => $documentDescription, - ':fname' => $safeName, - ':expiry' => $expiryDate !== '' ? $expiryDate : null, - ]); - - $uploadFeedback = $ok - ? ['type' => 'success', 'text' => 'Documento caricato correttamente.'] - : ['type' => 'error', 'text' => 'Errore nel salvataggio del documento. Riprova.']; - } else { - $uploadFeedback = ['type' => 'error', 'text' => 'Caricamento del file non riuscito. Riprova.']; - } - } - } -} elseif ( - $_SERVER['REQUEST_METHOD'] === 'POST' - && isset($_FILES['fileToUpload']) - && $_FILES['fileToUpload']['error'] !== UPLOAD_ERR_NO_FILE -) { - // Un file è stato scelto ma l'upload è fallito lato PHP - $uploadFeedback = ['type' => 'error', 'text' => 'Si è verificato un problema durante il caricamento. Riprova.']; -} - -/* ------------------------------------------------------------------------- - * Dati profilo utente - * ---------------------------------------------------------------------- */ -$idprofile = null; -$datebirthFromDatabase = ''; -$yogaforFromDatabase = ''; -$healthissueFromDatabase = ''; -$generalcommentFromDatabase = ''; - -$stmtProfile = $pdo->prepare("SELECT * FROM userprofile WHERE iduser = :iduser LIMIT 1"); -$stmtProfile->execute([':iduser' => $iduserlogin]); -$rowdata = $stmtProfile->fetch(); - -if ($rowdata) { - $idprofile = $rowdata['iduserprofile']; - $datebirthFromDatabase = $rowdata['datebirth'] ?? ''; - $yogaforFromDatabase = $rowdata['yogafor'] ?? ''; - $healthissueFromDatabase = $rowdata['healthissue'] ?? ''; - $generalcommentFromDatabase = $rowdata['generalcomment'] ?? ''; -} - -$isUpdate = !empty($idprofile); $currentYear = date('Y'); +$uploadFeedback = null; ?> @@ -309,9 +237,11 @@ $currentYear = date('Y');
- + + + + + @@ -327,8 +257,6 @@ $currentYear = date('Y');

Compila o aggiorna le informazioni del tuo profilo.

- -
@@ -358,38 +286,18 @@ $currentYear = date('Y');
- +
-
-
Certificati e documenti
-

Carica il tuo certificato medico o altri documenti (PDF, JPG o PNG, max 8 MB).

- - -
- - -
- -
- - -
Lascia vuoto se il documento non ha scadenza.
-
- -
- - - -
- - - +
+
+
Certificato medico
+ 0) : ?> +

Hai un certificato valido caricato.

+ +

Nessun certificato valido: caricalo per praticare.

+ +
+ Gestisci certificati
diff --git a/public/userprofiledoc.php b/public/userprofiledoc.php index a48ebb3..6b08fbb 100644 --- a/public/userprofiledoc.php +++ b/public/userprofiledoc.php @@ -2,7 +2,8 @@ require_once('include/headscript.php'); /** - * Connessione unica PDO (singleton). $iduserlogin dalla sessione autenticata. + * Certificati medici dell'allievo per la scuola corrente: elenco e caricamento. + * I file si aprono tramite certificate.php (controllo permessi). */ $pdo = DBHandlerSelect::getInstance()->getConnection(); $iduserlogin = (int) $iduserlogin; @@ -12,57 +13,45 @@ function e($value): string return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); } -$uploadFeedback = null; // ['type' => 'success'|'error', 'text' => '...'] +$uploadFeedback = null; /* ------------------------------------------------------------------------- - * Upload certificato (POST) con validazione robusta + * Upload certificato (POST) * ---------------------------------------------------------------------- */ $allowedExt = ['pdf', 'jpg', 'jpeg', 'png']; $allowedMime = ['application/pdf', 'image/jpeg', 'image/png']; $maxBytes = 16 * 1024 * 1024; // 16 MB -$uploadDir = 'user/document/'; - -if ( - $_SERVER['REQUEST_METHOD'] === 'POST' - && isset($_FILES['fileToUpload']) - && $_FILES['fileToUpload']['error'] === UPLOAD_ERR_OK -) { +// Cartella storica: verrà spostata fuori da public insieme a certificati.php e alle API +$uploadDir = __DIR__ . '/user/document/'; +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['fileToUpload'])) { $file = $_FILES['fileToUpload']; $documentDescription = trim($_POST['documentDescription'] ?? ''); $expiryDate = trim($_POST['expiryDate'] ?? ''); - if ($documentDescription === '' || $expiryDate === '') { - $uploadFeedback = ['type' => 'error', 'text' => 'Descrizione e data di scadenza sono obbligatorie.']; + if ($file['error'] !== UPLOAD_ERR_OK) { + $uploadFeedback = ['type' => 'error', 'text' => 'Si è verificato un problema durante il caricamento. Riprova.']; + } elseif ($documentDescription === '' || !DateTime::createFromFormat('Y-m-d', $expiryDate)) { + $uploadFeedback = ['type' => 'error', 'text' => 'Descrizione e data di scadenza valida sono obbligatorie.']; } elseif ($file['size'] > $maxBytes) { $uploadFeedback = ['type' => 'error', 'text' => 'Il file supera la dimensione massima di 16 MB.']; } else { $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); - $finfo = new finfo(FILEINFO_MIME_TYPE); - $realMime = $finfo->file($file['tmp_name']); + $realMime = (new finfo(FILEINFO_MIME_TYPE))->file($file['tmp_name']); if (!in_array($ext, $allowedExt, true) || !in_array($realMime, $allowedMime, true)) { $uploadFeedback = ['type' => 'error', 'text' => 'Formato non consentito. Carica un PDF, JPG o PNG.']; } else { $safeName = bin2hex(random_bytes(16)) . '.' . $ext; - $destination = $uploadDir . $safeName; - if (!is_dir($uploadDir)) { @mkdir($uploadDir, 0755, true); } - - if (move_uploaded_file($file['tmp_name'], $destination)) { - $sql = "INSERT INTO certificateuserprofile - (iduser, documentdescription, filenamedocument, expirydatedocument, uploaded_at) - VALUES (:iduser, :descr, :fname, :expiry, :uploaded)"; - $stmt = $pdo->prepare($sql); - $ok = $stmt->execute([ - ':iduser' => $iduserlogin, - ':descr' => $documentDescription, - ':fname' => $safeName, - ':expiry' => $expiryDate, - ':uploaded' => date('Y-m-d'), - ]); + if (move_uploaded_file($file['tmp_name'], $uploadDir . $safeName)) { + $ok = $pdo->prepare( + "INSERT INTO certificateuserprofile + (idschool, iduser, documentdescription, filenamedocument, expirydatedocument, uploaded_at) + VALUES (?, ?, ?, ?, ?, ?)" + )->execute([$idschool, $iduserlogin, $documentDescription, $safeName, $expiryDate, date('Y-m-d')]); $uploadFeedback = $ok ? ['type' => 'success', 'text' => 'Documento caricato correttamente.'] @@ -72,19 +61,15 @@ if ( } } } -} elseif ( - $_SERVER['REQUEST_METHOD'] === 'POST' - && isset($_FILES['fileToUpload']) - && $_FILES['fileToUpload']['error'] !== UPLOAD_ERR_NO_FILE -) { - $uploadFeedback = ['type' => 'error', 'text' => 'Si è verificato un problema durante il caricamento. Riprova.']; } /* ------------------------------------------------------------------------- - * Elenco documenti dell'utente + * Elenco documenti dell'utente nella scuola corrente * ---------------------------------------------------------------------- */ -$stmtDocs = $pdo->prepare("SELECT * FROM certificateuserprofile WHERE iduser = :iduser ORDER BY uploaded_at DESC"); -$stmtDocs->execute([':iduser' => $iduserlogin]); +$stmtDocs = $pdo->prepare( + "SELECT * FROM certificateuserprofile WHERE iduser = ? AND idschool = ? ORDER BY uploaded_at DESC, idcertificateuserprofile DESC" +); +$stmtDocs->execute([$iduserlogin, $idschool]); $documents = $stmtDocs->fetchAll(); ?> @@ -374,9 +359,14 @@ $documents = $stmtDocs->fetchAll(); - - + + + Scaduto + + + Apri