uuid(); // Parcourir toutes les étapes du projet foreach ($project->children() as $step) { // Parcourir tous les fichiers de chaque étape foreach ($step->files() as $file) { if ($file->comments()->isEmpty()) { continue; } $comments = Yaml::decode($file->comments()->value()); if (!is_array($comments)) { continue; } foreach ($comments as $comment) { // Ignorer les commentaires de type reply (gérés par ReplyProvider) if (($comment['type'] ?? 'comment') === 'comment-reply') { continue; } // Ne pas notifier l'auteur de son propre commentaire $authorUuid = $comment['author']['uuid'] ?? ''; if ($authorUuid === $userUuid) { continue; } $readby = $comment['readby'] ?? []; $location = $comment['location'] ?? []; // Assurer que location.project existe toujours if (!isset($location['project'])) { $location['project'] = [ 'uri' => $project->uri(), 'title' => (string) $project->title(), ]; } $notifications[] = [ 'id' => $comment['id'], 'type' => 'comment', 'text' => $comment['text'] ?? '', 'author' => $comment['author'] ?? [], 'date' => $comment['date'] ?? '', 'location' => $location, 'position' => $comment['position'] ?? [], 'readby' => $readby, 'isRead' => in_array($userUuid, $readby), // Métadonnées pour markAsRead '_file' => (string) $file->uuid(), '_stepUri' => $step->uri(), ]; } } // Parcourir aussi les sous-pages (ex: tracks dans virtual-sample) foreach ($step->children() as $subPage) { foreach ($subPage->files() as $file) { if ($file->comments()->isEmpty()) { continue; } $comments = Yaml::decode($file->comments()->value()); if (!is_array($comments)) { continue; } foreach ($comments as $comment) { if (($comment['type'] ?? 'comment') === 'comment-reply') { continue; } $authorUuid = $comment['author']['uuid'] ?? ''; if ($authorUuid === $userUuid) { continue; } $readby = $comment['readby'] ?? []; $location = $comment['location'] ?? []; // Assurer que location.project existe toujours if (!isset($location['project'])) { $location['project'] = [ 'uri' => $project->uri(), 'title' => (string) $project->title(), ]; } $notifications[] = [ 'id' => $comment['id'], 'type' => 'comment', 'text' => $comment['text'] ?? '', 'author' => $comment['author'] ?? [], 'date' => $comment['date'] ?? '', 'location' => $location, 'position' => $comment['position'] ?? [], 'readby' => $readby, 'isRead' => in_array($userUuid, $readby), '_file' => (string) $file->uuid(), '_stepUri' => $subPage->uri(), ]; } } } } return $notifications; } public function markAsRead(string $id, array $location, User $user): bool { $fileUuid = $location['_file'] ?? null; if (!$fileUuid) { return false; } // Trouver le fichier par UUID (peut être avec ou sans préfixe file://) $fileUri = str_starts_with($fileUuid, 'file://') ? $fileUuid : 'file://' . $fileUuid; $file = kirby()->file($fileUri); if (!$file) { return false; } $comments = Yaml::decode($file->comments()->value()); if (!is_array($comments)) { return false; } $userUuid = (string) $user->uuid(); $updated = false; foreach ($comments as &$comment) { if ($comment['id'] === $id) { $comment['readby'] = $comment['readby'] ?? []; if (!in_array($userUuid, $comment['readby'])) { $comment['readby'][] = $userUuid; $updated = true; } break; } } if ($updated) { $file->update(['comments' => $comments]); } return $updated; } }