213 lines
8.4 KiB
PHP
213 lines
8.4 KiB
PHP
<?php
|
|
|
|
// Ajout de connexion a la bdd
|
|
require_once('../functions/databaseConnection.php');
|
|
|
|
// Fonction qui va faire une requête SQL afin de collecter toutes les catégories de compétences
|
|
// Retourne un tableau vide si la table n'existe pas encore (pas de die() pour que la page
|
|
// Compétences continue de fonctionner tant que le script SQL n'a pas été exécuté)
|
|
function listeSkills() {
|
|
global $dbh;
|
|
|
|
try {
|
|
$stmt = $dbh->prepare('SELECT id, title, icon, items, position FROM skills ORDER BY position ASC, id ASC');
|
|
$stmt->execute();
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Fonction qui permet de récupérer une catégorie de compétences par id (pour la modification dans le panel Admin)
|
|
function recupererSkillParId($id) {
|
|
global $dbh;
|
|
|
|
try {
|
|
$stmt = $dbh->prepare('SELECT id, title, icon, items, position FROM skills WHERE id = :id');
|
|
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
|
|
$stmt->execute();
|
|
return $stmt->fetch(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Icônes Devicon dont la couleur de marque "colored" est noire ou quasi-noire (vérifié dans
|
|
// devicon.min.css : linux #000, apple #000, bash #293138, ansible #1a1918) : invisibles sur
|
|
// la tuile sombre du bandeau. On les affiche dans la couleur claire par défaut à la place.
|
|
const DEVICON_COLORED_TROP_SOMBRE = ['devicon-linux-plain', 'devicon-apple-plain', 'devicon-bash-plain', 'devicon-ansible-plain'];
|
|
|
|
// Fonction interne qui affiche le visuel (icône ou image) d'un item de compétence.
|
|
// Format accepté avant le "|" : soit des classes d'icône (Font Awesome ou Devicon), soit
|
|
// "img:URL" pour utiliser une vraie image de logo (pour les outils absents des polices
|
|
// d'icônes, ex : GLPI, FOG, Proxmox, VirtualBox, Guacamole).
|
|
// $colorise active les vraies couleurs de marque des icônes Devicon (utilisé uniquement
|
|
// pour le bandeau de la home : sur la page Compétences les icônes restent en orange
|
|
// uniforme, cohérent avec le reste de la liste)
|
|
function afficherVisuelItem($itemIcone, $classe = '', $colorise = false) {
|
|
if (strpos($itemIcone, 'img:') === 0) {
|
|
$image = htmlspecialchars(substr($itemIcone, 4));
|
|
echo '<img class="' . $classe . '" src="' . $image . '" alt="" loading="lazy">';
|
|
return;
|
|
}
|
|
|
|
if ($colorise && strpos($itemIcone, 'devicon-') === 0 && strpos($itemIcone, 'colored') === false) {
|
|
$estTropSombre = false;
|
|
foreach (DEVICON_COLORED_TROP_SOMBRE as $slug) {
|
|
if (strpos($itemIcone, $slug) === 0) {
|
|
$estTropSombre = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$estTropSombre) {
|
|
$itemIcone .= ' colored';
|
|
}
|
|
}
|
|
|
|
echo '<i class="' . $classe . ' ' . htmlspecialchars($itemIcone) . '"></i>';
|
|
}
|
|
|
|
// Fonction interne qui affiche une carte de compétences (utilisée par la page publique et le panel admin)
|
|
// Les items sont stockés un par ligne, au format "classes-icone|Texte" (icône optionnelle)
|
|
function afficherSkillCard($skill, $admin = false) {
|
|
$id = (int) $skill['id'];
|
|
$titre = htmlspecialchars($skill['title']);
|
|
$icone = htmlspecialchars(!empty($skill['icon']) ? $skill['icon'] : 'fa-solid fa-star');
|
|
|
|
echo '<div class="skill-category">';
|
|
echo '<div class="skill-category-icon"><i class="' . $icone . '"></i></div>';
|
|
echo '<h2>' . $titre . '</h2>';
|
|
echo '<ul class="skill-list">';
|
|
|
|
// Un item par ligne
|
|
$items = array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', $skill['items'])));
|
|
foreach ($items as $item) {
|
|
// Icône optionnelle avant le | sinon icône par défaut
|
|
$itemIcone = 'fa-solid fa-check';
|
|
$label = $item;
|
|
if (strpos($item, '|') !== false) {
|
|
list($itemIcone, $label) = array_map('trim', explode('|', $item, 2));
|
|
}
|
|
echo '<li>';
|
|
afficherVisuelItem($itemIcone, 'skill-item-visual');
|
|
echo ' ' . htmlspecialchars($label) . '</li>';
|
|
}
|
|
|
|
echo '</ul>';
|
|
|
|
// Boutons de modification / suppression pour le panel admin
|
|
if ($admin) {
|
|
echo '<div class="admin-actions">';
|
|
echo '<a class="btn-submit btn-edit" href="./admin.php?edit_skill=' . $id . '#admin-competences">Modifier</a>';
|
|
echo '<a class="btn-submit btn-delete" href="../scripts/removeSkill.php?id=' . $id . '&csrf_token=' . urlencode(csrfToken()) . '" onclick="return confirm(\'Voulez-vous vraiment supprimer cette catégorie de compétences ?\');">Supprimer</a>';
|
|
echo '</div>';
|
|
}
|
|
|
|
echo '</div>';
|
|
}
|
|
|
|
// Fonction qui va afficher les compétences sur la page publique
|
|
function afficherSkills() {
|
|
$skills = listeSkills();
|
|
|
|
// Si la table est vide ou n'existe pas encore
|
|
if (empty($skills)) {
|
|
echo '<p class="admin-notice">Les compétences seront bientôt disponibles.</p>';
|
|
return;
|
|
}
|
|
|
|
echo '<div class="skills-grid">';
|
|
foreach ($skills as $skill) {
|
|
afficherSkillCard($skill, false);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// Fonction identique à celle en haut mais ajout de boutons pour le panel admin
|
|
function afficherSkillsAdmin() {
|
|
$skills = listeSkills();
|
|
|
|
echo '<div class="skills-grid">';
|
|
foreach ($skills as $skill) {
|
|
afficherSkillCard($skill, true);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// Items exclus du bandeau de la home au cas par cas, en plus du filtre automatique
|
|
// (icône Devicon "réelle" mais jugée pas assez reconnaissable seule, sans le texte à côté)
|
|
const OUTILS_EXCLUS_DU_BANDEAU = ['Bash'];
|
|
|
|
// Fonction qui récupère tous les items de compétences représentant un vrai outil identifiable
|
|
// (icône Devicon ou image "img:"), toutes catégories confondues. Les items en texte seul
|
|
// SONT EXCLUS, ainsi que les icônes Font Awesome génériques (fa-solid/fa-brands) : dans un
|
|
// bandeau qui n'affiche pas le texte à côté (juste une info-bulle au survol), une icône
|
|
// générique comme un pictogramme "carte" pour "Adressage IP" ou "carnet de contact" pour
|
|
// "LDAP" ne représente aucun outil reconnaissable — ça reste illisible pour un visiteur qui
|
|
// ne survole pas. Ces items restent affichés normalement sur la page Compétences (avec leur
|
|
// texte à côté, donc sans ambiguïté), seul le bandeau de la home les filtre.
|
|
function listeIconesCompetences() {
|
|
$categories = listeSkills();
|
|
$resultats = [];
|
|
|
|
foreach ($categories as $categorie) {
|
|
$items = array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', $categorie['items'])));
|
|
|
|
foreach ($items as $item) {
|
|
if (strpos($item, '|') === false) {
|
|
continue;
|
|
}
|
|
|
|
list($icone, $label) = array_map('trim', explode('|', $item, 2));
|
|
if ($icone === '' || $label === '') {
|
|
continue;
|
|
}
|
|
|
|
// Seuls les vrais logos (Devicon ou image) sont assez reconnaissables sans texte
|
|
$estUnVraiLogo = strpos($icone, 'devicon-') === 0 || strpos($icone, 'img:') === 0;
|
|
if (!$estUnVraiLogo) {
|
|
continue;
|
|
}
|
|
|
|
if (in_array($label, OUTILS_EXCLUS_DU_BANDEAU, true)) {
|
|
continue;
|
|
}
|
|
|
|
$resultats[] = ['icon' => $icone, 'label' => $label];
|
|
}
|
|
}
|
|
|
|
return $resultats;
|
|
}
|
|
|
|
// Fonction qui affiche le bandeau défilant des outils, directement à partir des icônes
|
|
// de la page Compétences (voir listeIconesCompetences). Réutilise les mêmes classes CSS
|
|
// que les bandeaux de logo_banners pour un rendu visuel identique (voir primary_css.css).
|
|
// "logo-marquee-tools" désactive le filtre grayscale/survol : contrairement aux logos
|
|
// d'entreprises, on veut que les vrais outils soient reconnaissables immédiatement.
|
|
function afficherOutilsCompetences() {
|
|
$outils = listeIconesCompetences();
|
|
|
|
if (empty($outils)) {
|
|
return;
|
|
}
|
|
|
|
echo '<div class="logo-marquee logo-marquee-tools">';
|
|
echo '<div class="logo-track">';
|
|
|
|
// On répète deux fois la liste : le défilement CSS boucle sur -50%, ce qui donne
|
|
// un effet de scroll infini fluide et sans coupure
|
|
for ($repetition = 0; $repetition < 2; $repetition++) {
|
|
foreach ($outils as $outil) {
|
|
$label = htmlspecialchars($outil['label']);
|
|
|
|
echo '<div class="logo-tile" title="' . $label . '">';
|
|
afficherVisuelItem($outil['icon'], '', true);
|
|
echo '</div>';
|
|
}
|
|
}
|
|
|
|
echo '</div>';
|
|
echo '</div>';
|
|
}
|