';
case 'moderator':
return '';
default:
return '';
}
}
// Générer un token CSRF si non existant
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$csrf_token = $_SESSION['csrf_token'];
// Récupérer les informations de l'utilisateur connecté pour la navbar
if(isset($_SESSION['user_id'])) {
$avatar_url = htmlspecialchars($_SESSION['avatar_url'] ?? 'https://via.placeholder.com/40', ENT_QUOTES, 'UTF-8');
$role = htmlspecialchars($_SESSION['role'] ?? 'user', ENT_QUOTES, 'UTF-8');
$username = htmlspecialchars($_SESSION['username'] ?? 'Utilisateur', ENT_QUOTES, 'UTF-8');
}
// Fonction pour parser le contenu et appliquer la mise en forme
function parseContent($text) {
// Échapper les caractères spéciaux pour prévenir les XSS
$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
// Appliquer les transformations de mise en forme
// Gras: **texte**
$text = preg_replace('/\*\*(.*?)\*\*/s', '$1', $text);
// Italique: *texte*
$text = preg_replace('/\*(.*?)\*/s', '$1', $text);
// Souligné: [underline]texte[/underline]
$text = preg_replace('/\[underline\](.*?)\[\/underline\]/s', '$1', $text);
// Barré: [strike]texte[/strike]
$text = preg_replace('/\[strike\](.*?)\[\/strike\]/s', '$1', $text);
// Centré: [center]texte[/center]
$text = preg_replace('/\[center\](.*?)\[\/center\]/s', '
$1
', $text);
// Spoiler: [spoiler]texte[/spoiler]
$text = preg_replace('/\[spoiler\](.*?)\[\/spoiler\]/s', '$1', $text);
// Bloc de Code: [code]code ici[/code]
$text = preg_replace('/\[code\](.*?)\[\/code\]/s', '$1
', $text);
// Lien: [link=https://exemple.com]texte du lien[/link]
$text = preg_replace('/\[link=(https?:\/\/[^\]]+)\](.*?)\[\/link\]/s', '$2', $text);
// Image: [img]https://exemple.com/image.jpg[/img]
$text = preg_replace('/\[img\](https?:\/\/[^\]]+\.(?:jpg|jpeg|png|gif|bmp|webp))\[\/img\]/s', '
', $text);
// Liste non ordonnée: [ul][li]Item 1[/li][li]Item 2[/li][/ul]
$text = preg_replace('/\[ul\](.*?)\[\/ul\]/s', '', $text);
$text = preg_replace('/\[li\](.*?)\[\/li\]/s', '$1', $text);
// Liste ordonnée: [ol][li]Item 1[/li][li]Item 2[/li][/ol]
$text = preg_replace('/\[ol\](.*?)\[\/ol\]/s', '$1
', $text);
// Surligné: [highlight]texte[/highlight]
$text = preg_replace('/\[highlight\](.*?)\[\/highlight\]/s', '$1', $text);
// Citation: [blockquote]texte[/blockquote]
$text = preg_replace('/\[blockquote\](.*?)\[\/blockquote\]/s', '$1
', $text);
// Tableau: [table]...[/table]
$text = preg_replace('/\[table\](.*?)\[\/table\]/s', '', $text);
$text = preg_replace('/\[tr\](.*?)\[\/tr\]/s', '$1
', $text);
$text = preg_replace('/\[th\](.*?)\[\/th\]/s', '$1 | ', $text);
$text = preg_replace('/\[td\](.*?)\[\/td\]/s', '$1 | ', $text);
return $text;
}
// Récupérer les informations du sujet
try {
$stmt = $pdo->prepare("
SELECT topics.*, users.username, users.avatar_url, users.role, categories.name AS category_name, categories.image_url AS category_image
FROM topics
JOIN users ON topics.user_id = users.id
JOIN categories ON topics.category_id = categories.id
WHERE topics.id = :id
");
$stmt->execute(['id' => $topic_id]);
$topic = $stmt->fetch();
if (!$topic) {
header("Location: index.php");
exit;
}
} catch (PDOException $e) {
die("Erreur lors de la récupération du sujet : " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8'));
}
// Récupérer les badges de l'auteur du sujet
try {
$stmt = $pdo->prepare("
SELECT badges.*
FROM user_badges
JOIN badges ON user_badges.badge_id = badges.id
WHERE user_badges.user_id = :user_id
");
$stmt->execute(['user_id' => $topic['user_id']]);
$topic_badges = $stmt->fetchAll();
} catch (PDOException $e) {
$topic_badges = [];
$badge_error = "Erreur lors de la récupération des badges de l'auteur : " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
}
// Récupérer les messages du sujet
try {
$stmt = $pdo->prepare("
SELECT posts.*, users.username, users.avatar_url, users.role,
(SELECT GROUP_CONCAT(badges.name SEPARATOR ', ')
FROM user_badges
JOIN badges ON user_badges.badge_id = badges.id
WHERE user_badges.user_id = users.id) AS badges
FROM posts
JOIN users ON posts.user_id = users.id
WHERE posts.topic_id = :topic_id
ORDER BY posts.created_at ASC
");
$stmt->execute(['topic_id' => $topic_id]);
$posts = $stmt->fetchAll();
} catch (PDOException $e) {
$posts = [];
$error = "Erreur lors de la récupération des messages : " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
}
// Récupérer les réactions du sujet
try {
$stmt = $pdo->prepare("
SELECT reaction, COUNT(*) as count
FROM topic_reactions
WHERE topic_id = :topic_id
GROUP BY reaction
");
$stmt->execute(['topic_id' => $topic_id]);
$reactions = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); // [reaction => count]
} catch (PDOException $e) {
$reactions = [];
$reaction_error = "Erreur lors de la récupération des réactions : " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
}
// Traitement du formulaire d'ajout de message
$comment = '';
$comment_errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user_id'])) {
// Vérifier le token CSRF
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
$comment_errors[] = "Token de sécurité invalide. Veuillez réessayer.";
}
// Vérifier si le formulaire de commentaire a été soumis
if (isset($_POST['submit_comment'])) {
// Vérifier si le sujet est verrouillé
if ($topic['is_locked']) {
$comment_errors[] = "Ce sujet est verrouillé. Vous ne pouvez pas ajouter de réponses.";
} else {
// Récupérer et nettoyer les données
$comment = trim($_POST['comment']);
// Validation des champs
if (empty($comment)) {
$comment_errors[] = "Le commentaire ne peut pas être vide.";
}
if (empty($comment_errors)) {
try {
$stmt = $pdo->prepare("INSERT INTO posts (user_id, topic_id, content, created_at) VALUES (:user_id, :topic_id, :content, NOW())");
$stmt->execute([
'user_id' => $_SESSION['user_id'],
'topic_id' => $topic_id,
'content' => $comment
]);
header("Location: topic.php?id=" . $topic_id);
exit;
} catch (PDOException $e) {
$comment_errors[] = "Erreur lors de l'ajout du commentaire : " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
}
}
}
}
// Vérifier si une réaction a été ajoutée
if (isset($_POST['add_reaction'])) {
// Récupérer et nettoyer les données
$reaction = trim($_POST['reaction']);
// Validation des réactions (par exemple, limiter à certaines valeurs)
$allowed_reactions = ['like', 'love', 'haha', 'wow', 'sad', 'angry'];
if (!in_array($reaction, $allowed_reactions)) {
$comment_errors[] = "Réaction invalide.";
}
if (empty($comment_errors)) {
try {
// Vérifier si l'utilisateur a déjà réagi avec la même réaction
$stmt = $pdo->prepare("SELECT * FROM topic_reactions WHERE user_id = :user_id AND topic_id = :topic_id AND reaction = :reaction");
$stmt->execute([
'user_id' => $_SESSION['user_id'],
'topic_id' => $topic_id,
'reaction' => $reaction
]);
$existing_reaction = $stmt->fetch();
if (!$existing_reaction) {
// Ajouter la réaction
$stmt = $pdo->prepare("INSERT INTO topic_reactions (user_id, topic_id, reaction, created_at) VALUES (:user_id, :topic_id, :reaction, NOW())");
$stmt->execute([
'user_id' => $_SESSION['user_id'],
'topic_id' => $topic_id,
'reaction' => $reaction
]);
} else {
// Supprimer la réaction (toggle)
$stmt = $pdo->prepare("DELETE FROM topic_reactions WHERE id = :id");
$stmt->execute(['id' => $existing_reaction['id']]);
}
header("Location: topic.php?id=" . $topic_id);
exit;
} catch (PDOException $e) {
$comment_errors[] = "Erreur lors de l'ajout de la réaction : " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
}
}
}
// Gestion des actions de verrouillage/déverrouillage (admins uniquement)
if (isset($_POST['lock_topic']) && $role === 'admin') {
// Vérifier le token CSRF
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
$_SESSION['error'] = "Token de sécurité invalide. Veuillez réessayer.";
} else {
// Changer l'état de verrouillage
$new_lock_status = $topic['is_locked'] ? 0 : 1;
try {
$stmt = $pdo->prepare("UPDATE topics SET is_locked = :is_locked WHERE id = :id");
$stmt->execute([
'is_locked' => $new_lock_status,
'id' => $topic_id
]);
$_SESSION['message'] = $new_lock_status ? "Sujet verrouillé avec succès." : "Sujet déverrouillé avec succès.";
header("Location: topic.php?id=" . $topic_id);
exit;
} catch (PDOException $e) {
$_SESSION['error'] = "Erreur lors de la mise à jour du statut du sujet.";
}
}
}
}
// Récupérer le nombre de likes
try {
$stmt = $pdo->prepare("SELECT COUNT(*) AS like_count FROM topic_likes WHERE topic_id = :topic_id");
$stmt->execute(['topic_id' => $topic_id]);
$like_data = $stmt->fetch();
$like_count = $like_data ? $like_data['like_count'] : 0;
} catch (PDOException $e) {
$like_count = 0;
}
// Gérer les messages flash
$message = '';
if (isset($_SESSION['message'])) {
$message = $_SESSION['message'];
unset($_SESSION['message']);
}
$error_msg = '';
if (isset($_SESSION['error'])) {
$error_msg = $_SESSION['error'];
unset($_SESSION['error']);
}
?>
= htmlspecialchars($topic['title'], ENT_QUOTES, 'UTF-8') ?> - Blue Exorcist Forum
= htmlspecialchars($message) ?>
= htmlspecialchars($error_msg) ?>
= parseContent($topic['content']) ?>
Likes
Réactions
'fas fa-thumbs-up',
'love' => 'fas fa-heart',
'haha' => 'fas fa-laugh',
'wow' => 'fas fa-surprise',
'sad' => 'fas fa-sad-tear',
'angry' => 'fas fa-angry'
];
$allowed_reactions = array_keys($reaction_icons);
?>
= htmlspecialchars($reaction_error) ?>
Réponses
= htmlspecialchars($error) ?>
= parseContent($post['content']) ?>
Aucun message pour le moment. Soyez le premier à répondre !
Ajouter une Réponse
- = htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?>