mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 03:29:19 +02:00
fix(admin): stats bar always shows whole-DB counts, not filtered counts
admin/index.php showed "TFE total / Publiés / En attente" by running array_filter() over the already-filtered $theses array returned by getThesesList(). When any search or year filter was active the three numbers reflected only the matching subset, making the stats misleading (e.g. searching for a single student would show "1 total, 0 publiés"). Add Database::getThesesStats(): array — a single SQL aggregation query: SELECT COUNT(*), SUM(is_published), SUM(NOT is_published) FROM theses This runs against the raw theses table with no filters, so the counters always display the true whole-database figures regardless of what filter the admin has active. admin/index.php now calls getThesesStats() and reads $stats['total'], $stats['published'], $stats['pending'] instead of the array_filter expressions.
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -555,7 +555,7 @@ Goal: rename the tables and column to the canonical M2M pattern (`tags`, `thesis
|
|||||||
manually prepare `SELECT … FROM thesis_files WHERE thesis_id = ?` instead of calling
|
manually prepare `SELECT … FROM thesis_files WHERE thesis_id = ?` instead of calling
|
||||||
`$db->getThesisFiles($thesisId)` which already exists. Replace with the DB method.
|
`$db->getThesisFiles($thesisId)` which already exists. Replace with the DB method.
|
||||||
|
|
||||||
- [ ] **`admin/index.php` stats computed via PHP `array_filter` on full result set** — "total",
|
- [x] **`admin/index.php` stats computed via PHP `array_filter` on full result set** — "total",
|
||||||
"publiés", "en attente" counts are derived by filtering the already-fetched `$theses` array
|
"publiés", "en attente" counts are derived by filtering the already-fetched `$theses` array
|
||||||
in PHP. When a filter is active the stats reflect only filtered rows, which is misleading.
|
in PHP. When a filter is active the stats reflect only filtered rows, which is misleading.
|
||||||
Add `Database::getThesesStats(): array` returning three counts from SQL
|
Add `Database::getThesesStats(): array` returning three counts from SQL
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ try {
|
|||||||
if ($orientationFilter) $filters['orientation'] = $orientationFilter;
|
if ($orientationFilter) $filters['orientation'] = $orientationFilter;
|
||||||
|
|
||||||
$theses = $db->getThesesList($filters);
|
$theses = $db->getThesesList($filters);
|
||||||
|
$stats = $db->getThesesStats();
|
||||||
$years = $db->getAllYears();
|
$years = $db->getAllYears();
|
||||||
$orientations = $db->getAllOrientations();
|
$orientations = $db->getAllOrientations();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@@ -95,18 +96,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Stats -->
|
<!-- Stats (always reflects full DB, independent of active filters) -->
|
||||||
<div class="admin-stats">
|
<div class="admin-stats">
|
||||||
<div class="admin-stat">
|
<div class="admin-stat">
|
||||||
<div class="admin-stat__number"><?= count($theses) ?></div>
|
<div class="admin-stat__number"><?= $stats['total'] ?></div>
|
||||||
<div class="admin-stat__label">TFE total</div>
|
<div class="admin-stat__label">TFE total</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="admin-stat">
|
<div class="admin-stat">
|
||||||
<div class="admin-stat__number"><?= count(array_filter($theses, fn($t) => $t['is_published'])) ?></div>
|
<div class="admin-stat__number"><?= $stats['published'] ?></div>
|
||||||
<div class="admin-stat__label">Publiés</div>
|
<div class="admin-stat__label">Publiés</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="admin-stat">
|
<div class="admin-stat">
|
||||||
<div class="admin-stat__number"><?= count(array_filter($theses, fn($t) => !$t['is_published'])) ?></div>
|
<div class="admin-stat__number"><?= $stats['pending'] ?></div>
|
||||||
<div class="admin-stat__label">En attente</div>
|
<div class="admin-stat__label">En attente</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -540,6 +540,30 @@ class Database {
|
|||||||
return $stmt->fetchAll(PDO::FETCH_COLUMN);
|
return $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whole-database thesis counts, independent of any active filter.
|
||||||
|
*
|
||||||
|
* Always reflects the full theses table so the stats bar in admin/index.php
|
||||||
|
* shows accurate numbers even when a search or year filter is active.
|
||||||
|
*
|
||||||
|
* @return array{total: int, published: int, pending: int}
|
||||||
|
*/
|
||||||
|
public function getThesesStats(): array {
|
||||||
|
$stmt = $this->pdo->query(
|
||||||
|
"SELECT
|
||||||
|
COUNT(*) AS total,
|
||||||
|
SUM(CASE WHEN is_published = 1 THEN 1 ELSE 0 END) AS published,
|
||||||
|
SUM(CASE WHEN is_published = 0 THEN 1 ELSE 0 END) AS pending
|
||||||
|
FROM theses"
|
||||||
|
);
|
||||||
|
$row = $stmt->fetch();
|
||||||
|
return [
|
||||||
|
'total' => (int) $row['total'],
|
||||||
|
'published' => (int) $row['published'],
|
||||||
|
'pending' => (int) $row['pending'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// CRUD METHODS (from formulaire)
|
// CRUD METHODS (from formulaire)
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[1774615474]
|
[1774694544]
|
||||||
BIN
storage/test.db
BIN
storage/test.db
Binary file not shown.
Reference in New Issue
Block a user