- 1<?php
- 2
- 3 * --------------------------------------------------------------------------
- 4 * PROJET - Helpers de Vue (Fonctions d'affichage)
- 5 * --------------------------------------------------------------------------
- 6 *
- 7 * Fichier : theme/default/partials/view_helpers.php
- 8 * Rôle : Contient les fonctions PHP nécessaires uniquement pour l'affichage
- 9 * (ex: rendu récursif des commentaires, comptage, nettoyage HTML).
- 10 *
- 11 * @function count_comments_total() Compte les commentaires + réponses.
- 12 * @function render_comment_node() Génère le HTML d'un commentaire et ses enfants.
- 13 *
- 14 * @included_by theme/default/view.php
- 15 */
- 16?>
- 17
- 18
- 19if (!function_exists('count_comments_total')) {
- 20 function count_comments_total($list): int {
- 21 if (!is_array($list) || !$list) return 0;
- 22 if (!isset($list[0]['children'])) return (int)count($list);
- 23 $sum = 0;
- 24 foreach ($list as $n) {
- 25 $sum++;
- 26 if (!empty($n['children']) && is_array($n['children'])) {
- 27 $sum += count_comments_total($n['children']);
- 28 }
- 29 }
- 30 return $sum;
- 31 }
- 32}
- 33
- 34
- 35if (!function_exists('count_descendants')) {
- 36 function count_descendants(array $node): int {
- 37 $sum = 0;
- 38 if (!empty($node['children']) && is_array($node['children'])) {
- 39 foreach ($node['children'] as $ch) {
- 40 $sum++;
- 41 $sum += count_descendants($ch);
- 42 }
- 43 }
- 44 return $sum;
- 45 }
- 46}
- 47
- 48
- 49if (!function_exists('comment_body_html_safe')) {
- 50 function comment_body_html_safe(array $c): string {
- 51
- 52 return isset($c['body_html'])
- 53 ? (string)$c['body_html']
- 54 : (function_exists('render_comment_html') ? render_comment_html((string)($c['body'] ?? '')) : htmlspecialchars($c['body'] ?? ''));
- 55 }
- 56}
- 57
- 58
- 59if (!function_exists('render_comment_node')) {
- 60 function render_comment_node(
- 61 array $c,
- 62 bool $can_comment,
- 63 string $commentsActionUrl,
- 64 string $csrf,
- 65 callable $loginNext,
- 66 int $depth = 0,
- 67 int $maxDepth = 3
- 68 ) {
- 69 global $baseurl, $mod_rewrite, $lang;
- 70 $___base = rtrim((string)($baseurl ?? ''), '/') . '/';
- 71 $___mr = ((string)($mod_rewrite ?? '1') === '1');
- 72
- 73 $id = (int)($c['id'] ?? 0);
- 74 $username = (string)($c['username'] ?? 'Invité');
- 75 $ts = isset($c['created_at']) ? strtotime((string)$c['created_at']) : 0;
- 76 $ago = $ts ? ('il y a ' . (function_exists('conTime') ? conTime($ts) : date('Y-m-d', $ts))) : '';
- 77 $body_html = comment_body_html_safe($c);
- 78 $can_delete = !empty($c['can_delete']);
- 79 $children = is_array($c['children'] ?? null) ? $c['children'] : [];
- 80 $initial = strtoupper(mb_substr($username !== '' ? $username : 'G', 0, 1, 'UTF-8'));
- 81 $hasKids = !empty($children);
- 82 $clamped = ($depth >= $maxDepth) && $hasKids;
- 83 $threadId = 'thread-' . $id;
- 84 $descCnt = $clamped ? count_descendants($c) : 0;
- 85 $depthStyle = '--d:' . (int)$depth . ';';
- 86
- 87
- 88
- 89
- 90 ?>
- 91 <li id="c-<?php echo $id; ?>" class="list-group-item bg-body comment-item depth-<?php echo (int)$depth; ?>" style="<?php echo $depthStyle; ?>">
- 92 <div class="d-flex gap-3">
- 93 <div class="rounded-circle d-flex align-items-center justify-content-center flex-shrink-0 comment-avatar">
- 94 <span class="fw-bold"><?php echo htmlspecialchars($initial, ENT_QUOTES, 'UTF-8'); ?></span>
- 95 </div>
- 96 <div class="flex-grow-1 comment-main">
- 97 <div class="d-flex align-items-center justify-content-between mb-1">
- 98 <div class="d-flex align-items-center gap-2 flex-wrap">
- 99 <span class="fw-semibold">
- 100 <?php
- 101 $cu = trim($username);
- 102 if ($cu !== '' && strcasecmp($cu, 'Invité') !== 0) {
- 103 $cu_href = $___mr ? ($___base . 'user/' . rawurlencode($cu)) : ($___base . 'user.php?user=' . rawurlencode($cu));
- 104 echo '<a href="' . htmlspecialchars($cu_href, ENT_QUOTES, 'UTF-8') . '" class="text-decoration-none">' . htmlspecialchars($cu, ENT_QUOTES, 'UTF-8') . '</a>';
- 105 } else {
- 106 echo htmlspecialchars($cu ?: 'Invité', ENT_QUOTES, 'UTF-8');
- 107 }
- 108 ?>
- 109 </span>
- 110 <?php if ($ago): ?><span class="text-muted small"><?php echo htmlspecialchars($ago, ENT_QUOTES, 'UTF-8'); ?></span><?php endif; ?>
- 111 <a href="#c-<?php echo $id; ?>" class="comment-permalink ms-1 text-decoration-none">#</a>
- 112 </div>
- 113 <div class="d-flex align-items-center gap-2">
- 114 <?php if ($can_comment): ?>
- 115 <button type="button" class="btn btn-link btn-sm p-0 comment-reply" data-target="#reply-form-<?php echo $id; ?>">
- 116 <i class="bi bi-reply"></i> <?php echo htmlspecialchars($lang['reply'] ?? 'Répondre', ENT_QUOTES, 'UTF-8'); ?>
- 117 </button>
- 118 <?php endif; ?>
- 119 <?php if ($can_delete): ?>
- 120 <form method="post" action="<?php echo htmlspecialchars($commentsActionUrl, ENT_QUOTES, 'UTF-8'); ?>" class="d-inline delete-comment-form">
- 121 <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf, ENT_QUOTES, 'UTF-8'); ?>">
- 122 <input type="hidden" name="action" value="delete_comment">
- 123 <input type="hidden" name="comment_id" value="<?php echo $id; ?>">
- 124 <button type="submit" class="btn btn-sm btn-outline-danger border-0" title="Supprimer"><i class="bi bi-trash"></i></button>
- 125 </form>
- 126 <?php endif; ?>
- 127 </div>
- 128 </div>
- 129 <div class="comment-body lh-base"><?php echo $body_html; ?></div>
- 130
- 131 <?php if ($can_comment): ?>
- 132 <div id="reply-form-<?php echo $id; ?>" class="mt-2 d-none">
- 133 <form method="post" action="<?php echo htmlspecialchars($commentsActionUrl, ENT_QUOTES, 'UTF-8'); ?>">
- 134 <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf, ENT_QUOTES, 'UTF-8'); ?>">
- 135 <input type="hidden" name="action" value="add_comment">
- 136 <input type="hidden" name="parent_id" value="<?php echo $id; ?>">
- 137 <div class="mb-2">
- 138 <textarea class="form-control" name="comment_body" rows="3" required placeholder="Réponse..."></textarea>
- 139 </div>
- 140 <div class="d-flex justify-content-end gap-2">
- 141 <button type="button" class="btn btn-outline-secondary btn-sm reply-cancel" data-target="#reply-form-<?php echo $id; ?>">Annuler</button>
- 142 <button type="submit" class="btn btn-primary btn-sm">Répondre</button>
- 143 </div>
- 144 </form>
- 145 </div>
- 146 <?php endif; ?>
- 147
- 148 <?php if (!empty($children)): ?>
- 149 <?php if ($clamped): ?>
- 150 <div class="mt-2">
- 151 <button class="btn btn-outline-secondary btn-sm comment-expand" data-target="#<?php echo $threadId; ?>">
- 152 <i class="bi bi-chevron-down"></i> Afficher la suite
- 153 </button>
- 154 </div>
- 155 <ul id="<?php echo $threadId; ?>" class="list-group list-group-flush mt-2 d-none" style="--pd: <?php echo (int)$depth; ?>;">
- 156 <?php foreach ($children as $ch) { render_comment_node($ch, $can_comment, $commentsActionUrl, $csrf, $loginNext, $depth + 1, $maxDepth); } ?>
- 157 </ul>
- 158 <?php else: ?>
- 159 <ul class="list-group list-group-flush mt-2" style="--pd: <?php echo (int)$depth; ?>;">
- 160 <?php foreach ($children as $ch) { render_comment_node($ch, $can_comment, $commentsActionUrl, $csrf, $loginNext, $depth + 1, $maxDepth); } ?>
- 161 </ul>
- 162 <?php endif; ?>
- 163 <?php endif; ?>
- 164 </div>
- 165 </div>
- 166 </li>
- 167 <?php
- 168 }
- 169}
- 170?>