From a19c5c838191a3c684a9f7ee9dc529793bad2c1e Mon Sep 17 00:00:00 2001 From: Esteban Date: Fri, 3 Jul 2026 02:02:13 +0200 Subject: [PATCH] Fix lag --- .gitignore | 9 ++++++ captcha.php | 2 +- database/scriptDatabase.sql | 63 ++++++++++++++++++++++++++++++++++++- elements/footer.php | 3 +- elements/header.php | 27 +++++++++++++++- functions/listLogos.php | 2 +- functions/listProject.php | 29 ++++++++++++----- functions/listSchool.php | 26 ++++++++++++--- functions/listSkills.php | 2 +- functions/listStats.php | 27 ++++++++++++++++ functions/listUser.php | 2 +- functions/listXP.php | 32 +++++++++++++------ functions/security.php | 48 ++++++++++++++++++++++++++++ index.php | 2 +- pages/admin.php | 10 +++++- pages/details.php | 21 ++++++++----- pages/home.php | 27 ++++++++++++++++ scripts/addLogo.php | 5 ++- scripts/addProject.php | 22 ++++++++++--- scripts/addSchool.php | 22 ++++++++++--- scripts/addSkill.php | 5 ++- scripts/addUser.php | 5 ++- scripts/addXP.php | 22 ++++++++++--- scripts/checkLogin.php | 7 ++++- scripts/disconnect.php | 5 +-- scripts/exportData.php | 30 ++++++++++++------ scripts/importData.php | 31 +++++++++++------- scripts/removeLogo.php | 5 ++- scripts/removeProject.php | 5 ++- scripts/removeSchool.php | 5 ++- scripts/removeSkill.php | 5 ++- scripts/removeUser.php | 5 ++- scripts/removeXP.php | 5 ++- scripts/sendMessage.php | 2 +- scripts/updateLogo.php | 5 ++- scripts/updateProject.php | 42 +++++++++++++++++-------- scripts/updateSchool.php | 42 +++++++++++++++++-------- scripts/updateSettings.php | 5 ++- scripts/updateSkill.php | 5 ++- scripts/updateXP.php | 42 +++++++++++++++++-------- scripts/viewPdf.php | 10 +++--- styles/primary_css.css | 38 ++++++++++++++++++++++ 42 files changed, 578 insertions(+), 129 deletions(-) create mode 100644 .gitignore create mode 100644 functions/listStats.php create mode 100644 functions/security.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30efe56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Config Claude Code (local, pas utile au dépôt) +.claude/ + +# macOS +.DS_Store + +# Éditeurs +.vscode/ +.idea/ diff --git a/captcha.php b/captcha.php index db19866..4bc8f56 100644 --- a/captcha.php +++ b/captcha.php @@ -1,5 +1,5 @@ @@ -31,6 +40,22 @@ $currentPage = basename($_SERVER['PHP_SELF']); <?php echo htmlspecialchars($pageTitle); ?> + + + + + + + + + + + + + + + + diff --git a/functions/listLogos.php b/functions/listLogos.php index 8f335ae..73f5cef 100644 --- a/functions/listLogos.php +++ b/functions/listLogos.php @@ -118,7 +118,7 @@ function afficherLogosAdmin() { echo ''; echo '
'; echo 'Modifier'; - echo 'Supprimer'; + echo 'Supprimer'; echo '
'; echo ''; } diff --git a/functions/listProject.php b/functions/listProject.php index da36552..ecdc508 100644 --- a/functions/listProject.php +++ b/functions/listProject.php @@ -10,15 +10,22 @@ function listeProjets() { // Essayer try { - // Requête SQL qui récupère titre, tags, description, image_url - // SELECT * : les colonnes markdown / link_url sont optionnelles (la page fonctionne - // même si la migration SQL n'a pas encore été exécutée) - $stmt = $dbh->prepare('SELECT * FROM projects ORDER BY id DESC'); + // On liste les colonnes explicitement (pas de SELECT *) : le PDF (pdf_data) est + // stocké à part dans project_pdfs (voir migration Juillet 2026 (6)), on ne récupère + // ici que son nom de fichier via LEFT JOIN, sans jamais charger son contenu binaire + // (jusqu'à 15 Mo par PDF) en mémoire pour une simple liste de projets + $stmt = $dbh->prepare(' + SELECT p.id, p.title, p.status, p.tags, p.description, p.image_url, p.markdown, p.link_url, p.created_at, + pp.pdf_filename + FROM projects p + LEFT JOIN project_pdfs pp ON pp.project_id = p.id + ORDER BY p.id DESC + '); // Execution de la requête SQL $stmt->execute(); // Retourne toutes les données collectés dans un ARRAY return $stmt->fetchAll(PDO::FETCH_ASSOC); - } catch (PDOException $e) { // En cas d'erreur + } catch (PDOException $e) { // En cas d'erreur die("Erreur de connexion à la base de donnée portfolio :".$e->getMessage()); return []; } @@ -29,7 +36,15 @@ function recupererProjetParId($id) { global $dbh; try { - $stmt = $dbh->prepare('SELECT * FROM projects WHERE id = :id'); + // Même principe que listeProjets() : le PDF est joint pour son nom de fichier + // uniquement, jamais son contenu binaire + $stmt = $dbh->prepare(' + SELECT p.id, p.title, p.status, p.tags, p.description, p.image_url, p.markdown, p.link_url, p.created_at, + pp.pdf_filename + FROM projects p + LEFT JOIN project_pdfs pp ON pp.project_id = p.id + WHERE p.id = :id + '); $stmt->bindValue(':id', $id, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetch(PDO::FETCH_ASSOC); @@ -164,7 +179,7 @@ function afficherProjetsAdmin() { // Boutons qui vont permettrent la modification / Suppresion echo '
'; echo 'Modifier'; - echo 'Supprimer'; + echo 'Supprimer'; echo '
'; echo ''; diff --git a/functions/listSchool.php b/functions/listSchool.php index facfd56..b871ec6 100644 --- a/functions/listSchool.php +++ b/functions/listSchool.php @@ -10,9 +10,17 @@ function listeEcoles() { global $dbh; try { - // SELECT * : les colonnes markdown / link_url sont optionnelles (la page fonctionne - // même si la migration SQL n'a pas encore été exécutée) - $stmt = $dbh->prepare('SELECT * FROM schools ORDER BY id DESC'); + // On liste les colonnes explicitement (pas de SELECT *) : le PDF (pdf_data) est + // stocké à part dans school_pdfs (voir migration Juillet 2026 (6)), on ne récupère + // ici que son nom de fichier via LEFT JOIN, sans jamais charger son contenu binaire + // (jusqu'à 15 Mo par PDF) en mémoire pour une simple liste d'écoles + $stmt = $dbh->prepare(' + SELECT s.id, s.title, s.status, s.tags, s.description, s.duration, s.image_url, s.markdown, s.link_url, s.created_at, + sp.pdf_filename + FROM schools s + LEFT JOIN school_pdfs sp ON sp.school_id = s.id + ORDER BY s.id DESC + '); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { @@ -25,7 +33,15 @@ function recupererEcoleParId($id) { global $dbh; try { - $stmt = $dbh->prepare('SELECT * FROM schools WHERE id = :id'); + // Même principe que listeEcoles() : le PDF est joint pour son nom de fichier + // uniquement, jamais son contenu binaire + $stmt = $dbh->prepare(' + SELECT s.id, s.title, s.status, s.tags, s.description, s.duration, s.image_url, s.markdown, s.link_url, s.created_at, + sp.pdf_filename + FROM schools s + LEFT JOIN school_pdfs sp ON sp.school_id = s.id + WHERE s.id = :id + '); $stmt->bindValue(':id', $id, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetch(PDO::FETCH_ASSOC); @@ -98,7 +114,7 @@ function afficherEcoleCard($ecole, $admin = false) { if ($admin) { echo '
'; echo 'Modifier'; - echo 'Supprimer'; + echo 'Supprimer'; echo '
'; } diff --git a/functions/listSkills.php b/functions/listSkills.php index 7b0562b..6972ceb 100644 --- a/functions/listSkills.php +++ b/functions/listSkills.php @@ -99,7 +99,7 @@ function afficherSkillCard($skill, $admin = false) { if ($admin) { echo '
'; echo 'Modifier'; - echo 'Supprimer'; + echo 'Supprimer'; echo '
'; } diff --git a/functions/listStats.php b/functions/listStats.php new file mode 100644 index 0000000..1015090 --- /dev/null +++ b/functions/listStats.php @@ -0,0 +1,27 @@ + 0, 'experiences' => 0]; + + try { + $stats['projets'] = (int) $dbh->query('SELECT COUNT(*) FROM projects')->fetchColumn(); + } catch (PDOException $e) { + // Table pas encore créée : on laisse le compteur à 0 + } + + try { + $stats['experiences'] = (int) $dbh->query('SELECT COUNT(*) FROM experiences')->fetchColumn(); + } catch (PDOException $e) { + // Table pas encore créée : on laisse le compteur à 0 + } + + return $stats; +} diff --git a/functions/listUser.php b/functions/listUser.php index 1c3c69c..f7c0470 100644 --- a/functions/listUser.php +++ b/functions/listUser.php @@ -19,7 +19,7 @@ function afficherUsersAdmin() echo '

