designtopack/public/site/config/routes/migrate-notifications.php
isUnknown a7d315942a Refonte du système de notifications : passage aux notifications dérivées
Remplace le système de notifications stockées par un système de providers
qui dérivent les notifications des données existantes (commentaires, réponses,
demandes de projet, demandes de rendez-vous, validations de brief).

- Ajout du NotificationCollector et de l'interface NotificationProvider
- Création de 5 providers : Comment, Reply, ProjectRequest, AppointmentRequest, Content
- Métadonnées de notifications stockées directement sur les entités source
- Nouvelles routes mark-as-read et mark-all-read
- Mise à jour du frontend pour le nouveau système
- Route de migration pour les données existantes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 10:31:31 +01:00

175 lines
6.3 KiB
PHP

<?php
/**
* Script de migration unique pour le système de notifications dérivées.
*
* Ce script copie les `readby[]` des anciennes notifications vers les sources de données.
* À exécuter une seule fois après le déploiement, puis à supprimer.
*
* Usage: POST /migrate-notifications.json
*/
return [
'pattern' => 'migrate-notifications.json',
'method' => 'POST',
'action' => function () {
$user = kirby()->user();
// Vérifier que l'utilisateur est admin
if (!$user || $user->role()->id() !== 'admin') {
return [
'status' => 'error',
'message' => 'Cette action nécessite les droits administrateur.'
];
}
$migrated = [
'comments' => 0,
'replies' => 0,
'project-requests' => 0,
'appointment-requests' => 0,
'content' => 0,
'errors' => []
];
$projects = page('projects')->children();
foreach ($projects as $project) {
// Récupérer les anciennes notifications
$notifications = $project->notifications()->yaml() ?? [];
if (empty($notifications)) {
continue;
}
foreach ($notifications as $notification) {
try {
$type = $notification['type'] ?? 'comment';
$id = $notification['id'] ?? null;
$readby = $notification['readby'] ?? [];
if (empty($id) || empty($readby)) {
continue;
}
switch ($type) {
case 'comment':
case 'comment-reply':
$fileUuid = $notification['location']['file']['uuid'] ?? null;
if (!$fileUuid) continue 2;
$file = kirby()->file($fileUuid);
if (!$file) continue 2;
$comments = Yaml::decode($file->comments()->value()) ?? [];
$updated = false;
foreach ($comments as &$comment) {
// Vérifier si c'est le commentaire principal
if ($comment['id'] === $id) {
$existingReadby = $comment['readby'] ?? [];
$comment['readby'] = array_values(array_unique(array_merge($existingReadby, $readby)));
$updated = true;
$migrated['comments']++;
break;
}
// Vérifier dans les réponses
foreach ($comment['replies'] ?? [] as &$reply) {
if ($reply['id'] === $id) {
$existingReadby = $reply['readby'] ?? [];
$reply['readby'] = array_values(array_unique(array_merge($existingReadby, $readby)));
$updated = true;
$migrated['replies']++;
break 2;
}
}
}
if ($updated) {
$file->update(['comments' => $comments]);
}
break;
case 'project-request':
$existingReadby = $project->requestReadby()->yaml() ?? [];
$newReadby = array_values(array_unique(array_merge($existingReadby, $readby)));
$updateData = ['requestReadby' => $newReadby];
// Migrer aussi les métadonnées si elles n'existent pas encore
if ($project->requestAuthor()->isEmpty() && isset($notification['author'])) {
$updateData['requestAuthor'] = $notification['author']['uuid'] ?? '';
$updateData['requestAuthorName'] = $notification['author']['name'] ?? '';
$updateData['requestAuthorEmail'] = $notification['author']['email'] ?? '';
$updateData['requestDate'] = $notification['date'] ?? '';
}
$project->update($updateData);
$migrated['project-requests']++;
break;
case 'appointment-request':
$existingReadby = $project->optimizationReadby()->yaml() ?? [];
$newReadby = array_values(array_unique(array_merge($existingReadby, $readby)));
$updateData = ['optimizationReadby' => $newReadby];
// Migrer aussi les métadonnées si elles n'existent pas encore
if ($project->optimizationAuthor()->isEmpty() && isset($notification['author'])) {
$updateData['optimizationAuthor'] = $notification['author']['uuid'] ?? '';
$updateData['optimizationAuthorName'] = $notification['author']['name'] ?? '';
$updateData['optimizationAuthorEmail'] = $notification['author']['email'] ?? '';
$updateData['optimizationDate'] = $notification['date'] ?? '';
}
$project->update($updateData);
$migrated['appointment-requests']++;
break;
case 'content':
$briefUri = $notification['location']['page']['uri'] ?? null;
if (!$briefUri) continue 2;
$brief = page($briefUri);
if (!$brief) continue 2;
$existingReadby = $brief->validationReadby()->yaml() ?? [];
$newReadby = array_values(array_unique(array_merge($existingReadby, $readby)));
$updateData = ['validationReadby' => $newReadby];
// Migrer aussi les métadonnées si elles n'existent pas encore
if ($brief->validatedBy()->isEmpty() && isset($notification['author'])) {
$updateData['validatedBy'] = $notification['author']['uuid'] ?? '';
$updateData['validatedByName'] = $notification['author']['name'] ?? '';
$updateData['validatedByEmail'] = $notification['author']['email'] ?? '';
$updateData['validatedAt'] = $notification['date'] ?? '';
}
$brief->update($updateData);
$migrated['content']++;
break;
}
} catch (\Throwable $th) {
$migrated['errors'][] = [
'project' => $project->title()->value(),
'notification_id' => $id ?? 'unknown',
'type' => $type ?? 'unknown',
'error' => $th->getMessage()
];
}
}
}
$total = $migrated['comments'] + $migrated['replies'] +
$migrated['project-requests'] + $migrated['appointment-requests'] +
$migrated['content'];
return [
'status' => 'success',
'message' => "Migration terminée. $total notifications migrées.",
'details' => $migrated
];
}
];