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;
|
$profileSuccess = false;
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$newName = trim($_POST['display_name'] ?? '');
|
$newName = trim($_POST['display_name'] ?? '');
|
||||||
|
$newUrl = trim($_POST['profile_url'] ?? '');
|
||||||
|
if ($newUrl !== '' && !filter_var($newUrl, FILTER_VALIDATE_URL)) {
|
||||||
|
$newUrl = '';
|
||||||
|
}
|
||||||
if ($newName === '') {
|
if ($newName === '') {
|
||||||
$profileError = 'Le nom ne peut pas être vide.';
|
$profileError = 'Le nom ne peut pas être vide.';
|
||||||
} else {
|
} else {
|
||||||
@@ -1782,11 +1786,11 @@ switch ($action) {
|
|||||||
if ($pdo) {
|
if ($pdo) {
|
||||||
try {
|
try {
|
||||||
$st = $pdo->prepare(
|
$st = $pdo->prepare(
|
||||||
'INSERT INTO user_profiles (email, display_name, updated_at)
|
'INSERT INTO user_profiles (email, display_name, profile_url, updated_at)
|
||||||
VALUES (:e, :n, now())
|
VALUES (:e, :n, :u, now())
|
||||||
ON CONFLICT (email) DO UPDATE SET display_name = :n, updated_at = 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;
|
$_SESSION['user_display_name'] = $newName;
|
||||||
$profileSuccess = true;
|
$profileSuccess = true;
|
||||||
} catch (\Throwable $ex) {
|
} catch (\Throwable $ex) {
|
||||||
@@ -1796,6 +1800,7 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$profileCurrentName = currentUserName();
|
$profileCurrentName = currentUserName();
|
||||||
|
$profileCurrentUrl = authorProfileUrl(currentUserEmail() ?? '');
|
||||||
include BASE_PATH . '/templates/profile.php';
|
include BASE_PATH . '/templates/profile.php';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
+21
-6
@@ -35,11 +35,21 @@ function currentUserName(): string
|
|||||||
}
|
}
|
||||||
|
|
||||||
function authorDisplayName(string $email): 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 = [];
|
static $cache = [];
|
||||||
$key = strtolower(trim($email));
|
$key = strtolower(trim($email));
|
||||||
if ($key === '') {
|
if ($key === '') {
|
||||||
return '';
|
return ['name' => '', 'url' => ''];
|
||||||
}
|
}
|
||||||
if (array_key_exists($key, $cache)) {
|
if (array_key_exists($key, $cache)) {
|
||||||
return $cache[$key];
|
return $cache[$key];
|
||||||
@@ -47,15 +57,20 @@ function authorDisplayName(string $email): string
|
|||||||
$pdo = dbPdo();
|
$pdo = dbPdo();
|
||||||
if ($pdo) {
|
if ($pdo) {
|
||||||
try {
|
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]);
|
$st->execute([':e' => $key]);
|
||||||
$name = $st->fetchColumn();
|
$row = $st->fetch(PDO::FETCH_ASSOC);
|
||||||
$cache[$key] = ($name !== false && $name !== '') ? $name : explode('@', $key)[0];
|
if ($row) {
|
||||||
return $cache[$key];
|
$cache[$key] = [
|
||||||
|
'name' => ($row['display_name'] !== '') ? $row['display_name'] : explode('@', $key)[0],
|
||||||
|
'url' => $row['profile_url'] ?? '',
|
||||||
|
];
|
||||||
|
return $cache[$key];
|
||||||
|
}
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cache[$key] = explode('@', $key)[0];
|
$cache[$key] = ['name' => explode('@', $key)[0], 'url' => ''];
|
||||||
return $cache[$key];
|
return $cache[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,9 @@
|
|||||||
<?php if (!empty($articlePublishedAt ?? '')): ?>
|
<?php if (!empty($articlePublishedAt ?? '')): ?>
|
||||||
<meta property="article:published_time" content="<?= htmlspecialchars(date('c', strtotime((string)$articlePublishedAt))) ?>">
|
<meta property="article:published_time" content="<?= htmlspecialchars(date('c', strtotime((string)$articlePublishedAt))) ?>">
|
||||||
<?php endif; ?>
|
<?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) ?>">
|
<meta property="article:author" content="<?= htmlspecialchars($metaAuthor) ?>">
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|||||||
+11
-5
@@ -43,8 +43,9 @@ $externalLinks = $article['external_links'] ?? [];
|
|||||||
<div class="private-ribbon">Privé</div>
|
<div class="private-ribbon">Privé</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php
|
<?php
|
||||||
$authorEmail = $article['author'] ?? '';
|
$authorEmail = $article['author'] ?? '';
|
||||||
$authorName = ($authorEmail !== '' && function_exists('authorDisplayName')) ? authorDisplayName($authorEmail) : '';
|
$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'] ?? ''))));
|
$pubDate = htmlspecialchars(date('d/m/Y', strtotime((string)($article['published_at'] ?? $article['created_at'] ?? ''))));
|
||||||
$hasCover = $coverFile !== '';
|
$hasCover = $coverFile !== '';
|
||||||
$heroExtraClass = $hasCover ? '' : ' article-cover--gradient';
|
$heroExtraClass = $hasCover ? '' : ' article-cover--gradient';
|
||||||
@@ -281,8 +282,9 @@ if ($ogImage === null || $ogImage === '') {
|
|||||||
$ogImage = $article['og_image'] ?? '';
|
$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;
|
$metaAuthor = $authorName;
|
||||||
|
$metaAuthorUrl = $authorProfileUrl;
|
||||||
|
|
||||||
// JSON-LD Article
|
// JSON-LD Article
|
||||||
$jsonLdData = [
|
$jsonLdData = [
|
||||||
@@ -293,7 +295,11 @@ $jsonLdData = [
|
|||||||
'url' => $canonical,
|
'url' => $canonical,
|
||||||
'datePublished' => date('c', strtotime((string)$articlePublishedAt)),
|
'datePublished' => date('c', strtotime((string)$articlePublishedAt)),
|
||||||
'dateModified' => date('c', strtotime((string)($article['updated_at'] ?? $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' => [
|
'publisher' => [
|
||||||
'@type' => 'Person',
|
'@type' => 'Person',
|
||||||
'name' => siteAuthor() !== '' ? siteAuthor() : siteTitle(),
|
'name' => siteAuthor() !== '' ? siteAuthor() : siteTitle(),
|
||||||
|
|||||||
@@ -24,6 +24,14 @@
|
|||||||
placeholder="Prénom Nom" required>
|
placeholder="Prénom Nom" required>
|
||||||
<div class="form-text">Affiché comme auteur sur vos articles.</div>
|
<div class="form-text">Affiché comme auteur sur vos articles.</div>
|
||||||
</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">
|
<div class="mb-3">
|
||||||
<label class="form-label fw-semibold text-muted">Email</label>
|
<label class="form-label fw-semibold text-muted">Email</label>
|
||||||
<input type="text" class="form-control" value="<?= htmlspecialchars(currentUserEmail() ?? '') ?>" disabled>
|
<input type="text" class="form-control" value="<?= htmlspecialchars(currentUserEmail() ?? '') ?>" disabled>
|
||||||
|
|||||||
Reference in New Issue
Block a user