feat: page profil public /profil/{slug} avec liste des articles
This commit is contained in:
@@ -41,6 +41,9 @@ RewriteRule ^categories/?$ /index.php?action=categories [L,QSA]
|
||||
RewriteRule ^profile/?$ /index.php?action=profile [L,QSA]
|
||||
RewriteRule ^search/?$ /index.php?action=search [L,QSA]
|
||||
|
||||
# Profil public auteur
|
||||
RewriteRule ^profil/([a-z0-9][a-z0-9-]*)/?$ /index.php?action=author&slug=$1 [L,QSA]
|
||||
|
||||
# Pages statiques
|
||||
RewriteRule ^about/?$ /index.php?action=about [L,QSA]
|
||||
RewriteRule ^legal/?$ /index.php?action=legal [L,QSA]
|
||||
|
||||
@@ -1242,3 +1242,38 @@ footer.mt-5 { margin-top: 0 !important; }
|
||||
}
|
||||
|
||||
.tag-cloud-reset:hover { color: var(--vl-accent); }
|
||||
|
||||
/* ─── Profil public auteur ───────────────── */
|
||||
|
||||
.author-profile-hero {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.author-avatar {
|
||||
flex-shrink: 0;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
border-radius: 50%;
|
||||
background: var(--vl-accent);
|
||||
color: #fff;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.author-profile-name {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 .25rem;
|
||||
}
|
||||
|
||||
.author-profile-link {
|
||||
font-size: .875rem;
|
||||
color: var(--vl-muted);
|
||||
}
|
||||
|
||||
.author-profile-link:hover { color: var(--vl-accent); }
|
||||
|
||||
+35
-4
@@ -851,6 +851,36 @@ switch ($action) {
|
||||
header('Location: /categories');
|
||||
exit;
|
||||
|
||||
case 'author':
|
||||
$authorSlug = trim($_GET['slug'] ?? '');
|
||||
$authorRow = profileBySlug($authorSlug);
|
||||
if (!$authorRow) {
|
||||
http_response_code(404);
|
||||
$content = '<div class="container py-5"><p class="text-muted">Profil introuvable.</p></div>';
|
||||
$title = 'Profil introuvable';
|
||||
include BASE_PATH . '/templates/layout.php';
|
||||
break;
|
||||
}
|
||||
$privateCats = $articles->getPrivateCategories();
|
||||
$authorArticles = array_values(array_filter(
|
||||
$articles->getAll(publishedOnly: true),
|
||||
static function (array $a) use ($authorRow, $privateCats): bool {
|
||||
if (($a['author'] ?? '') !== $authorRow['email']) {
|
||||
return false;
|
||||
}
|
||||
$cat = trim($a['category'] ?? '');
|
||||
if ($cat !== '' && in_array($cat, $privateCats, true) && !isLoggedIn()) {
|
||||
return false;
|
||||
}
|
||||
if (strtotime((string)($a['published_at'] ?? '')) > time() && !hasCapability('view_previews')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
include BASE_PATH . '/templates/author_profile.php';
|
||||
break;
|
||||
|
||||
case 'about':
|
||||
include BASE_PATH . '/templates/about.php';
|
||||
break;
|
||||
@@ -1785,12 +1815,13 @@ switch ($action) {
|
||||
$pdo = dbPdo();
|
||||
if ($pdo) {
|
||||
try {
|
||||
$newSlug = slugify($newName);
|
||||
$st = $pdo->prepare(
|
||||
'INSERT INTO user_profiles (email, display_name, profile_url, updated_at)
|
||||
VALUES (:e, :n, :u, now())
|
||||
ON CONFLICT (email) DO UPDATE SET display_name = :n, profile_url = :u, updated_at = now()'
|
||||
'INSERT INTO user_profiles (email, display_name, profile_url, profile_slug, updated_at)
|
||||
VALUES (:e, :n, :u, :s, now())
|
||||
ON CONFLICT (email) DO UPDATE SET display_name = :n, profile_url = :u, profile_slug = :s, updated_at = now()'
|
||||
);
|
||||
$st->execute([':e' => currentUserEmail(), ':n' => $newName, ':u' => $newUrl]);
|
||||
$st->execute([':e' => currentUserEmail(), ':n' => $newName, ':u' => $newUrl, ':s' => $newSlug]);
|
||||
$_SESSION['user_display_name'] = $newName;
|
||||
$profileSuccess = true;
|
||||
} catch (\Throwable $ex) {
|
||||
|
||||
Reference in New Issue
Block a user