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
+242
View File
@@ -0,0 +1,242 @@
<?php ob_start();
$metaLabels = [
'mime' => 'Type MIME',
'size' => 'Taille originale',
'pages' => 'Pages',
'page_size' => 'Format',
'pdf_version' => 'Version PDF',
'width' => 'Dimensions',
'camera' => 'Appareil photo',
'site_name' => 'Site',
'og_type' => 'Type OG',
'language' => 'Langue',
'date' => 'Date',
'description' => 'Description',
'subject' => 'Sujet',
'keywords' => 'Mots-clés',
'copyright' => 'Copyright',
'credit' => 'Crédit',
'creator' => 'Créé avec',
'producer' => 'Produit par',
'canonical' => 'URL canonique',
'og_image' => 'Image OG',
];
function renderMetaCell(string $key, mixed $val, array $row = []): string
{
return match($key) {
'size' => htmlspecialchars(number_format((float)$val / 1024, 1)) . ' Ko',
'width' => htmlspecialchars((string)$val) . ' × ' . htmlspecialchars((string)($row['height'] ?? '?')) . ' px',
'og_image' => str_starts_with((string)$val, '/')
? '<img src="' . htmlspecialchars((string)$val) . '" style="max-height:64px;max-width:160px;border-radius:4px" alt="">'
: '<a href="' . htmlspecialchars((string)$val) . '" target="_blank" rel="noopener" class="small text-break font-monospace">' . htmlspecialchars((string)$val) . '</a>',
'canonical' => '<a href="' . htmlspecialchars((string)$val) . '" target="_blank" rel="noopener" class="text-break font-monospace small">' . htmlspecialchars((string)$val) . '</a>',
default => htmlspecialchars((string)$val),
};
}
?>
<div class="d-flex align-items-center gap-3 mb-1">
<a href="/?action=edit&uuid=<?= rawurlencode($article['uuid']) ?>" class="btn btn-secondary btn-sm">← Modifier</a>
<h1 class="h4 mb-0">Sources &amp; médias</h1>
</div>
<p class="text-muted small mb-4"><?= htmlspecialchars($article['title']) ?></p>
<?php
// ── Liens & sources externes ──────────────────────────────────────────────────
$externalLinks = $article['external_links'] ?? [];
?>
<section class="mb-5">
<h2 class="h5 border-bottom pb-2 mb-3">
Liens &amp; sources externes
<span class="badge bg-secondary fw-normal ms-1"><?= count($externalLinks) ?></span>
</h2>
<?php if (empty($externalLinks)): ?>
<p class="text-muted">Aucun lien externe enregistré.</p>
<?php else: ?>
<div class="d-flex flex-column gap-3">
<?php foreach ($externalLinks as $lnk):
$lMeta = $lnk['meta'] ?? [];
$lMime = $lMeta['mime'] ?? 'text/html';
$isPdf = ($lMime === 'application/pdf');
$isImg = str_starts_with($lMime, 'image/');
$lHost = parse_url($lnk['url'] ?? '', PHP_URL_HOST) ?? '';
?>
<div class="card">
<div class="card-body p-3">
<div class="d-flex gap-3 align-items-start">
<!-- Vignette (locale uniquement pour respecter la CSP) -->
<?php if (!empty($lMeta['og_image']) && str_starts_with($lMeta['og_image'], '/')): ?>
<img src="<?= htmlspecialchars($lMeta['og_image']) ?>" alt=""
style="width:80px;height:60px;object-fit:cover;border-radius:4px;flex-shrink:0">
<?php else: ?>
<div style="width:40px;font-size:1.8rem;flex-shrink:0;text-align:center;padding-top:2px">
<?= $isPdf ? '📑' : ($isImg ? '🖼' : '🔗') ?>
</div>
<?php endif; ?>
<div class="flex-grow-1 overflow-hidden">
<!-- Titre + URL -->
<div class="fw-semibold mb-1"><?= htmlspecialchars($lnk['name'] ?? '') ?></div>
<a href="<?= htmlspecialchars($lnk['url'] ?? '') ?>" target="_blank" rel="noopener"
class="small text-break font-monospace text-muted">
<?= htmlspecialchars($lnk['url'] ?? '') ?>
</a>
<!-- Auteur · Date ajout -->
<div class="d-flex flex-wrap gap-3 mt-2 small">
<?php if (!empty($lnk['author'])): ?>
<span><span class="text-muted">Auteur :</span> <?= htmlspecialchars($lnk['author']) ?></span>
<?php endif; ?>
<?php if (!empty($lnk['added_at'])): ?>
<span class="text-muted">Ajouté le <?= htmlspecialchars(date('d/m/Y à H:i', strtotime((string)$lnk['added_at']))) ?></span>
<?php endif; ?>
</div>
<!-- Métadonnées -->
<?php
$visibleMeta = array_filter($lMeta, fn ($v, $k) => isset($metaLabels[$k]) && $v !== null && $v !== '' && $k !== 'height', ARRAY_FILTER_USE_BOTH);
?>
<?php if ($visibleMeta): ?>
<table class="table table-sm table-borderless mb-0 mt-2 small">
<tbody>
<?php foreach ($metaLabels as $key => $label):
if (!isset($lMeta[$key]) || $lMeta[$key] === '' || $lMeta[$key] === null) {
continue;
}
?>
<tr>
<th class="text-muted fw-normal text-nowrap pe-3 align-top" style="width:140px"><?= $label ?></th>
<td><?= renderMetaCell($key, $lMeta[$key], $lMeta) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
<?php
// ── Pièces jointes ────────────────────────────────────────────────────────────
$filesMeta = $article['files_meta'] ?? [];
$coverFile = $article['cover'] ?? '';
$realFiles = array_values(array_filter($sourcesFiles, fn ($f) => !str_starts_with($f['name'], '_thumb_')));
?>
<section class="mb-5">
<h2 class="h5 border-bottom pb-2 mb-3">
Pièces jointes
<span class="badge bg-secondary fw-normal ms-1"><?= count($realFiles) ?></span>
</h2>
<?php if (empty($realFiles)): ?>
<p class="text-muted">Aucun fichier joint.</p>
<?php else: ?>
<div class="d-flex flex-column gap-3">
<?php foreach ($sourcesFiles as $f):
if (str_starts_with($f['name'], '_thumb_')) {
continue;
}
$fmeta = $filesMeta[$f['name']] ?? [];
$fExtra = $fmeta['meta'] ?? [];
$fileUrl = '/file?uuid=' . rawurlencode($article['uuid']) . '&name=' . rawurlencode($f['name']);
$isCover = ($f['name'] === $coverFile);
?>
<div class="card">
<div class="card-body p-3">
<div class="d-flex gap-3 align-items-start">
<!-- Vignette -->
<?php if ($f['is_image']): ?>
<a href="<?= htmlspecialchars($fileUrl) ?>" target="_blank" rel="noopener" class="flex-shrink-0">
<img src="<?= htmlspecialchars($fileUrl) ?>" alt=""
style="width:80px;height:60px;object-fit:cover;border-radius:4px;<?= $isCover ? 'outline:2px solid #0d6efd' : '' ?>">
</a>
<?php else: ?>
<div style="width:40px;font-size:1.8rem;flex-shrink:0;text-align:center;padding-top:2px">
<?= match(true) {
str_starts_with($f['mime'], 'video/') => '🎬',
str_starts_with($f['mime'], 'audio/') => '🎵',
$f['mime'] === 'application/pdf' => '📑',
default => '📄',
} ?>
</div>
<?php endif; ?>
<div class="flex-grow-1 overflow-hidden">
<!-- Titre + nom fichier -->
<div class="d-flex align-items-center gap-2 flex-wrap mb-1">
<a href="<?= htmlspecialchars($fileUrl) ?>" target="_blank" rel="noopener" class="fw-semibold">
<?= htmlspecialchars($fmeta['title'] ?? $f['name']) ?>
</a>
<?php if (!empty($fmeta['title'])): ?>
<code class="small text-muted"><?= htmlspecialchars($f['name']) ?></code>
<?php endif; ?>
<?php if ($isCover): ?>
<span class="badge bg-primary">cover</span>
<?php endif; ?>
</div>
<!-- Auteur · Source · Taille -->
<div class="d-flex flex-wrap gap-3 small mb-1">
<span class="text-muted"><?= htmlspecialchars(number_format($f['size'] / 1024, 1)) ?> Ko</span>
<?php if (!empty($fmeta['author'])): ?>
<span><span class="text-muted">Auteur :</span> <?= htmlspecialchars($fmeta['author']) ?></span>
<?php endif; ?>
<?php if (!empty($fmeta['source_url'])): ?>
<span>
<span class="text-muted">Source :</span>
<a href="<?= htmlspecialchars($fmeta['source_url']) ?>" target="_blank" rel="noopener"
class="font-monospace text-break small">
<?= htmlspecialchars($fmeta['source_url']) ?>
</a>
</span>
<?php endif; ?>
</div>
<!-- Métadonnées EXIF/PDF -->
<?php
$visibleExtra = array_filter($fExtra, fn ($v, $k) => isset($metaLabels[$k]) && $v !== null && $v !== '' && $k !== 'height', ARRAY_FILTER_USE_BOTH);
?>
<?php if ($visibleExtra): ?>
<table class="table table-sm table-borderless mb-0 mt-1 small">
<tbody>
<?php foreach ($metaLabels as $key => $label):
if (!isset($fExtra[$key]) || $fExtra[$key] === '' || $fExtra[$key] === null) {
continue;
}
?>
<tr>
<th class="text-muted fw-normal text-nowrap pe-3 align-top" style="width:140px"><?= $label ?></th>
<td><?= renderMetaCell($key, $fExtra[$key], $fExtra) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<?php if (empty($fmeta) && empty($fExtra)): ?>
<span class="text-muted small">Pas de métadonnées enregistrées.</span>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
<?php
$content = ob_get_clean();
$title = 'Sources — ' . htmlspecialchars($article['title']);
include __DIR__ . '/layout.php';