Initialisation du projet geosector complet (web + flutter)
This commit is contained in:
263
flutt/lib/chat/scripts/send_notification.php
Normal file
263
flutt/lib/chat/scripts/send_notification.php
Normal file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
/**
|
||||
* Script d'envoi de notifications push pour le chat
|
||||
*
|
||||
* Ce script est appelé par l'API backend pour envoyer des notifications
|
||||
* lorsqu'un nouveau message est reçu
|
||||
*/
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use Kreait\Firebase\Factory;
|
||||
use Kreait\Firebase\Messaging\CloudMessage;
|
||||
use Kreait\Firebase\Messaging\Notification;
|
||||
|
||||
class ChatNotificationSender {
|
||||
private $messaging;
|
||||
private $db;
|
||||
|
||||
public function __construct($firebaseServiceAccount, $dbConnection) {
|
||||
$factory = (new Factory)->withServiceAccount($firebaseServiceAccount);
|
||||
$this->messaging = $factory->createMessaging();
|
||||
$this->db = $dbConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie une notification à un utilisateur pour un nouveau message
|
||||
*/
|
||||
public function sendMessageNotification($userId, $messageId, $senderId, $content, $conversationId) {
|
||||
try {
|
||||
// Récupérer les préférences de notification de l'utilisateur
|
||||
$settings = $this->getUserNotificationSettings($userId);
|
||||
|
||||
if (!$settings['enable_notifications']) {
|
||||
return ['status' => 'skipped', 'reason' => 'notifications_disabled'];
|
||||
}
|
||||
|
||||
// Vérifier si la conversation est en silencieux
|
||||
if (in_array($conversationId, $settings['muted_conversations'])) {
|
||||
return ['status' => 'skipped', 'reason' => 'conversation_muted'];
|
||||
}
|
||||
|
||||
// Vérifier le mode Ne pas déranger
|
||||
if ($this->isInDoNotDisturbPeriod($settings)) {
|
||||
return ['status' => 'skipped', 'reason' => 'do_not_disturb'];
|
||||
}
|
||||
|
||||
// Obtenir le token du device
|
||||
$deviceToken = $this->getUserDeviceToken($userId);
|
||||
if (!$deviceToken) {
|
||||
return ['status' => 'error', 'reason' => 'no_device_token'];
|
||||
}
|
||||
|
||||
// Obtenir les informations de l'expéditeur
|
||||
$sender = $this->getSenderInfo($senderId);
|
||||
|
||||
// Obtenir le nom de la conversation
|
||||
$conversationName = $this->getConversationName($conversationId, $userId);
|
||||
|
||||
// Préparation du contenu de la notification
|
||||
$title = $conversationName ?? $sender['name'];
|
||||
$body = $settings['show_preview'] ? $content : 'Nouveau message';
|
||||
|
||||
// Créer le message Firebase
|
||||
$message = CloudMessage::withTarget('token', $deviceToken)
|
||||
->withNotification(Notification::create($title, $body))
|
||||
->withData([
|
||||
'type' => 'chat_message',
|
||||
'messageId' => $messageId,
|
||||
'conversationId' => $conversationId,
|
||||
'senderId' => $senderId,
|
||||
'click_action' => 'FLUTTER_NOTIFICATION_CLICK',
|
||||
])
|
||||
->withAndroidConfig([
|
||||
'priority' => 'high',
|
||||
'notification' => [
|
||||
'sound' => $settings['sound_enabled'] ? 'default' : null,
|
||||
'channel_id' => 'chat_messages',
|
||||
'icon' => 'ic_launcher',
|
||||
],
|
||||
])
|
||||
->withApnsConfig([
|
||||
'payload' => [
|
||||
'aps' => [
|
||||
'sound' => $settings['sound_enabled'] ? 'default' : null,
|
||||
'badge' => 1, // TODO: Calculer le nombre réel de messages non lus
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Envoyer la notification
|
||||
$result = $this->messaging->send($message);
|
||||
|
||||
// Enregistrer la notification dans la base de données
|
||||
$this->saveNotificationToDatabase($userId, $messageId, $conversationId, $title, $body);
|
||||
|
||||
return [
|
||||
'status' => 'success',
|
||||
'message_id' => $result,
|
||||
];
|
||||
|
||||
} catch (Exception $e) {
|
||||
return [
|
||||
'status' => 'error',
|
||||
'reason' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie une notification de type broadcast
|
||||
*/
|
||||
public function sendBroadcastNotification($audienceTargets, $messageId, $content, $conversationId) {
|
||||
$results = [];
|
||||
|
||||
// Résoudre les cibles d'audience
|
||||
$userIds = $this->resolveAudienceTargets($audienceTargets);
|
||||
|
||||
foreach ($userIds as $userId) {
|
||||
$result = $this->sendMessageNotification($userId, $messageId, null, $content, $conversationId);
|
||||
$results[$userId] = $result;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enregistre la notification dans la base de données
|
||||
*/
|
||||
private function saveNotificationToDatabase($userId, $messageId, $conversationId, $title, $body) {
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO chat_notifications (fk_user, fk_message, fk_room, type, contenu, statut)
|
||||
VALUES (?, ?, ?, 'chat_message', ?, 'non_lue')
|
||||
");
|
||||
|
||||
$stmt->execute([$userId, $messageId, $conversationId, json_encode([
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
])]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les préférences de notification de l'utilisateur
|
||||
*/
|
||||
private function getUserNotificationSettings($userId) {
|
||||
// Implémenter la logique pour récupérer les paramètres
|
||||
return [
|
||||
'enable_notifications' => true,
|
||||
'sound_enabled' => true,
|
||||
'vibration_enabled' => true,
|
||||
'muted_conversations' => [],
|
||||
'show_preview' => true,
|
||||
'do_not_disturb' => false,
|
||||
'do_not_disturb_start' => null,
|
||||
'do_not_disturb_end' => null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si on est dans la période Ne pas déranger
|
||||
*/
|
||||
private function isInDoNotDisturbPeriod($settings) {
|
||||
if (!$settings['do_not_disturb']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$now = new DateTime();
|
||||
$start = new DateTime($settings['do_not_disturb_start']);
|
||||
$end = new DateTime($settings['do_not_disturb_end']);
|
||||
|
||||
if ($start < $end) {
|
||||
return $now >= $start && $now <= $end;
|
||||
} else {
|
||||
// Période qui chevauche minuit
|
||||
return $now >= $start || $now <= $end;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le token du device de l'utilisateur
|
||||
*/
|
||||
private function getUserDeviceToken($userId) {
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT device_token
|
||||
FROM notification_settings
|
||||
WHERE user_id = ? AND device_token IS NOT NULL
|
||||
ORDER BY updated_at DESC LIMIT 1
|
||||
");
|
||||
|
||||
$stmt->execute([$userId]);
|
||||
return $stmt->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les informations de l'expéditeur
|
||||
*/
|
||||
private function getSenderInfo($senderId) {
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT id, name, username
|
||||
FROM users
|
||||
WHERE id = ?
|
||||
");
|
||||
|
||||
$stmt->execute([$senderId]);
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le nom de la conversation
|
||||
*/
|
||||
private function getConversationName($conversationId, $userId) {
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT title
|
||||
FROM chat_rooms
|
||||
WHERE id = ?
|
||||
");
|
||||
|
||||
$stmt->execute([$conversationId]);
|
||||
return $stmt->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Résout les cibles d'audience en une liste d'IDs utilisateur
|
||||
*/
|
||||
private function resolveAudienceTargets($targets) {
|
||||
$userIds = [];
|
||||
|
||||
foreach ($targets as $target) {
|
||||
switch ($target['target_type']) {
|
||||
case 'all':
|
||||
// Récupérer tous les utilisateurs
|
||||
$stmt = $this->db->query("SELECT id FROM users WHERE chk_active = 1");
|
||||
$userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
break;
|
||||
|
||||
case 'role':
|
||||
// Récupérer les utilisateurs par rôle
|
||||
$stmt = $this->db->prepare("SELECT id FROM users WHERE fk_role = ?");
|
||||
$stmt->execute([$target['role_filter']]);
|
||||
$userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
break;
|
||||
|
||||
case 'entity':
|
||||
// Récupérer les utilisateurs par entité
|
||||
$stmt = $this->db->prepare("SELECT id FROM users WHERE fk_entite = ?");
|
||||
$stmt->execute([$target['entity_filter']]);
|
||||
$userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
break;
|
||||
|
||||
case 'combined':
|
||||
// Récupérer les utilisateurs par combinaison de rôle et entité
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT id FROM users
|
||||
WHERE fk_role = ? AND fk_entite = ?
|
||||
");
|
||||
$stmt->execute([$target['role_filter'], $target['entity_filter']]);
|
||||
$userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($userIds);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user