Files
ecoles/api/comments.php
T
Arnaud 5633969d98 Version initiale — carte des établissements scolaires
Carte Leaflet (annuaire Éducation nationale) + API PHP/MySQL :
fiche établissement (effectifs, IPS, population INSEE, DPE ADEME),
GED documents/photos, commentaires par groupe, gestion utilisateurs
et politique de mots de passe. Imports opendata (effectifs, IPS,
population, DPE, IRIS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 21:35:41 +02:00

154 lines
6.4 KiB
PHP

<?php
/**
* Commentaires — sur une fiche d'établissement OU sur un document précis.
*
* Mêmes règles dans les deux cas : un commentaire est horodaté, porte un texte et
* le nom de son auteur, et n'est visible que par les membres d'un même groupe que
* l'auteur (le super-admin voit tout). Poster nécessite d'appartenir à au moins un
* groupe. L'auteur ou le super-admin peuvent supprimer ; pas d'édition.
*
* Portée : ?uai=UAI (établissement, commentaires « généraux ») ou
* ?item_id=N (document précis). Un commentaire de document n'apparaît pas
* dans les commentaires d'établissement et inversement.
*
* GET ?uai=UAI → { auth, username, role, can_post, can_validate, comments[] }
* GET ?item_id=N → { auth, username, role, can_post, comments[] }
* POST ?uai=UAI | ?item_id=N {body} → crée un commentaire (membre d'un groupe requis)
* DELETE ?id=N → supprime (auteur ou super-admin)
*/
declare(strict_types=1);
require __DIR__ . '/db.php';
try {
$method = $_SERVER['REQUEST_METHOD'];
$itemId = isset($_GET['item_id']) && $_GET['item_id'] !== '' ? (int) $_GET['item_id'] : 0;
// ---- Liste des commentaires visibles ----------------------------------
if ($method === 'GET') {
$uai = trim((string) ($_GET['uai'] ?? ''));
if ($itemId <= 0 && $uai === '') {
json_error('Paramètre uai ou item_id requis.');
}
$me = current_user();
if (!$me) {
json_out(['auth' => false, 'can_post' => false, 'comments' => []]);
}
$isSuper = $me['role'] === 'super';
$canPost = $isSuper || !empty(user_group_ids((int) $me['id']));
// Clause de portée : un document précis, ou l'établissement (hors documents).
if ($itemId > 0) {
$scopeSql = 'c.item_id = ?';
$scopeArg = $itemId;
} else {
$scopeSql = 'c.uai = ? AND c.item_id IS NULL';
$scopeArg = $uai;
}
// Super : tout ; sinon ses propres commentaires + ceux d'un membre partageant
// au moins un groupe avec lui.
if ($isSuper) {
$sql = "SELECT c.id, c.user_id, c.body, c.created_at, u.username
FROM comments c JOIN users u ON u.id = c.user_id
WHERE $scopeSql ORDER BY c.created_at DESC";
$st = db()->prepare($sql);
$st->execute([$scopeArg]);
} else {
$sql = "SELECT c.id, c.user_id, c.body, c.created_at, u.username
FROM comments c JOIN users u ON u.id = c.user_id
WHERE $scopeSql AND (
c.user_id = ?
OR EXISTS (SELECT 1 FROM group_members a
JOIN group_members b ON a.group_id = b.group_id
WHERE a.user_id = ? AND b.user_id = c.user_id))
ORDER BY c.created_at DESC";
$st = db()->prepare($sql);
$st->execute([$scopeArg, (int) $me['id'], (int) $me['id']]);
}
$out = [];
foreach ($st as $r) {
$out[] = [
'id' => (int) $r['id'],
'username' => $r['username'],
'body' => $r['body'],
'created_at' => $r['created_at'],
'mine' => (int) $r['user_id'] === (int) $me['id'],
];
}
$resp = [
'auth' => true,
'username' => $me['username'],
'role' => $me['role'],
'can_post' => $canPost,
'comments' => $out,
];
// Au niveau établissement, indique si l'utilisateur peut éditer les documents.
if ($itemId <= 0) {
$resp['can_validate'] = can_validate_uai($me, $uai);
}
json_out($resp);
}
// ---- Dépôt d'un commentaire -------------------------------------------
if ($method === 'POST') {
$me = require_login();
if ($me['role'] !== 'super' && empty(user_group_ids((int) $me['id']))) {
json_error('Vous devez appartenir à un groupe pour commenter.', 403);
}
$body = trim((string) (body_json()['body'] ?? ''));
if ($body === '') {
json_error('Le commentaire est vide.');
}
if ($itemId > 0) {
// Commentaire sur un document : on récupère l'UAI de l'élément.
$st = db()->prepare('SELECT uai FROM items WHERE id = ?');
$st->execute([$itemId]);
$uai = $st->fetchColumn();
if ($uai === false) {
json_error('Document introuvable.', 404);
}
db()->prepare('INSERT INTO comments (uai, item_id, user_id, body) VALUES (?, ?, ?, ?)')
->execute([$uai, $itemId, (int) $me['id'], $body]);
} else {
$uai = trim((string) ($_GET['uai'] ?? ''));
if ($uai === '') {
json_error('Paramètre uai ou item_id requis.');
}
$chk = db()->prepare('SELECT 1 FROM etablissements WHERE id = ?');
$chk->execute([$uai]);
if (!$chk->fetchColumn()) {
json_error('Établissement inconnu.', 404);
}
db()->prepare('INSERT INTO comments (uai, user_id, body) VALUES (?, ?, ?)')
->execute([$uai, (int) $me['id'], $body]);
}
json_out(['ok' => true, 'id' => (int) db()->lastInsertId()], 201);
}
// ---- Suppression (auteur ou super) ------------------------------------
if ($method === 'DELETE') {
$me = require_login();
$id = (int) ($_GET['id'] ?? 0);
if ($id <= 0) {
json_error('id requis.');
}
$st = db()->prepare('SELECT user_id FROM comments WHERE id = ?');
$st->execute([$id]);
$owner = $st->fetchColumn();
if ($owner === false) {
json_error('Commentaire introuvable.', 404);
}
if ($me['role'] !== 'super' && (int) $owner !== (int) $me['id']) {
json_error('Vous ne pouvez supprimer que vos propres commentaires.', 403);
}
db()->prepare('DELETE FROM comments WHERE id = ?')->execute([$id]);
json_out(['deleted' => $id]);
}
json_error('Méthode non supportée.', 405);
} catch (Throwable $e) {
json_error('Erreur : ' . $e->getMessage(), 500);
}