This commit is contained in:
Esteban
2026-07-03 02:02:13 +02:00
parent 88c10ee5b0
commit a19c5c8381
42 changed files with 578 additions and 129 deletions
+9 -1
View File
@@ -87,6 +87,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<!-- enctype multipart/form-data : nécessaire pour l'upload du PDF -->
<!-- en envoie les données à addProject.php -->
<form method="POST" enctype="multipart/form-data" action="<?php echo $projetAModifier ? '../scripts/updateProject.php' : '../scripts/addProject.php'; ?>">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<?php if ($projetAModifier): ?>
<input type="hidden" name="id" value="<?php echo (int) $projetAModifier['id']; ?>">
@@ -151,6 +152,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<div class="project-form-card">
<!-- en envoie les données à addXP.php -->
<form method="POST" enctype="multipart/form-data" action="<?php echo $xpAModifier ? '../scripts/updateXP.php' : '../scripts/addXP.php'; ?>">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<?php if ($xpAModifier): ?>
<input type="hidden" name="id" value="<?php echo (int) $xpAModifier['id']; ?>">
@@ -221,6 +223,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<div class="project-form-card">
<!-- on envoie les données à addSchool.php -->
<form method="POST" enctype="multipart/form-data" action="<?php echo $ecoleAModifier ? '../scripts/updateSchool.php' : '../scripts/addSchool.php'; ?>">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<?php if ($ecoleAModifier): ?>
<input type="hidden" name="id" value="<?php echo (int) $ecoleAModifier['id']; ?>">
@@ -288,6 +291,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<div class="project-form-card">
<!-- on envoie les données à addSkill.php -->
<form method="POST" action="<?php echo $skillAModifier ? '../scripts/updateSkill.php' : '../scripts/addSkill.php'; ?>">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<?php if ($skillAModifier): ?>
<input type="hidden" name="id" value="<?php echo (int) $skillAModifier['id']; ?>">
@@ -332,6 +336,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<div class="project-form-card">
<!-- on envoie les données à addLogo.php -->
<form method="POST" action="<?php echo $logoAModifier ? '../scripts/updateLogo.php' : '../scripts/addLogo.php'; ?>">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<?php if ($logoAModifier): ?>
<input type="hidden" name="id" value="<?php echo (int) $logoAModifier['id']; ?>">
@@ -376,6 +381,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<div class="project-form-card">
<!-- on envoie les données à updateSettings.php -->
<form method="POST" action="../scripts/updateSettings.php">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<label>Titre (affiché en gras)</label>
<input type="text" name="notice_title" value="<?php echo htmlspecialchars($noticeTitle); ?>">
@@ -406,6 +412,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
<div class="project-form-card">
<!-- en envoie les données addUser.php -->
<form method="POST" action="../scripts/addUser.php">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<label>Nom du compte</label>
<input type="text" name="user" required>
@@ -440,7 +447,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
Télécharge une sauvegarde JSON de toutes les données du site
(projets, expériences, écoles, compétences, notification, utilisateurs).
</p>
<a class="btn-submit admin-export-btn" href="../scripts/exportData.php">
<a class="btn-submit admin-export-btn" href="../scripts/exportData.php?csrf_token=<?php echo urlencode(csrfToken()); ?>">
<i class="fa-solid fa-download"></i> Exporter les données (JSON)
</a>
@@ -454,6 +461,7 @@ $noticeEnabled = recupererSetting('site_notice_enabled') ?? '1';
</p>
<form method="POST" action="../scripts/importData.php" enctype="multipart/form-data"
onsubmit="return confirm('ATTENTION : les données actuelles du site vont être écrasées par celles du fichier. Continuer ?');">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(csrfToken()); ?>">
<input type="file" name="jsonfile" accept=".json,application/json" required>
<input type="submit" value="Importer les données" class="btn-submit btn-delete">
</form>
+14 -7
View File
@@ -8,10 +8,12 @@
require_once('../functions/databaseConnection.php');
// Types autorisés : liste blanche pour empêcher toute injection de nom de table
// (le PDF est stocké dans une table associée depuis la migration Juillet 2026 (6) : on la
// joint juste pour le nom de fichier, jamais pour son contenu binaire)
$types = [
'projet' => ['table' => 'projects', 'retour' => './projects.php', 'label' => 'Projet'],
'experience' => ['table' => 'experiences', 'retour' => './xp.php', 'label' => 'Expérience'],
'ecole' => ['table' => 'schools', 'retour' => './xp.php', 'label' => 'École'],
'projet' => ['table' => 'projects', 'pdf' => 'project_pdfs', 'pdf_colonne' => 'project_id', 'retour' => './projects.php', 'label' => 'Projet'],
'experience' => ['table' => 'experiences', 'pdf' => 'experience_pdfs', 'pdf_colonne' => 'experience_id', 'retour' => './xp.php', 'label' => 'Expérience'],
'ecole' => ['table' => 'schools', 'pdf' => 'school_pdfs', 'pdf_colonne' => 'school_id', 'retour' => './xp.php', 'label' => 'École'],
];
$type = $_GET['type'] ?? '';
@@ -28,15 +30,20 @@ $infos = $types[$type];
// Récupération de l'élément demandé
// (pdf_data n'est volontairement pas sélectionné : le PDF est servi à part par viewPdf.php
// dans une <iframe>, inutile de charger son contenu binaire en mémoire ici)
$colonnesCommunes = 'id, title, status, tags, description, image_url, markdown, link_url, pdf_filename';
$colonnesCommunes = 'e.id, e.title, e.status, e.tags, e.description, e.image_url, e.markdown, e.link_url, p.pdf_filename';
$colonnesParType = [
'projet' => $colonnesCommunes,
'experience' => $colonnesCommunes . ', xptype, duration',
'ecole' => $colonnesCommunes . ', duration',
'experience' => $colonnesCommunes . ', e.xptype, e.duration',
'ecole' => $colonnesCommunes . ', e.duration',
];
try {
$stmt = $dbh->prepare('SELECT ' . $colonnesParType[$type] . ' FROM `' . $infos['table'] . '` WHERE id = :id');
$stmt = $dbh->prepare(
'SELECT ' . $colonnesParType[$type] . '
FROM `' . $infos['table'] . '` e
LEFT JOIN `' . $infos['pdf'] . '` p ON p.`' . $infos['pdf_colonne'] . '` = e.id
WHERE e.id = :id'
);
$stmt->bindValue(':id', (int) $id, PDO::PARAM_INT);
$stmt->execute();
$element = $stmt->fetch(PDO::FETCH_ASSOC);
+27
View File
@@ -19,6 +19,12 @@ require_once('../functions/listLogos.php');
// Compétences, pas de saisie séparée (voir listeIconesCompetences)
require_once('../functions/listSkills.php');
// Chiffres clés (bandeau de stats sous le hero) : nombre réel de projets/expériences
// en BDD, et nombre de technologies reconnaissables (réutilise listeIconesCompetences)
require_once('../functions/listStats.php');
$statsHome = recupererStatsHome();
$statsHome['technologies'] = count(listeIconesCompetences());
// Affichage de la notification (si elle est activée dans le panel Admin)
afficherNotice();
?>
@@ -42,6 +48,27 @@ afficherNotice();
</a>
</section>
<?php
// Chiffres clés : n'affiche que les compteurs non nuls (pas de "0 projets" décevant
// si le site vient d'être initialisé)
$statsAffichables = array_filter([
'projets' => ['valeur' => $statsHome['projets'], 'label' => 'Projet' . ($statsHome['projets'] > 1 ? 's' : '') . ' réalisés'],
'experiences' => ['valeur' => $statsHome['experiences'], 'label' => 'Expérience' . ($statsHome['experiences'] > 1 ? 's' : '') . ' pro'],
'technologies' => ['valeur' => $statsHome['technologies'], 'label' => 'Technologies maîtrisées'],
], function ($stat) { return $stat['valeur'] > 0; });
?>
<?php if (!empty($statsAffichables)): ?>
<!-- Bandeau de chiffres clés : compteurs réels, calculés depuis la BDD -->
<section class="stats-strip">
<?php foreach ($statsAffichables as $stat): ?>
<div class="stat-item">
<span class="stat-number"><?php echo (int) $stat['valeur']; ?></span>
<span class="stat-label"><?php echo htmlspecialchars($stat['label']); ?></span>
</div>
<?php endforeach; ?>
</section>
<?php endif; ?>
<?php if (!empty(listeIconesCompetences())): ?>
<!-- Bandeau défilant des outils, dérivé de la page Compétences -->
<section class="logo-banner-section">