ae4ac11305
- admin/articles : champ filter_search (titre, insensible casse) cumulable avec auteur/catégorie/statut (#85) - admin/articles : colonne ★ avec toggle rapide featured + filtre filter_featured (#84) - post/ : date de modification sous la date de publication si modifié après mise en ligne (#81) - sources/ : bouton ← Retour à l'article vers post/<slug> au lieu de /edit/<uuid> (#83) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
243 lines
12 KiB
PHP
243 lines
12 KiB
PHP
<?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="/post/<?= rawurlencode($article['slug'] ?? $article['uuid']) ?>" class="btn btn-secondary btn-sm">← Retour à l'article</a>
|
||
<h1 class="h4 mb-0">Sources & 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 & 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';
|