feat: déplacer 'À lire aussi' après les réactions dans la colonne principale
This commit is contained in:
@@ -36,6 +36,12 @@ RewriteRule ^admin/role/([a-z0-9_-]+)/?$ /index.php?action=admin_role_edit&role_
|
|||||||
RewriteRule ^admin/([a-z0-9-]+)/?$ /index.php?action=admin&tab=$1 [L,QSA]
|
RewriteRule ^admin/([a-z0-9-]+)/?$ /index.php?action=admin&tab=$1 [L,QSA]
|
||||||
RewriteRule ^admin/?$ /index.php?action=admin [L,QSA]
|
RewriteRule ^admin/?$ /index.php?action=admin [L,QSA]
|
||||||
|
|
||||||
|
# Réactions et commentaires
|
||||||
|
RewriteRule ^react/?$ /index.php?action=react [L,QSA]
|
||||||
|
RewriteRule ^comment/?$ /index.php?action=comment [L,QSA]
|
||||||
|
RewriteRule ^comment-moderate/?$ /index.php?action=comment_moderate [L,QSA]
|
||||||
|
RewriteRule ^verify-comment/([0-9]{6})/?$ /index.php?action=verify_comment&code=$1 [L,QSA]
|
||||||
|
|
||||||
# Pages de gestion
|
# Pages de gestion
|
||||||
RewriteRule ^categories/?$ /index.php?action=categories [L,QSA]
|
RewriteRule ^categories/?$ /index.php?action=categories [L,QSA]
|
||||||
RewriteRule ^profile/?$ /index.php?action=profile [L,QSA]
|
RewriteRule ^profile/?$ /index.php?action=profile [L,QSA]
|
||||||
|
|||||||
@@ -681,6 +681,36 @@ textarea.form-control {
|
|||||||
border-color: var(--vl-accent);
|
border-color: var(--vl-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.also-read-title {
|
||||||
|
font-size: .7rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: .08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--vl-muted);
|
||||||
|
margin-bottom: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.also-read-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.also-read-grid .related-card {
|
||||||
|
flex: 1 1 200px;
|
||||||
|
max-width: 280px;
|
||||||
|
background: var(--vl-surface);
|
||||||
|
border-radius: var(--vl-radius);
|
||||||
|
padding: .65rem;
|
||||||
|
box-shadow: var(--vl-shadow-sm);
|
||||||
|
transition: box-shadow .15s, transform .15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.also-read-grid .related-card:hover {
|
||||||
|
box-shadow: var(--vl-shadow-md);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
.related-card {
|
.related-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
|
|||||||
+212
-1
@@ -22,7 +22,7 @@ $action = $_GET['action'] ?? 'list';
|
|||||||
$uuid = $_GET['uuid'] ?? '';
|
$uuid = $_GET['uuid'] ?? '';
|
||||||
$slug = $_GET['slug'] ?? '';
|
$slug = $_GET['slug'] ?? '';
|
||||||
|
|
||||||
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links'];
|
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate'];
|
||||||
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
|
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
|
||||||
unset($_noindexActions);
|
unset($_noindexActions);
|
||||||
|
|
||||||
@@ -635,6 +635,38 @@ switch ($action) {
|
|||||||
|
|
||||||
$backlinks = $articles->getBacklinks($article['slug'] ?? '', $article['uuid']);
|
$backlinks = $articles->getBacklinks($article['slug'] ?? '', $article['uuid']);
|
||||||
|
|
||||||
|
// Réactions et commentaires
|
||||||
|
require_once BASE_PATH . '/src/ReactionManager.php';
|
||||||
|
require_once BASE_PATH . '/src/CommentManager.php';
|
||||||
|
$reactionStats = array_fill_keys(ReactionManager::TYPES, 0);
|
||||||
|
$visitorReactions = [];
|
||||||
|
$comments = [];
|
||||||
|
$commentFlash = isset($_GET['commented']);
|
||||||
|
$commentVerified = isset($_GET['verified']);
|
||||||
|
$commentError = null;
|
||||||
|
if ($pdo) {
|
||||||
|
$reactionMgr = new ReactionManager($pdo);
|
||||||
|
$commentMgr = new CommentManager($pdo);
|
||||||
|
|
||||||
|
// Cookie visiteur (fingerprint anti-doublon)
|
||||||
|
if (empty($_COOKIE['vl_vid'])) {
|
||||||
|
$vid = bin2hex(random_bytes(16));
|
||||||
|
setcookie('vl_vid', $vid, [
|
||||||
|
'expires' => time() + 365 * 86400,
|
||||||
|
'path' => '/',
|
||||||
|
'secure' => !empty($_SERVER['HTTPS']),
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax',
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$vid = $_COOKIE['vl_vid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$reactionStats = $reactionMgr->statsForArticle($article['uuid']);
|
||||||
|
$visitorReactions = $reactionMgr->visitorReactions($article['uuid'], $vid);
|
||||||
|
$comments = $commentMgr->forArticle($article['uuid']);
|
||||||
|
}
|
||||||
|
|
||||||
include BASE_PATH . '/templates/post_view.php';
|
include BASE_PATH . '/templates/post_view.php';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1616,6 +1648,161 @@ switch ($action) {
|
|||||||
header('Location: /edit/' . rawurlencode($uuid));
|
header('Location: /edit/' . rawurlencode($uuid));
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
case 'react':
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$reactUuid = trim($_POST['uuid'] ?? '');
|
||||||
|
$reactType = trim($_POST['type'] ?? '');
|
||||||
|
$isAjax = ($_POST['_ajax'] ?? '') === '1';
|
||||||
|
|
||||||
|
// Cookie visiteur
|
||||||
|
if (empty($_COOKIE['vl_vid'])) {
|
||||||
|
$vid = bin2hex(random_bytes(16));
|
||||||
|
setcookie('vl_vid', $vid, [
|
||||||
|
'expires' => time() + 365 * 86400,
|
||||||
|
'path' => '/',
|
||||||
|
'secure' => !empty($_SERVER['HTTPS']),
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax',
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$vid = $_COOKIE['vl_vid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = dbPdo();
|
||||||
|
if ($pdo && $reactUuid !== '') {
|
||||||
|
require_once BASE_PATH . '/src/ReactionManager.php';
|
||||||
|
$rm = new ReactionManager($pdo);
|
||||||
|
$added = $rm->toggle($reactUuid, $reactType, $vid);
|
||||||
|
$count = $rm->statsForArticle($reactUuid)[$reactType] ?? 0;
|
||||||
|
|
||||||
|
if ($isAjax) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['ok' => true, 'active' => $added, 'count' => $count]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$reactBack = $_POST['_back'] ?? '/';
|
||||||
|
header('Location: ' . $reactBack);
|
||||||
|
exit;
|
||||||
|
|
||||||
|
case 'comment':
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Honeypot
|
||||||
|
if (($_POST['website'] ?? '') !== '') {
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF
|
||||||
|
$csrfOk = isset($_POST['_token'], $_SESSION['comment_csrf'])
|
||||||
|
&& hash_equals($_SESSION['comment_csrf'], $_POST['_token']);
|
||||||
|
unset($_SESSION['comment_csrf']);
|
||||||
|
if (!$csrfOk) {
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cmtUuid = trim($_POST['uuid'] ?? '');
|
||||||
|
$cmtName = trim($_POST['author_name'] ?? '');
|
||||||
|
$cmtEmail = trim($_POST['author_email'] ?? '');
|
||||||
|
$cmtContent = trim($_POST['content'] ?? '');
|
||||||
|
|
||||||
|
$cmtArticle = $cmtUuid !== '' ? $articles->getByUuid($cmtUuid) : null;
|
||||||
|
$cmtBack = $cmtArticle ? '/post/' . rawurlencode($cmtArticle['slug'] ?? $cmtUuid) : '/';
|
||||||
|
|
||||||
|
$pdo = dbPdo();
|
||||||
|
if (!$pdo || !$cmtArticle || $cmtName === '' || !filter_var($cmtEmail, FILTER_VALIDATE_EMAIL) || $cmtContent === '') {
|
||||||
|
header('Location: ' . $cmtBack . '#comment-form-card');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb_strlen($cmtContent) > 2000) {
|
||||||
|
header('Location: ' . $cmtBack . '#comment-form-card');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once BASE_PATH . '/src/CommentManager.php';
|
||||||
|
require_once BASE_PATH . '/src/mailer.php';
|
||||||
|
|
||||||
|
$cm = new CommentManager($pdo);
|
||||||
|
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
|
||||||
|
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
|
||||||
|
$code = $cm->submit($cmtUuid, $cmtName, $cmtEmail, $cmtContent, $ip, $ua);
|
||||||
|
|
||||||
|
$verifyUrl = rtrim(APP_URL, '/') . '/verify-comment/' . $code;
|
||||||
|
$articleUrl = rtrim(APP_URL, '/') . $cmtBack;
|
||||||
|
$subject = '[' . siteTitle() . '] Confirmez votre commentaire';
|
||||||
|
$html = '<!DOCTYPE html><html><body style="font-family:sans-serif;max-width:560px;margin:0 auto">'
|
||||||
|
. '<p>Bonjour ' . htmlspecialchars($cmtName) . ',</p>'
|
||||||
|
. '<p>Cliquez sur le bouton ci-dessous pour confirmer votre commentaire sur <em>' . htmlspecialchars($cmtArticle['title']) . '</em> :</p>'
|
||||||
|
. '<p><a href="' . htmlspecialchars($verifyUrl) . '" style="display:inline-block;padding:10px 20px;background:#0d6efd;color:#fff;text-decoration:none;border-radius:4px">Confirmer mon commentaire</a></p>'
|
||||||
|
. '<p style="color:#888;font-size:.875em">Ou copiez ce lien dans votre navigateur :<br>' . htmlspecialchars($verifyUrl) . '</p>'
|
||||||
|
. '<p style="color:#888;font-size:.875em">Ce lien expire dans 24 heures. Si vous n\'êtes pas à l\'origine de ce message, ignorez-le.</p>'
|
||||||
|
. '</body></html>';
|
||||||
|
|
||||||
|
try {
|
||||||
|
envoyer_mail_smtp($cmtEmail, $subject, $html);
|
||||||
|
} catch (\RuntimeException) {
|
||||||
|
// Taux limité ou erreur SMTP : on continue sans planter le visiteur
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . $cmtBack . '?commented=1#comments');
|
||||||
|
exit;
|
||||||
|
|
||||||
|
case 'verify_comment':
|
||||||
|
$vcCode = trim($_GET['code'] ?? '');
|
||||||
|
$pdo = dbPdo();
|
||||||
|
if ($pdo && preg_match('/^[0-9]{6}$/', $vcCode)) {
|
||||||
|
require_once BASE_PATH . '/src/CommentManager.php';
|
||||||
|
$cm = new CommentManager($pdo);
|
||||||
|
$vcUuid = $cm->verify($vcCode);
|
||||||
|
if ($vcUuid !== null) {
|
||||||
|
$vcArticle = $articles->getByUuid($vcUuid);
|
||||||
|
$vcSlug = $vcArticle ? ($vcArticle['slug'] ?? $vcUuid) : $vcUuid;
|
||||||
|
header('Location: /post/' . rawurlencode($vcSlug) . '?verified=1#comments');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Code invalide ou expiré
|
||||||
|
http_response_code(404);
|
||||||
|
ob_start();
|
||||||
|
?>
|
||||||
|
<div class="container py-5 text-center">
|
||||||
|
<h1 class="h2 mb-3">Lien invalide ou expiré</h1>
|
||||||
|
<p class="text-muted mb-4">Ce lien de confirmation n'est plus valide (expiré après 24 h) ou a déjà été utilisé.</p>
|
||||||
|
<a href="/" class="btn btn-primary">← Retour à l'accueil</a>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
$content = ob_get_clean();
|
||||||
|
$title = 'Lien invalide — ' . siteTitle();
|
||||||
|
$metaRobots = 'noindex, nofollow';
|
||||||
|
include BASE_PATH . '/templates/layout.php';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'comment_moderate':
|
||||||
|
requireAuth();
|
||||||
|
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
http_response_code(403);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$modId = (int)($_POST['id'] ?? 0);
|
||||||
|
$modPub = (int)($_POST['pub'] ?? 1);
|
||||||
|
$pdo = dbPdo();
|
||||||
|
if ($pdo && $modId > 0) {
|
||||||
|
require_once BASE_PATH . '/src/CommentManager.php';
|
||||||
|
(new CommentManager($pdo))->setPublished($modId, $modPub === 1);
|
||||||
|
}
|
||||||
|
header('Location: /admin/comments');
|
||||||
|
exit;
|
||||||
|
|
||||||
case 'rate':
|
case 'rate':
|
||||||
requireAuth();
|
requireAuth();
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
@@ -1780,6 +1967,30 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($tab === 'comments') {
|
||||||
|
if (!isAdmin()) {
|
||||||
|
http_response_code(403);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$pdo = dbPdo();
|
||||||
|
if ($pdo) {
|
||||||
|
require_once BASE_PATH . '/src/CommentManager.php';
|
||||||
|
$adminData['comments'] = (new CommentManager($pdo))->allForAdmin();
|
||||||
|
// Enrichit avec le slug de chaque article pour les liens
|
||||||
|
$adminData['articleSlugs'] = [];
|
||||||
|
foreach ($adminData['comments'] as $cmtRow) {
|
||||||
|
$uuid = $cmtRow['article_uuid'];
|
||||||
|
if (!isset($adminData['articleSlugs'][$uuid])) {
|
||||||
|
$a = $articles->getByUuid($uuid);
|
||||||
|
$adminData['articleSlugs'][$uuid] = $a ? ($a['slug'] ?? null) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$adminData['comments'] = [];
|
||||||
|
$adminData['articleSlugs'] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
include BASE_PATH . '/templates/admin.php';
|
include BASE_PATH . '/templates/admin.php';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ function adminStatusBadge(array $a, int $now): string
|
|||||||
<a class="nav-link <?= $tab === 'site' ? 'active' : '' ?>"
|
<a class="nav-link <?= $tab === 'site' ? 'active' : '' ?>"
|
||||||
href="/admin/site">Site</a>
|
href="/admin/site">Site</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?= $tab === 'comments' ? 'active' : '' ?>"
|
||||||
|
href="/admin/comments">Commentaires</a>
|
||||||
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -461,6 +465,79 @@ function adminStatusBadge(array $a, int $now): string
|
|||||||
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- ─────────────────────────── COMMENTAIRES ──────────────────────── -->
|
||||||
|
<?php if ($tab === 'comments' && isAdmin()): ?>
|
||||||
|
|
||||||
|
<h5 class="mb-3">Commentaires</h5>
|
||||||
|
<?php if (empty($adminData['comments'])): ?>
|
||||||
|
<p class="text-muted">Aucun commentaire pour l'instant.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover align-middle">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Article</th>
|
||||||
|
<th>Auteur</th>
|
||||||
|
<th>Commentaire</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>État</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($adminData['comments'] as $c): ?>
|
||||||
|
<?php
|
||||||
|
$cSlug = $adminData['articleSlugs'][$c['article_uuid']] ?? null;
|
||||||
|
$cDate = date('d/m/Y H:i', strtotime((string)$c['created_at']));
|
||||||
|
$cVerif = $c['verified'] ? '<span class="badge bg-success">Vérifié</span>' : '<span class="badge bg-warning text-dark">En attente</span>';
|
||||||
|
$cPub = $c['published'] ? '<span class="badge bg-primary">Publié</span>' : '<span class="badge bg-secondary">Masqué</span>';
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td class="small">
|
||||||
|
<?php if ($cSlug): ?>
|
||||||
|
<a href="/post/<?= rawurlencode($cSlug) ?>#comments"><?= htmlspecialchars($cSlug) ?></a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="text-muted"><?= htmlspecialchars(substr($c['article_uuid'], 0, 8)) ?>…</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="small">
|
||||||
|
<div><?= htmlspecialchars($c['author_name']) ?></div>
|
||||||
|
<div class="text-muted"><?= htmlspecialchars($c['author_email']) ?></div>
|
||||||
|
</td>
|
||||||
|
<td class="small" style="max-width:30ch">
|
||||||
|
<span title="<?= htmlspecialchars($c['content']) ?>">
|
||||||
|
<?= htmlspecialchars(mb_strimwidth($c['content'], 0, 80, '…')) ?>
|
||||||
|
</span>
|
||||||
|
<?php if (!empty($c['verification_code'])): ?>
|
||||||
|
<br><span class="text-muted">Code : <?= htmlspecialchars($c['verification_code']) ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="text-muted small text-nowrap"><?= htmlspecialchars($cDate) ?></td>
|
||||||
|
<td><?= $cVerif ?> <?= $cPub ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($c['verified'] && $c['published']): ?>
|
||||||
|
<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>
|
||||||
|
<?php elseif ($c['verified'] && !$c['published']): ?>
|
||||||
|
<form method="post" action="/comment-moderate" class="d-inline">
|
||||||
|
<input type="hidden" name="id" value="<?= (int)$c['id'] ?>">
|
||||||
|
<input type="hidden" name="pub" value="1">
|
||||||
|
<button type="submit" class="btn btn-sm btn-outline-success">Publier</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$content = ob_get_clean();
|
$content = ob_get_clean();
|
||||||
$title = 'Administration — ' . siteTitle();
|
$title = 'Administration — ' . siteTitle();
|
||||||
|
|||||||
@@ -44,6 +44,31 @@ $_SESSION['comment_csrf'] = $_csrfToken;
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if (!empty($alsoReadArticles ?? [])): ?>
|
||||||
|
<!-- ── À lire aussi ──────────────────────────────────────────────── -->
|
||||||
|
<div class="also-read mb-4">
|
||||||
|
<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 ───────────────────────────────────────────────── -->
|
<!-- ── Commentaires ───────────────────────────────────────────────── -->
|
||||||
<div id="comments" class="mb-4">
|
<div id="comments" class="mb-4">
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,9 @@ $_layoutCurrentCat = trim($_GET['cat'] ?? '');
|
|||||||
<!-- JS -->
|
<!-- JS -->
|
||||||
<script src="/assets/js/bootstrap.bundle.min.js"></script>
|
<script src="/assets/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="/assets/js/app.js"></script>
|
<script src="/assets/js/app.js"></script>
|
||||||
|
<?php if (isset($reactionStats)): ?>
|
||||||
|
<script src="/assets/js/reactions.js"></script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+2
-20
@@ -170,6 +170,8 @@ $hasSources = (!empty($externalLinks) || !empty($files))
|
|||||||
</p>
|
</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/comments_section.php'; ?>
|
||||||
|
|
||||||
</div><!-- /col principale -->
|
</div><!-- /col principale -->
|
||||||
|
|
||||||
<div class="post-sidebar-col order-3">
|
<div class="post-sidebar-col order-3">
|
||||||
@@ -286,26 +288,6 @@ $hasSources = (!empty($externalLinks) || !empty($files))
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (!empty($alsoReadArticles ?? [])): ?>
|
|
||||||
<h6 class="related-sidebar-title">À lire aussi</h6>
|
|
||||||
<?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; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user