266 lines
12 KiB
PHP
266 lines
12 KiB
PHP
<?php
|
||
ob_start();
|
||
$CONTEXT = 3;
|
||
|
||
$base = rtrim(APP_URL, '/');
|
||
$effectiveTitle = ($seoTitle !== '') ? $seoTitle : $title;
|
||
$effectiveDesc = ($seoDescription !== '') ? $seoDescription : $autoSeoDesc;
|
||
$effectiveSlug = $postSlug;
|
||
|
||
$coverFilename = ($newCover ?? '') !== '' ? $newCover : ($article['cover'] ?? '');
|
||
$suggestedOgImage = $coverFilename !== ''
|
||
? $base . '/file?uuid=' . rawurlencode($uuid) . '&name=' . rawurlencode($coverFilename)
|
||
: '';
|
||
?>
|
||
|
||
<div class="d-flex align-items-center gap-3 mb-4 flex-wrap">
|
||
<a href="/edit/<?= htmlspecialchars($uuid) ?>" class="btn btn-outline-secondary">← Retour à l'édition</a>
|
||
<h1 class="h4 mb-0">Confirmer les modifications</h1>
|
||
</div>
|
||
|
||
<form method="POST" action="/edit/<?= htmlspecialchars($uuid) ?>">
|
||
<input type="hidden" name="_confirm" value="1">
|
||
<input type="hidden" name="title" value="<?= htmlspecialchars($title) ?>">
|
||
<input type="hidden" name="content" value="<?= htmlspecialchars($content) ?>">
|
||
<?php if ($published): ?>
|
||
<input type="hidden" name="published" value="1">
|
||
<?php endif; ?>
|
||
<input type="hidden" name="published_at" value="<?= htmlspecialchars($published_at) ?>">
|
||
<!-- seo_title et seo_description sont des champs visibles dans la colonne droite -->
|
||
<!-- og_image est calculé depuis la couverture côté serveur -->
|
||
<input type="hidden" name="category" value="<?= htmlspecialchars($category) ?>">
|
||
<?php if (($newCover ?? '') !== ''): ?>
|
||
<input type="hidden" name="cover_file" value="<?= htmlspecialchars($newCover) ?>">
|
||
<?php endif; ?>
|
||
<?php foreach ($fmetaNames as $fi => $fname): ?>
|
||
<input type="hidden" name="fmeta_name[]" value="<?= htmlspecialchars($fname) ?>">
|
||
<input type="hidden" name="fmeta_author[]" value="<?= htmlspecialchars($fmetaAuthors[$fi] ?? '') ?>">
|
||
<input type="hidden" name="fmeta_source[]" value="<?= htmlspecialchars($fmetaSources[$fi] ?? '') ?>">
|
||
<?php endforeach; ?>
|
||
|
||
<div class="row g-4">
|
||
<div class="col-lg-8">
|
||
|
||
<?php if (!empty($changes)): ?>
|
||
<div class="alert alert-info py-2 mb-3">
|
||
<?= htmlspecialchars(ucfirst(implode(' · ', $changes))) ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="alert alert-secondary py-2 mb-3">Aucune modification détectée.</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- ─── Diff ─────────────────────────────────────────────────────────────── -->
|
||
<div class="mb-4">
|
||
<h2 class="h6 fw-semibold mb-2">Diff du contenu</h2>
|
||
<?php if ($diffLines === []): ?>
|
||
<div class="text-muted small">Contenu identique.</div>
|
||
<?php else:
|
||
$total = count($diffLines);
|
||
$show = [];
|
||
for ($i = 0; $i < $total; $i++) {
|
||
if ($diffLines[$i][0] !== '=') {
|
||
for ($c = max(0, $i - $CONTEXT); $c <= min($total - 1, $i + $CONTEXT); $c++) {
|
||
$show[$c] = true;
|
||
}
|
||
}
|
||
}
|
||
$hasChanges = false;
|
||
foreach ($diffLines as [$op]) {
|
||
if ($op !== '=') {
|
||
$hasChanges = true;
|
||
break;
|
||
}
|
||
}
|
||
?>
|
||
<div class="d-flex gap-3 mb-1 small">
|
||
<span class="diff-del px-2 py-1 rounded">− Supprimé</span>
|
||
<span class="diff-ins px-2 py-1 rounded">+ Ajouté</span>
|
||
</div>
|
||
<div class="diff-view font-monospace small">
|
||
<?php $inEllipsis = false;
|
||
for ($i = 0; $i < $total; $i++): ?>
|
||
<?php [$op, $line] = $diffLines[$i]; ?>
|
||
<?php if (!isset($show[$i])): ?>
|
||
<?php if (!$inEllipsis): $inEllipsis = true; ?>
|
||
<div class="diff-ellipsis text-muted px-2">⋯</div>
|
||
<?php endif;
|
||
continue; ?>
|
||
<?php else: $inEllipsis = false; endif; ?>
|
||
<?php if ($op === '!'): ?>
|
||
<div class="diff-warning text-warning px-2"><?= htmlspecialchars($line) ?></div>
|
||
<?php elseif ($op === '-'): ?>
|
||
<div class="diff-del px-2">− <?= htmlspecialchars($line) ?></div>
|
||
<?php elseif ($op === '+'): ?>
|
||
<div class="diff-ins px-2">+ <?= htmlspecialchars($line) ?></div>
|
||
<?php else: ?>
|
||
<div class="diff-eq px-2 text-muted"> <?= htmlspecialchars($line) ?></div>
|
||
<?php endif; ?>
|
||
<?php endfor; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- ─── Slug ─────────────────────────────────────────────────────────────── -->
|
||
<?php
|
||
$slugDefault = ($titleChanged && $autoSlug !== $postSlug) ? $autoSlug : $postSlug;
|
||
$slugOriginal = $postSlug;
|
||
?>
|
||
<div class="mb-3">
|
||
<label for="confirm-slug" class="form-label fw-semibold">
|
||
Slug (URL permanente)
|
||
<small class="text-muted fw-normal">— /post/<span id="slug-display"><?= htmlspecialchars($slugDefault) ?></span></small>
|
||
</label>
|
||
<input type="text" class="form-control form-control-sm font-monospace" id="confirm-slug" name="slug"
|
||
value="<?= htmlspecialchars($slugDefault) ?>"
|
||
pattern="[a-z0-9][a-z0-9\-]*"
|
||
oninput="document.getElementById('slug-display').textContent=this.value">
|
||
<?php if ($titleChanged && $autoSlug !== $slugOriginal): ?>
|
||
<div class="mt-2 d-flex align-items-center gap-2 flex-wrap">
|
||
<small class="text-muted">Slug recalculé depuis le nouveau titre. Slug initial :</small>
|
||
<code class="small"><?= htmlspecialchars($slugOriginal) ?></code>
|
||
<button type="button" id="slug-btn-keep" class="btn btn-sm btn-outline-secondary py-0"
|
||
data-slug-keep="<?= htmlspecialchars($slugOriginal) ?>">
|
||
Conserver
|
||
</button>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- ─── Commentaire de révision ──────────────────────────────────────────── -->
|
||
<div class="mb-4">
|
||
<label for="revision_comment" class="form-label fw-semibold">
|
||
Commentaire de révision <small class="text-muted fw-normal">(optionnel)</small>
|
||
</label>
|
||
<input type="text" class="form-control" id="revision_comment" name="revision_comment"
|
||
value="<?= htmlspecialchars($autoRevisionComment) ?>"
|
||
placeholder="ex. Correction typos, ajout section X…">
|
||
</div>
|
||
|
||
<div class="d-flex gap-3 flex-wrap">
|
||
<button type="submit" class="btn btn-success">Confirmer et enregistrer</button>
|
||
<a href="/edit/<?= htmlspecialchars($uuid) ?>" class="btn btn-outline-secondary">← Retour</a>
|
||
</div>
|
||
|
||
</div><!-- /col-lg-8 -->
|
||
|
||
<!-- ─── SEO ───────────────────────────────────────────────────────────────── -->
|
||
<div class="col-lg-4">
|
||
<div class="card border-secondary mb-3">
|
||
<div class="card-header bg-transparent py-2">
|
||
<span class="fw-semibold small">SEO — titre, description, image</span>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="mb-3">
|
||
<label for="seo_title" class="form-label small">
|
||
Titre SEO <small class="text-muted">(og:title, <title>)</small>
|
||
</label>
|
||
<input type="text" class="form-control form-control-sm" id="seo_title" name="seo_title"
|
||
maxlength="70"
|
||
value="<?= htmlspecialchars($seoTitle) ?>"
|
||
placeholder="<?= htmlspecialchars($title) ?>">
|
||
<div class="d-flex justify-content-between mt-1">
|
||
<small class="text-muted">Idéal : 30–60 car.</small>
|
||
<small id="seo_title_counter" class="text-muted">0 / 60</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label for="seo_description" class="form-label small">
|
||
Description SEO <small class="text-muted">(meta description)</small>
|
||
</label>
|
||
<textarea class="form-control form-control-sm" id="seo_description" name="seo_description"
|
||
rows="3" maxlength="200"
|
||
placeholder="<?= htmlspecialchars(mb_strimwidth($autoSeoDesc, 0, 80, '…')) ?>"><?= htmlspecialchars($seoDescription) ?></textarea>
|
||
<div class="d-flex justify-content-between mt-1">
|
||
<small class="text-muted">Idéal : 120–155 car.</small>
|
||
<small id="seo_desc_counter" class="text-muted">0 / 155</small>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card border-secondary">
|
||
<div class="card-header bg-transparent py-2">
|
||
<span class="fw-semibold small">Aperçu dans les moteurs de recherche</span>
|
||
</div>
|
||
<div class="card-body p-3">
|
||
<?php
|
||
$pubTs = strtotime((string)($published_at ?? $article['published_at'] ?? ''));
|
||
$modTs = time(); // sera mis à jour à la sauvegarde
|
||
$pubFmt = $pubTs ? date('d/m/Y H:i', $pubTs) : '—';
|
||
$modFmt = date('d/m/Y H:i', $modTs);
|
||
$catVal = trim($category ?? '');
|
||
?>
|
||
<div class="seo-preview mb-3">
|
||
<div class="seo-preview-url small text-truncate mb-1" id="preview-url">
|
||
<?= htmlspecialchars(rtrim($base, '/') . '/post/' . $effectiveSlug) ?>
|
||
</div>
|
||
<div class="seo-preview-title mb-1" id="preview-title">
|
||
<?= htmlspecialchars($effectiveTitle) ?>
|
||
</div>
|
||
<div class="seo-preview-desc small" id="preview-desc">
|
||
<?= htmlspecialchars($effectiveDesc) ?>
|
||
</div>
|
||
</div>
|
||
<table class="table table-sm table-borderless mb-0 small">
|
||
<tbody>
|
||
<tr>
|
||
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap" style="width:1%">Auteur</th>
|
||
<td><?= htmlspecialchars(currentUserName() ?: (currentUserEmail() ?? '—')) ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Publication</th>
|
||
<td><?= htmlspecialchars($pubFmt) ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Modification</th>
|
||
<td><?= htmlspecialchars($modFmt) ?> <small class="text-muted">(après enreg.)</small></td>
|
||
</tr>
|
||
<tr>
|
||
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Langue</th>
|
||
<td>fr-FR</td>
|
||
</tr>
|
||
<tr>
|
||
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Catégorie</th>
|
||
<td><?= $catVal !== '' ? htmlspecialchars($catVal) : '<span class="text-muted">—</span>' ?></td>
|
||
</tr>
|
||
<tr>
|
||
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">og:image</th>
|
||
<td class="text-truncate" style="max-width:0">
|
||
<?= $suggestedOgImage !== '' ? '<span title="' . htmlspecialchars($suggestedOgImage) . '">' . htmlspecialchars($coverFilename) . '</span>' : '<span class="text-muted">— (pas de couverture)</span>' ?>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /row -->
|
||
</form>
|
||
|
||
<style>
|
||
.diff-view { border: 1px solid var(--bs-border-color, #dee2e6); border-radius: 6px; overflow-x: auto; }
|
||
.diff-view > div { padding: 1px 8px; white-space: pre; line-height: 1.5; }
|
||
.diff-del { background: #ffeef0; color: #b91c1c; }
|
||
.diff-ins { background: #e6ffec; color: #15803d; }
|
||
.diff-eq { }
|
||
.diff-ellipsis { background: #f8f9fa; padding: 2px 8px; user-select: none; }
|
||
|
||
.seo-preview { border: 1px solid #dee2e6; border-radius: 6px; padding: 10px 12px; background: #fff; }
|
||
.seo-preview-url { color: #006621; font-size: .78rem; }
|
||
.seo-preview-title { color: #1a0dab; font-size: 1.05rem; font-weight: 500; line-height: 1.3; word-break: break-word; }
|
||
.seo-preview-desc { color: #545454; line-height: 1.5; }
|
||
</style>
|
||
<div id="pc-data" hidden
|
||
data-default-title="<?= htmlspecialchars($effectiveTitle) ?>"
|
||
data-default-desc="<?= htmlspecialchars($effectiveDesc) ?>"
|
||
data-base-url="<?= htmlspecialchars(rtrim($base, '/') . '/post/') ?>"></div>
|
||
<script src="/assets/js/post_confirm.js"></script>
|
||
|
||
<?php
|
||
$content = ob_get_clean();
|
||
$title = 'Confirmer — ' . $title;
|
||
include __DIR__ . '/layout.php';
|