mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 03:29:19 +02:00
Extract pagination into templates/partials/pagination.php
The pagination nav was duplicated between public/index.php and public/search.php
with structural differences: index.php used string concatenation for query params
and had first/last-page buttons (« »); search.php used http_build_query but had
only prev/next (‹ ›) and a flat <span> rather than a <ul>/<li> structure.
- Add templates/partials/pagination.php: accepts $page, $totalPages, $baseParams[]
(any array of query params to preserve); builds URLs with http_build_query;
renders a semantic <nav>/<ul>/<li> block with first/prev/info/next/last buttons,
correct aria-disabled + tabindex on disabled links, and aria-label on each button.
Returns immediately (no output) when $totalPages <= 1.
- Replace inline pagination block in index.php with:
$baseParams = array_filter(['year' => $year]);
include pagination.php
- Replace inline pagination block in search.php with:
$baseParams = array_diff_key($_GET, ['page' => '']);
include pagination.php
This also upgrades search.php to the full first/last button set it was missing.
Both callers verified with php -l. No functional change to existing behaviour.
This commit is contained in:
4
TODO.md
4
TODO.md
@@ -43,7 +43,7 @@ PHP has no component system, but `include`/`require` with variable scoping works
|
|||||||
- [ ] **`jury-fieldset.php`** — the entire jury composition fieldset + JS is duplicated verbatim between `add.php` and `edit.php`; extract into one partial accepting `$juryPresident`, `$juryPromoteur`, `$juryPromoteurExt`, `$juryLecteurs[]`
|
- [ ] **`jury-fieldset.php`** — the entire jury composition fieldset + JS is duplicated verbatim between `add.php` and `edit.php`; extract into one partial accepting `$juryPresident`, `$juryPromoteur`, `$juryPromoteurExt`, `$juryLecteurs[]`
|
||||||
|
|
||||||
### Shared UI partials — `templates/partials/`
|
### Shared UI partials — `templates/partials/`
|
||||||
- [ ] **`pagination.php`** — pagination nav is duplicated between `index.php` and `search.php` with minor variations; unify into one partial accepting `$page`, `$totalPages`, `$baseParams[]`
|
- [x] **`pagination.php`** — pagination nav is duplicated between `index.php` and `search.php` with minor variations; unify into one partial accepting `$page`, `$totalPages`, `$baseParams[]`
|
||||||
- [ ] **`status-badge.php`** — the published/pending badge + access badge pattern is repeated in `index.php` admin table rows; extract into a partial
|
- [ ] **`status-badge.php`** — the published/pending badge + access badge pattern is repeated in `index.php` admin table rows; extract into a partial
|
||||||
- [ ] **`admin-alert.php`** — rename/merge `flash-messages.php` to also handle the 3 different legacy flash key patterns (`$_SESSION['error']`, `$_SESSION['admin_error']`, `$_SESSION['edit_error']`, etc.) that pages still consume manually instead of via `App::consumeFlash()`
|
- [ ] **`admin-alert.php`** — rename/merge `flash-messages.php` to also handle the 3 different legacy flash key patterns (`$_SESSION['error']`, `$_SESSION['admin_error']`, `$_SESSION['edit_error']`, etc.) that pages still consume manually instead of via `App::consumeFlash()`
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ The admin system page (`/admin/system.php`) runs expensive operations on every l
|
|||||||
- [ ] Extract `ThesisEditController` — merges edit.php + actions/edit.php, deduplicate jury fieldset (§2 step 5)
|
- [ ] Extract `ThesisEditController` — merges edit.php + actions/edit.php, deduplicate jury fieldset (§2 step 5)
|
||||||
- [ ] Extract remaining controllers one by one (§2 step 6)
|
- [ ] Extract remaining controllers one by one (§2 step 6)
|
||||||
- [ ] Consolidate action handlers into controller methods (§4)
|
- [ ] Consolidate action handlers into controller methods (§4)
|
||||||
- [ ] Introduce pagination partial `templates/partials/pagination.php` (§6)
|
- [x] Introduce pagination partial `templates/partials/pagination.php` (§6)
|
||||||
- [ ] Introduce admin form partials: select-field, checkbox-list, jury-fieldset (§6)
|
- [ ] Introduce admin form partials: select-field, checkbox-list, jury-fieldset (§6)
|
||||||
- [ ] Unify flash message keys project-wide to `_flash_error` / `_flash_success` (§7)
|
- [ ] Unify flash message keys project-wide to `_flash_error` / `_flash_success` (§7)
|
||||||
- [ ] Move OG tag construction into controller logic (§8)
|
- [ ] Move OG tag construction into controller logic (§8)
|
||||||
|
|||||||
@@ -126,40 +126,10 @@ $bodyClass = 'home-body';
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<?php if ($totalPages > 1): ?>
|
<?php
|
||||||
<nav class="pagination-wrap" aria-label="Pagination">
|
$baseParams = array_filter(['year' => $year]);
|
||||||
<?php $yearParam = $year ? '&year=' . (int)$year : ''; ?>
|
include APP_ROOT . '/templates/partials/pagination.php';
|
||||||
<ul>
|
?>
|
||||||
<li>
|
|
||||||
<a href="?page=1<?= $yearParam ?>"
|
|
||||||
class="pagination-btn <?= $page <= 1 ? 'disabled' : '' ?>"
|
|
||||||
<?= $page <= 1 ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
|
||||||
aria-label="Première page">«</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="?page=<?= max(1, $page - 1) . $yearParam ?>"
|
|
||||||
class="pagination-btn <?= $page <= 1 ? 'disabled' : '' ?>"
|
|
||||||
<?= $page <= 1 ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
|
||||||
aria-label="Page précédente">‹</a>
|
|
||||||
</li>
|
|
||||||
<li class="pagination-info" aria-current="page">
|
|
||||||
<span class="page-current"><?= $page ?></span> / <?= $totalPages ?>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="?page=<?= min($totalPages, $page + 1) . $yearParam ?>"
|
|
||||||
class="pagination-btn <?= $page >= $totalPages ? 'disabled' : '' ?>"
|
|
||||||
<?= $page >= $totalPages ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
|
||||||
aria-label="Page suivante">›</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="?page=<?= $totalPages . $yearParam ?>"
|
|
||||||
class="pagination-btn <?= $page >= $totalPages ? 'disabled' : '' ?>"
|
|
||||||
<?= $page >= $totalPages ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
|
||||||
aria-label="Dernière page">»</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<?php endif; ?>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<?php include APP_ROOT . '/templates/footer.php'; ?>
|
<?php include APP_ROOT . '/templates/footer.php'; ?>
|
||||||
|
|||||||
@@ -179,19 +179,11 @@ $bodyClass = 'search-body';
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<?php if ($totalPages > 1): ?>
|
<?php
|
||||||
<nav class="pagination-wrap" aria-label="Pagination">
|
// Preserve all active search/filter params (strip 'page' — injected by partial)
|
||||||
<a href="?<?= http_build_query(array_merge($_GET, ['page' => max(1, $page - 1)])) ?>"
|
$baseParams = array_diff_key($_GET, ['page' => '']);
|
||||||
class="pagination-btn<?= $page <= 1 ? ' disabled' : '' ?>"
|
include APP_ROOT . '/templates/partials/pagination.php';
|
||||||
<?= $page <= 1 ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
?>
|
||||||
aria-label="Page précédente">‹</a>
|
|
||||||
<span class="pagination-info" aria-current="page"><?= $page ?> / <?= $totalPages ?></span>
|
|
||||||
<a href="?<?= http_build_query(array_merge($_GET, ['page' => min($totalPages, $page + 1)])) ?>"
|
|
||||||
class="pagination-btn<?= $page >= $totalPages ? ' disabled' : '' ?>"
|
|
||||||
<?= $page >= $totalPages ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
|
||||||
aria-label="Page suivante">›</a>
|
|
||||||
</nav>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<p class="search-empty">Aucun résultat pour cette recherche.</p>
|
<p class="search-empty">Aucun résultat pour cette recherche.</p>
|
||||||
|
|||||||
61
templates/partials/pagination.php
Normal file
61
templates/partials/pagination.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pagination partial
|
||||||
|
*
|
||||||
|
* Required variables (set before include):
|
||||||
|
* int $page — current page (1-based)
|
||||||
|
* int $totalPages — total number of pages
|
||||||
|
* array $baseParams — query-string params preserved across page links
|
||||||
|
* (e.g. ['year' => 2024, 'query' => 'design'])
|
||||||
|
* The 'page' key is injected automatically; do not include it.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* <?php $baseParams = array_filter(['year' => $year]); ?>
|
||||||
|
* <?php include APP_ROOT . '/templates/partials/pagination.php'; ?>
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!isset($page, $totalPages) || $totalPages <= 1) {
|
||||||
|
return; // nothing to render
|
||||||
|
}
|
||||||
|
|
||||||
|
$baseParams = isset($baseParams) && is_array($baseParams) ? $baseParams : [];
|
||||||
|
|
||||||
|
/** Build a URL for a given target page, preserving all base params. */
|
||||||
|
$paginationUrl = static function(int $targetPage) use ($baseParams): string {
|
||||||
|
return '?' . http_build_query(array_merge($baseParams, ['page' => $targetPage]));
|
||||||
|
};
|
||||||
|
|
||||||
|
$atFirst = $page <= 1;
|
||||||
|
$atLast = $page >= $totalPages;
|
||||||
|
?>
|
||||||
|
<nav class="pagination-wrap" aria-label="Pagination">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="<?= $paginationUrl(1) ?>"
|
||||||
|
class="pagination-btn<?= $atFirst ? ' disabled' : '' ?>"
|
||||||
|
<?= $atFirst ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
||||||
|
aria-label="Première page">«</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?= $paginationUrl(max(1, $page - 1)) ?>"
|
||||||
|
class="pagination-btn<?= $atFirst ? ' disabled' : '' ?>"
|
||||||
|
<?= $atFirst ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
||||||
|
aria-label="Page précédente">‹</a>
|
||||||
|
</li>
|
||||||
|
<li class="pagination-info" aria-current="page">
|
||||||
|
<span class="page-current"><?= $page ?></span> / <?= $totalPages ?>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?= $paginationUrl(min($totalPages, $page + 1)) ?>"
|
||||||
|
class="pagination-btn<?= $atLast ? ' disabled' : '' ?>"
|
||||||
|
<?= $atLast ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
||||||
|
aria-label="Page suivante">›</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="<?= $paginationUrl($totalPages) ?>"
|
||||||
|
class="pagination-btn<?= $atLast ? ' disabled' : '' ?>"
|
||||||
|
<?= $atLast ? 'aria-disabled="true" tabindex="-1"' : '' ?>
|
||||||
|
aria-label="Dernière page">»</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
Reference in New Issue
Block a user