Créé le : ' . htmlspecialchars($user["created_at"]) . '

'; echo '
'; - echo 'Supprimer'; + echo 'Supprimer'; echo '
'; echo ''; diff --git a/functions/listXP.php b/functions/listXP.php index 6cf7551..dc24e65 100644 --- a/functions/listXP.php +++ b/functions/listXP.php @@ -13,15 +13,22 @@ function listeXP() { // Essayer try { - // Requête SQL qui récupère titre, type, tags, description, durée, image_url - // SELECT * : les colonnes markdown / link_url sont optionnelles (la page fonctionne - // même si la migration SQL n'a pas encore été exécutée) - $stmt = $dbh->prepare('SELECT * FROM experiences ORDER BY id DESC'); + // On liste les colonnes explicitement (pas de SELECT *) : le PDF (pdf_data) est + // stocké à part dans experience_pdfs (voir migration Juillet 2026 (6)), on ne + // récupère ici que son nom de fichier via LEFT JOIN, sans jamais charger son contenu + // binaire (jusqu'à 15 Mo par PDF) en mémoire pour une simple liste d'expériences + $stmt = $dbh->prepare(' + SELECT e.id, e.title, e.status, e.xptype, e.tags, e.description, e.duration, e.image_url, e.markdown, e.link_url, e.created_at, + ep.pdf_filename + FROM experiences e + LEFT JOIN experience_pdfs ep ON ep.experience_id = e.id + ORDER BY e.id DESC + '); // Execution de la requête SQL $stmt->execute(); // Retourne toutes les données collectés dans un ARRAY return $stmt->fetchAll(PDO::FETCH_ASSOC); - } catch (PDOException $e) { // En cas d'erreur + } catch (PDOException $e) { // En cas d'erreur die("Erreur de connexion à la base de donnée portfolio :".$e->getMessage()); return []; } @@ -32,13 +39,20 @@ function recupererXPParId($id) { global $dbh; try { - // Préparation de la requête préparée - $stmt = $dbh->prepare('SELECT * FROM experiences WHERE id = :id'); + // Même principe que listeXP() : le PDF est joint pour son nom de fichier + // uniquement, jamais son contenu binaire + $stmt = $dbh->prepare(' + SELECT e.id, e.title, e.status, e.xptype, e.tags, e.description, e.duration, e.image_url, e.markdown, e.link_url, e.created_at, + ep.pdf_filename + FROM experiences e + LEFT JOIN experience_pdfs ep ON ep.experience_id = e.id + WHERE e.id = :id + '); $stmt->bindValue(':id', $id, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetch(PDO::FETCH_ASSOC); - // En cas d'erreur => renvoyer un message avec l'erreur + // En cas d'erreur => renvoyer un message avec l'erreur } catch (PDOException $e) { die("Erreur de connexion à la base de donnée portfolio :" . $e->getMessage()); // Retourner false en cas d'eerreur @@ -195,7 +209,7 @@ function afficherXPAdmin() { // Boutons qui vont permettrent la modification / Suppresion echo '
'; echo 'Modifier'; - echo 'Supprimer'; + echo 'Supprimer'; echo '
'; echo ''; diff --git a/functions/security.php b/functions/security.php new file mode 100644 index 0000000..dbea165 --- /dev/null +++ b/functions/security.php @@ -0,0 +1,48 @@ + 0, + 'path' => '/', + 'httponly' => true, + 'samesite' => 'Lax', + 'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off', + ]); +} + +// Anti-clickjacking : interdit d'afficher le site dans une