feat: profile_url auteur → article:author URL + JSON-LD author.url
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ALTER TABLE user_profiles ADD COLUMN IF NOT EXISTS profile_url TEXT NOT NULL DEFAULT '';
|
||||
+9
-4
@@ -1775,6 +1775,10 @@ switch ($action) {
|
||||
$profileSuccess = false;
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$newName = trim($_POST['display_name'] ?? '');
|
||||
$newUrl = trim($_POST['profile_url'] ?? '');
|
||||
if ($newUrl !== '' && !filter_var($newUrl, FILTER_VALIDATE_URL)) {
|
||||
$newUrl = '';
|
||||
}
|
||||
if ($newName === '') {
|
||||
$profileError = 'Le nom ne peut pas être vide.';
|
||||
} else {
|
||||
@@ -1782,11 +1786,11 @@ switch ($action) {
|
||||
if ($pdo) {
|
||||
try {
|
||||
$st = $pdo->prepare(
|
||||
'INSERT INTO user_profiles (email, display_name, updated_at)
|
||||
VALUES (:e, :n, now())
|
||||
ON CONFLICT (email) DO UPDATE SET display_name = :n, updated_at = now()'
|
||||
'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()'
|
||||
);
|
||||
$st->execute([':e' => currentUserEmail(), ':n' => $newName]);
|
||||
$st->execute([':e' => currentUserEmail(), ':n' => $newName, ':u' => $newUrl]);
|
||||
$_SESSION['user_display_name'] = $newName;
|
||||
$profileSuccess = true;
|
||||
} catch (\Throwable $ex) {
|
||||
@@ -1796,6 +1800,7 @@ switch ($action) {
|
||||
}
|
||||
}
|
||||
$profileCurrentName = currentUserName();
|
||||
$profileCurrentUrl = authorProfileUrl(currentUserEmail() ?? '');
|
||||
include BASE_PATH . '/templates/profile.php';
|
||||
break;
|
||||
|
||||
|
||||
+20
-5
@@ -35,11 +35,21 @@ function currentUserName(): string
|
||||
}
|
||||
|
||||
function authorDisplayName(string $email): string
|
||||
{
|
||||
return authorProfile($email)['name'];
|
||||
}
|
||||
|
||||
function authorProfileUrl(string $email): string
|
||||
{
|
||||
return authorProfile($email)['url'];
|
||||
}
|
||||
|
||||
function authorProfile(string $email): array
|
||||
{
|
||||
static $cache = [];
|
||||
$key = strtolower(trim($email));
|
||||
if ($key === '') {
|
||||
return '';
|
||||
return ['name' => '', 'url' => ''];
|
||||
}
|
||||
if (array_key_exists($key, $cache)) {
|
||||
return $cache[$key];
|
||||
@@ -47,15 +57,20 @@ function authorDisplayName(string $email): string
|
||||
$pdo = dbPdo();
|
||||
if ($pdo) {
|
||||
try {
|
||||
$st = $pdo->prepare('SELECT display_name FROM user_profiles WHERE email = :e');
|
||||
$st = $pdo->prepare('SELECT display_name, profile_url FROM user_profiles WHERE email = :e');
|
||||
$st->execute([':e' => $key]);
|
||||
$name = $st->fetchColumn();
|
||||
$cache[$key] = ($name !== false && $name !== '') ? $name : explode('@', $key)[0];
|
||||
$row = $st->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row) {
|
||||
$cache[$key] = [
|
||||
'name' => ($row['display_name'] !== '') ? $row['display_name'] : explode('@', $key)[0],
|
||||
'url' => $row['profile_url'] ?? '',
|
||||
];
|
||||
return $cache[$key];
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
}
|
||||
}
|
||||
$cache[$key] = explode('@', $key)[0];
|
||||
$cache[$key] = ['name' => explode('@', $key)[0], 'url' => ''];
|
||||
return $cache[$key];
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<?php if (!empty($articlePublishedAt ?? '')): ?>
|
||||
<meta property="article:published_time" content="<?= htmlspecialchars(date('c', strtotime((string)$articlePublishedAt))) ?>">
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($metaAuthor ?? '')): ?>
|
||||
<?php if (!empty($metaAuthorUrl ?? '')): ?>
|
||||
<meta property="article:author" content="<?= htmlspecialchars($metaAuthorUrl) ?>">
|
||||
<?php elseif (!empty($metaAuthor ?? '')): ?>
|
||||
<meta property="article:author" content="<?= htmlspecialchars($metaAuthor) ?>">
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ $externalLinks = $article['external_links'] ?? [];
|
||||
<?php
|
||||
$authorEmail = $article['author'] ?? '';
|
||||
$authorName = ($authorEmail !== '' && function_exists('authorDisplayName')) ? authorDisplayName($authorEmail) : '';
|
||||
$authorProfileUrl = ($authorEmail !== '' && function_exists('authorProfileUrl')) ? authorProfileUrl($authorEmail) : '';
|
||||
$pubDate = htmlspecialchars(date('d/m/Y', strtotime((string)($article['published_at'] ?? $article['created_at'] ?? ''))));
|
||||
$hasCover = $coverFile !== '';
|
||||
$heroExtraClass = $hasCover ? '' : ' article-cover--gradient';
|
||||
@@ -281,8 +282,9 @@ if ($ogImage === null || $ogImage === '') {
|
||||
$ogImage = $article['og_image'] ?? '';
|
||||
}
|
||||
|
||||
// Auteur : nom affiché résolu depuis le champ author du JSON de l'article
|
||||
// Auteur : nom et URL de profil résolus depuis le champ author du JSON de l'article
|
||||
$metaAuthor = $authorName;
|
||||
$metaAuthorUrl = $authorProfileUrl;
|
||||
|
||||
// JSON-LD Article
|
||||
$jsonLdData = [
|
||||
@@ -293,7 +295,11 @@ $jsonLdData = [
|
||||
'url' => $canonical,
|
||||
'datePublished' => date('c', strtotime((string)$articlePublishedAt)),
|
||||
'dateModified' => date('c', strtotime((string)($article['updated_at'] ?? $articlePublishedAt))),
|
||||
'author' => ['@type' => 'Person', 'name' => $metaAuthor !== '' ? $metaAuthor : (siteAuthor() !== '' ? siteAuthor() : siteTitle())],
|
||||
'author' => array_filter([
|
||||
'@type' => 'Person',
|
||||
'name' => $metaAuthor !== '' ? $metaAuthor : (siteAuthor() !== '' ? siteAuthor() : siteTitle()),
|
||||
'url' => $metaAuthorUrl !== '' ? $metaAuthorUrl : null,
|
||||
]),
|
||||
'publisher' => [
|
||||
'@type' => 'Person',
|
||||
'name' => siteAuthor() !== '' ? siteAuthor() : siteTitle(),
|
||||
|
||||
@@ -24,6 +24,14 @@
|
||||
placeholder="Prénom Nom" required>
|
||||
<div class="form-text">Affiché comme auteur sur vos articles.</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold" for="profile_url">URL de profil</label>
|
||||
<input type="url" id="profile_url" name="profile_url"
|
||||
class="form-control"
|
||||
value="<?= htmlspecialchars($profileCurrentUrl) ?>"
|
||||
placeholder="https://example.com/~vous">
|
||||
<div class="form-text">Utilisée dans les métadonnées de vos articles (article:author, JSON-LD).</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold text-muted">Email</label>
|
||||
<input type="text" class="form-control" value="<?= htmlspecialchars(currentUserEmail() ?? '') ?>" disabled>
|
||||
|
||||
Reference in New Issue
Block a user