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>
175 lines
6.3 KiB
PHP
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
|
|
];
|
|
}
|
|
];
|