pagination curseur, layout 3 colonnes article, sidebar fixe

This commit is contained in:
Cedric Abonnel
2026-05-12 00:42:51 +02:00
parent d774042be9
commit be09fad48f
91 changed files with 8152 additions and 816 deletions
+172 -1
View File
@@ -21,15 +21,186 @@ function currentUserEmail(): ?string
return $_SESSION['user_email'] ?? null;
}
function currentUserName(): string
{
if (!isLoggedIn()) {
return '';
}
if (isset($_SESSION['user_display_name']) && $_SESSION['user_display_name'] !== '') {
return $_SESSION['user_display_name'];
}
$name = authorDisplayName(currentUserEmail() ?? '');
$_SESSION['user_display_name'] = $name;
return $name;
}
function authorDisplayName(string $email): string
{
static $cache = [];
$key = strtolower(trim($email));
if ($key === '') {
return '';
}
if (array_key_exists($key, $cache)) {
return $cache[$key];
}
$pdo = dbPdo();
if ($pdo) {
try {
$st = $pdo->prepare('SELECT display_name FROM user_profiles WHERE email = :e');
$st->execute([':e' => $key]);
$name = $st->fetchColumn();
$cache[$key] = ($name !== false && $name !== '') ? $name : explode('@', $key)[0];
return $cache[$key];
} catch (\Throwable) {
}
}
$cache[$key] = explode('@', $key)[0];
return $cache[$key];
}
function dbPdo(): ?PDO
{
static $pdo = null;
static $failed = false;
if ($failed) {
return null;
}
if ($pdo !== null) {
return $pdo;
}
$dsn = $_ENV['DB_DSN'] ?? (getenv('DB_DSN') ?: '');
$user = $_ENV['DB_USER'] ?? (getenv('DB_USER') ?: '');
$pass = $_ENV['DB_PASS'] ?? (getenv('DB_PASS') ?: '');
if (!$dsn) {
$failed = true;
return null;
}
try {
$pdo = new PDO($dsn, $user ?: null, $pass ?: null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (\Throwable) {
$failed = true;
return null;
}
return $pdo;
}
function currentUserRoles(): array
{
if (!isLoggedIn()) {
return [];
}
if (isset($_SESSION['user_roles'])) {
return $_SESSION['user_roles'];
}
$pdo = dbPdo();
if (!$pdo) {
$_SESSION['user_roles'] = [];
return [];
}
try {
$st = $pdo->prepare(
'SELECT r.name FROM roles r
JOIN user_roles ur ON ur.role_id = r.id
WHERE ur.user_email = :e'
);
$st->execute([':e' => strtolower(currentUserEmail() ?? '')]);
$_SESSION['user_roles'] = $st->fetchAll(PDO::FETCH_COLUMN) ?: [];
} catch (\Throwable) {
$_SESSION['user_roles'] = [];
}
return $_SESSION['user_roles'];
}
function hasRole(string $role): bool
{
return in_array($role, currentUserRoles(), true);
}
// Capacités connues — clé => label affiché dans l'admin
const KNOWN_CAPABILITIES = [
'view_sources_own' => 'Voir les sources de ses propres articles',
'view_sources_all' => 'Voir les sources de tous les articles',
'view_drafts_own' => 'Voir ses articles non publiés',
'view_drafts_all' => 'Voir tous les articles non publiés',
'edit_articles_own' => 'Modifier ses propres articles',
'edit_articles_all' => 'Modifier tous les articles',
'rate_articles' => 'Noter des articles',
];
// Groupes pour l'interface d'administration
// 'single' => pas de variante own/all
const CAPABILITY_GROUPS = [
['label' => 'Sources & métadonnées', 'own' => 'view_sources_own', 'all' => 'view_sources_all'],
['label' => 'Articles non publiés', 'own' => 'view_drafts_own', 'all' => 'view_drafts_all'],
['label' => 'Modification', 'own' => 'edit_articles_own', 'all' => 'edit_articles_all'],
['label' => 'Noter des articles', 'single' => 'rate_articles'],
];
function currentUserCapabilities(): array
{
if (!isLoggedIn()) {
return [];
}
if (isset($_SESSION['user_capabilities'])) {
return $_SESSION['user_capabilities'];
}
$pdo = dbPdo();
if (!$pdo) {
$_SESSION['user_capabilities'] = [];
return [];
}
try {
$st = $pdo->prepare(
'SELECT DISTINCT rc.capability
FROM role_capabilities rc
JOIN user_roles ur ON ur.role_id = rc.role_id
WHERE ur.user_email = :e'
);
$st->execute([':e' => strtolower(currentUserEmail() ?? '')]);
$_SESSION['user_capabilities'] = $st->fetchAll(PDO::FETCH_COLUMN) ?: [];
} catch (\Throwable) {
$_SESSION['user_capabilities'] = [];
}
return $_SESSION['user_capabilities'];
}
function hasCapability(string $cap): bool
{
if (isAdmin()) {
return true;
}
return in_array($cap, currentUserCapabilities(), true);
}
function canDoOnArticle(string $baseCap, array $article): bool
{
if (isAdmin()) {
return true;
}
if (hasCapability($baseCap . '_all')) {
return true;
}
if (hasCapability($baseCap . '_own')) {
$owner = strtolower($article['author'] ?? '');
return $owner !== '' && $owner === strtolower(currentUserEmail() ?? '');
}
return false;
}
function isAdmin(): bool
{
$email = currentUserEmail();
if (!$email) {
return false;
}
// Fallback bootstrap : var d'env
$rawAdmin = $_ENV['ADMIN_EMAIL'] ?? (getenv('ADMIN_EMAIL') ?: '');
$allowed = array_filter(array_map('trim', explode(',', (string)$rawAdmin)));
return in_array(strtolower($email), array_map('strtolower', $allowed), true);
if (in_array(strtolower($email), array_map('strtolower', $allowed), true)) {
return true;
}
return hasRole('admin');
}
function ssoLogoutUrl(): string