165 lines
8.5 KiB
PHP
165 lines
8.5 KiB
PHP
<?php
|
|
// Variables attendues (injectées depuis index.php) :
|
|
// $article — tableau article courant (uuid, slug, title)
|
|
// $reactionStats — array<string, int>
|
|
// $visitorReactions — string[] (types déjà cliqués par ce visiteur)
|
|
// $comments — array de commentaires publiés
|
|
// $commentFlash — bool|null (commentaire soumis, email envoyé)
|
|
// $commentVerified — bool|null (commentaire vérifié et publié)
|
|
// $commentError — string|null (message d'erreur)
|
|
|
|
$_reactionDefs = [
|
|
'useful' => ['👍', 'Utile'],
|
|
'important' => ['🔥', 'Important'],
|
|
'interesting' => ['🤔', 'À creuser'],
|
|
];
|
|
|
|
$_csrfToken = bin2hex(random_bytes(16));
|
|
$_SESSION['comment_csrf'] = $_csrfToken;
|
|
?>
|
|
|
|
<!-- ── Réactions ──────────────────────────────────────────────────── -->
|
|
<div class="card mb-4" id="reactions">
|
|
<div class="card-body">
|
|
<h6 class="card-title mb-3 text-muted text-uppercase" style="font-size:.75rem;letter-spacing:.06em">Réactions</h6>
|
|
<div class="d-flex gap-2 flex-wrap" id="reaction-buttons">
|
|
<?php foreach ($_reactionDefs as $type => [$icon, $label]): ?>
|
|
<?php $active = in_array($type, $visitorReactions, true); ?>
|
|
<form method="post" action="/react" class="reaction-form d-inline">
|
|
<input type="hidden" name="uuid" value="<?= htmlspecialchars($article['uuid']) ?>">
|
|
<input type="hidden" name="type" value="<?= htmlspecialchars($type) ?>">
|
|
<input type="hidden" name="_back" value="/post/<?= rawurlencode($article['slug'] ?? '') ?>#reactions">
|
|
<button type="submit"
|
|
class="btn btn-sm <?= $active ? 'btn-primary' : 'btn-outline-secondary' ?> reaction-btn"
|
|
data-type="<?= htmlspecialchars($type) ?>"
|
|
data-uuid="<?= htmlspecialchars($article['uuid']) ?>">
|
|
<span class="reaction-icon"><?= $icon ?></span>
|
|
<span class="reaction-label"><?= htmlspecialchars($label) ?></span>
|
|
<span class="badge <?= $active ? 'bg-light text-primary' : 'bg-secondary' ?> ms-1 reaction-count"
|
|
data-type="<?= htmlspecialchars($type) ?>"><?= (int)($reactionStats[$type] ?? 0) ?></span>
|
|
</button>
|
|
</form>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (!empty($alsoReadArticles ?? [])): ?>
|
|
<!-- ── À lire aussi ──────────────────────────────────────────────── -->
|
|
<div class="also-read mb-4" id="also-read">
|
|
<h6 class="also-read-title">À lire aussi</h6>
|
|
<div class="also-read-grid">
|
|
<?php foreach ($alsoReadArticles as $_also):
|
|
$_alsoCover = $_also['cover'] ?? '';
|
|
$_alsoCat = trim($_also['category'] ?? '');
|
|
$_alsoGradient = coverGradient($_alsoCat !== '' ? $_alsoCat : $_also['uuid'], $allCats ?? []);
|
|
$_alsoDate = date('d/m/Y', strtotime((string)($_also['published_at'] ?? $_also['created_at'] ?? '')));
|
|
?>
|
|
<a href="/post/<?= rawurlencode($_also['slug'] ?? '') ?>" class="related-card">
|
|
<div class="related-card-thumb" style="<?= $_alsoCover !== ''
|
|
? 'background-image:url(/file?uuid=' . rawurlencode($_also['uuid']) . '&name=' . rawurlencode($_alsoCover) . ');background-size:cover;background-position:center'
|
|
: 'background:' . htmlspecialchars($_alsoGradient) ?>"></div>
|
|
<div class="related-card-body">
|
|
<div class="related-card-title"><?= htmlspecialchars($_also['title']) ?></div>
|
|
<div class="related-card-date"><?= $_alsoDate ?></div>
|
|
</div>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- ── Commentaires ───────────────────────────────────────────────── -->
|
|
<div id="comments" class="mb-4">
|
|
|
|
<h5 class="mb-3">
|
|
Commentaires
|
|
<?php if (!empty($comments)): ?>
|
|
<span class="badge bg-secondary ms-1"><?= count($comments) ?></span>
|
|
<?php endif; ?>
|
|
</h5>
|
|
|
|
<?php if ($commentFlash ?? false): ?>
|
|
<div class="alert alert-info">
|
|
Un code de confirmation vous a été envoyé par email.
|
|
Cliquez sur le lien reçu pour publier votre commentaire.
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($commentVerified ?? false): ?>
|
|
<div class="alert alert-success">Votre commentaire a été publié. Merci !</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($commentError ?? null)): ?>
|
|
<div class="alert alert-danger"><?= htmlspecialchars($commentError) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php foreach ($comments as $c): ?>
|
|
<div class="card mb-3 comment-card" id="comment-<?= (int)$c['id'] ?>">
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-start mb-2">
|
|
<strong class="comment-author"><?= htmlspecialchars($c['author_name']) ?></strong>
|
|
<small class="text-muted">
|
|
<?= htmlspecialchars(date('d/m/Y à H\hi', strtotime((string)$c['created_at']))) ?>
|
|
</small>
|
|
</div>
|
|
<div class="comment-content"><?= nl2br(htmlspecialchars((string)$c['content'])) ?></div>
|
|
<?php if (function_exists('isAdmin') && isAdmin()): ?>
|
|
<div class="mt-2">
|
|
<form method="post" action="/comment-moderate" class="d-inline">
|
|
<input type="hidden" name="id" value="<?= (int)$c['id'] ?>">
|
|
<input type="hidden" name="pub" value="0">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">Masquer</button>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
<?php if (empty($comments) && !($commentFlash ?? false) && !($commentVerified ?? false)): ?>
|
|
<p class="text-muted mb-4">Aucun commentaire pour l'instant. Soyez le premier !</p>
|
|
<?php endif; ?>
|
|
|
|
<!-- Formulaire -->
|
|
<div class="card mt-3" id="comment-form-card">
|
|
<div class="card-body">
|
|
<h6 class="card-title mb-3">Laisser un commentaire</h6>
|
|
<form method="post" action="/comment" id="comment-form">
|
|
<input type="hidden" name="_token" value="<?= htmlspecialchars($_csrfToken) ?>">
|
|
<input type="hidden" name="uuid" value="<?= htmlspecialchars($article['uuid']) ?>">
|
|
<!-- honeypot -->
|
|
<div class="d-none" aria-hidden="true">
|
|
<input type="text" name="website" tabindex="-1" autocomplete="off">
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-sm-6">
|
|
<label class="form-label" for="comment-name">Nom <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="comment-name" name="author_name"
|
|
maxlength="100" required placeholder="Votre nom">
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<label class="form-label" for="comment-email">
|
|
Email <span class="text-danger">*</span>
|
|
<span class="text-muted fw-normal">(non publié)</span>
|
|
</label>
|
|
<input type="email" class="form-control" id="comment-email" name="author_email"
|
|
maxlength="254" required placeholder="votre@email.fr">
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label" for="comment-content">Commentaire <span class="text-danger">*</span></label>
|
|
<textarea class="form-control" id="comment-content" name="content"
|
|
rows="4" maxlength="2000" required
|
|
placeholder="Votre commentaire (2000 caractères max)"></textarea>
|
|
</div>
|
|
<div class="col-12 d-flex align-items-center gap-3">
|
|
<button type="submit" class="btn btn-primary">Envoyer</button>
|
|
<small class="text-muted">Un code de vérification sera envoyé à votre adresse email.</small>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|