xorgxx / warp-messenger-bundle
WarpMessengerBundle is a modular, warp multi-channel messaging bundle for Symfony.
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/xorgxx/warp-messenger-bundle
Requires
- php: >=8.2
- symfony/amqp-messenger: ^6.0 || ^7.0
- symfony/asset: ^6.3|^7.0
- symfony/asset-mapper: ^6.3|^7.0
- symfony/framework-bundle: ^6.0 || ^7.0
- symfony/messenger: ^6.0 || ^7.0
- symfony/ux-icons: ^2.0
- symfony/ux-live-component: ^2.0
- symfony/ux-turbo: ^2.0
- symfony/ux-twig-component: *
- twig/twig: ^3.0
Suggests
- symfony/mercure-bundle: ^0.3.0 - Pour activer les notifications en temps réel dans le navigateur
This package is auto-updated.
Last update: 2025-11-06 12:51:55 UTC
README
Adaptateur SMS Personnalisé
Présentation
Ce projet implémente un adaptateur SMS personnalisé pour le bundle WarpMessengerBundle. L'adaptateur utilise une API SMS externe pour envoyer des messages texte.
Configuration
L'adaptateur SMS est configuré dans src/Service/Sms/MonAdapterSmsProvider.php et utilise les clés d'API directement codées :
$apiKey = 'votre_cle_api'; // SMS_API_KEY $apiSecret = 'votre_secret_api'; // SMS_API_SECRET
Utilisation
Pour envoyer un SMS :
$monAdapterSmsProvider->send('+33612345678', 'Votre message ici');
Fonctionnalités supportées
- Support Unicode
- Concaténation de SMS longs
- Rapports de livraison
Dépendances
WarpMessengerBundle est une solution complète et moderne pour l'envoi de messages multi-canaux dans les applications Symfony. Il permet d'envoyer facilement des messages via différents canaux (email, SMS, Discord, etc.) avec une API fluide et une architecture extensible.
Note: Les notifications en temps réel via Mercure sont optionnelles. Pour les activer, installez simplement le bundle Mercure avec
composer require symfony/mercure-bundle.
Documentation Avancée
Pour approfondir les fonctionnalités avancées, consultez les guides détaillés suivants :
- 📝 Guide d'installation détaillé - Configuration complète et options
- 🔌 Canaux personnalisés - Créer vos propres adaptateurs de communication
- 🌐 Utilisation de Mercure - Notifications temps réel dans le navigateur
- 📊 Journalisation des messages - Suivre et analyser vos envois
- 📱 Communication multi-canal - Utiliser plusieurs canaux simultanément
- 📋 Exemples pratiques - Cas d'utilisation courants
- 🖥️ Commandes CLI - Utilisation en ligne de commande
Installation
composer require xorgxx/warp-messenger-bundle
Consultez le guide d'installation détaillé pour plus d'informations sur la configuration et les fonctionnalités optionnelles.
Caractéristiques
✅ API fluide intuitive - API en chaîne de méthodes (fluent API) pour une expérience développeur optimale
✅ Multi-canal - Envoi de messages via différents canaux (email, SMS, Discord) avec une seule configuration
✅ Extensible - Architecture modulaire permettant d'ajouter facilement de nouveaux canaux
✅ Templating Twig - Utilisation de templates Twig pour le formatage des messages
✅ Gestion intelligente des SMS - Concaténation automatique, détection Unicode, optimisation de la longueur
✅ Canaux de secours - Envoi automatique via des canaux alternatifs en cas d'échec
✅ Résultats détaillés - Informations précises sur le statut d'envoi et les erreurs
✅ Intégration Symfony - Compatibilité totale avec les composants Symfony (Messenger, Mailer, EventDispatcher)
Installation
Via Composer
composer require neoxx/warp-messenger-bundle
Configuration du bundle
Activez le bundle dans config/bundles.php :
return [ // ... Warp\MessengerBundle\WarpMessengerBundle::class => ['all' => true], ];
Créez un fichier de configuration config/packages/warp_messenger.yaml :
warp_messenger: # Templates par défaut pour chaque canal templates: email: 'emails/default.html.twig' sms: 'sms/default.txt.twig' discord: 'discord/default.txt.twig' # Configuration spécifique SMS sms: enable_concat: true # Autoriser la concaténation des SMS longs enable_truncate: false # Autoriser la troncature des SMS longs # Expéditeurs par défaut default_from: email: 'noreply@example.com' sms: 'WARP' # Canaux de secours en cas d'échec fallback_channels: enabled: false default: ['email'] # Configuration générale log_messages: true # Journaliser les messages enable_retries: false # Activer les nouvelles tentatives
Utilisation
Injection du service
use Warp\MessengerBundle\Service\WarpMessenger; class NotificationService { public function __construct( private WarpMessenger $messenger ) {} // ... }
Envoi d'un message simple
$messenger->createMessage("Contenu du message") ->to([ 'email' => 'utilisateur@example.com', 'sms' => '+33612345678' ]) ->send();
Exemple multichanal complet
/** * Envoi d'une notification multichanal pour une commande */ public function notifierClient(WarpMessenger $messenger, Order $order, User $client) { // Préparer les données communes pour tous les canaux $commonData = [ 'order' => $order, 'client' => $client, 'order_number' => $order->getReference(), 'shipping_date' => $order->getShippingDate()->format('d/m/Y'), 'tracking_url' => $this->generateTrackingUrl($order), 'logo_url' => 'https://example.com/logo.png' ]; // Créer un message avec gestion des erreurs et canaux de secours $result = $messenger->createMessage() // Définir tous les destinataires pour tous les canaux ->to([ // Email principal avec nom complet 'email' => new Address($client->getEmail(), $client->getFullName()), // SMS avec le numéro formaté pour l'international 'sms' => $client->getFormattedPhoneNumber(), // Notification Discord sur le canal approprié 'discord' => $this->params->get('discord.customer_notifications_webhook'), // Pour les clients qui utilisent l'application mobile 'push' => $client->getPushTokens() ]) // Activer uniquement les canaux que le client a autorisés dans ses préférences ->onChannels($client->getEnabledNotificationChannels()) // Template email avec données spécifiques à l'email ->usingTemplate('emails/order_shipped.html.twig', array_merge($commonData, [ 'subject' => 'Votre commande ' . $order->getReference() . ' a été expédiée', 'cc' => $client->getSecondarEmails(), 'attachments' => [ // Ajouter automatiquement la facture PDF $this->invoiceGenerator->generatePdfPath($order) ] ])) // Métadonnées pour le suivi et les statistiques ->withMetadata([ 'order_id' => $order->getId(), 'client_id' => $client->getId(), 'notification_type' => 'order_shipped', 'priority' => 'high' ]) // Configurer les options avancées ->withOptions([ 'track_opens' => true, // Tracker l'ouverture des emails 'track_clicks' => true, // Tracker les clics dans les emails 'save_history' => true, // Sauvegarder l'historique des envois 'retry_on_failure' => true, // Réessayer en cas d'échec 'max_retries' => 3, // Nombre maximum de tentatives 'retry_delay' => 300 // Délai entre les tentatives (secondes) ]) // Envoyer le message et récupérer le résultat détaillé ->send(); // Analyser les résultats de l'envoi if ($result->isCompleteSuccess()) { $this->logger->info('Notification envoyée avec succès sur tous les canaux', [ 'order' => $order->getId(), 'channels' => $result->getSuccessfulChannels() ]); } elseif ($result->isPartialSuccess()) { $this->logger->warning('Notification partiellement envoyée', [ 'order' => $order->getId(), 'success_channels' => $result->getSuccessfulChannels(), 'failed_channels' => $result->getFailedChannels() ]); // Notification interne en cas d'échec partiel $this->notifyTeam('Échec partiel de notification client', [ 'order' => $order->getReference(), 'client' => $client->getFullName(), 'failed_channels' => $result->getFailedChannels() ]); } else { $this->logger->error('Échec d\'envoi de notification', [ 'order' => $order->getId(), 'errors' => $this->formatChannelErrors($result) ]); // Action de repli en cas d'échec total (ex: notification manuelle) $this->createManualFollowupTask($order, 'Échec des notifications automatiques'); } return $result; } /** * Formate les erreurs par canal pour le log */ private function formatChannelErrors(MessageResult $result): array { $errors = []; foreach ($result->getFailedChannels() as $channelId) { $channelResult = $result->getChannelResult($channelId); $errors[$channelId] = [ 'message' => $channelResult->getMessage(), 'exception' => $channelResult->getException() ? $channelResult->getException()->getMessage() : null ]; } return $errors; }
Utilisation de templates
$messenger->createMessage() ->to(['email' => 'client@example.com']) ->usingTemplate('emails/facture.html.twig', [ 'subject' => 'Votre facture #123', 'facture' => $facture, 'client' => $client, 'montant' => 99.99 ]) ->send();
Envoi spécifique par canal
// SMS uniquement $messenger->createMessage("Votre code de confirmation est 123456") ->to(['sms' => '+33612345678']) ->onChannels(['sms']) ->send(); // Email avec pièces jointes $messenger->createMessage() ->to(['email' => 'contact@example.com']) ->onChannels(['email']) ->usingTemplate('emails/document.html.twig', [ 'subject' => 'Documents importants', 'user' => $user ]) ->withAttachments([ '/chemin/vers/document.pdf', ['path' => '/chemin/vers/image.jpg', 'name' => 'Photo.jpg', 'mime' => 'image/jpeg'] ]) ->send();
Envoi groupé
// Préparer plusieurs messages foreach ($users as $user) { $messenger->createMessage() ->to(['email' => $user->getEmail()]) ->usingTemplate('emails/newsletter.html.twig', [ 'subject' => 'Notre newsletter mensuelle', 'user' => $user ]) ->queueMessage(); } // Envoyer tous les messages en une fois $messenger->flush();
Planification des messages
$date = new \DateTime('tomorrow 10:00:00'); $messenger->createMessage("Rappel de rendez-vous") ->to(['sms' => '+33612345678']) ->delayUntil($date) ->send();
Canaux disponibles
$messenger->createMessage() ->to(['email' => 'destinataire@example.com']) ->usingTemplate('emails/notification.html.twig', [ 'subject' => 'Objet du message', 'cc' => ['copie@example.com'], // Optionnel 'bcc' => ['copie.cachee@example.com'], // Optionnel ]) ->send();
Système d'adapters personnalisés
WarpMessengerBundle utilise un système d'adapters extensible qui vous permet de créer facilement vos propres canaux de communication.
Comment fonctionne le système d'adapters
- Le nom de l'adapter dans votre configuration YAML est utilisé pour « matcher » et charger dynamiquement la classe correspondante.
- Lorsque vous spécifiez
adapter: 'mon_adapter_sms'dans la configuration, le bundle recherche un service avec le tagwarp_messenger.channelet le nom correspondant. - Tous les adapters personnalisés sont chargés automatiquement s'ils sont correctement enregistrés comme services Symfony avec le tag approprié.
Exemple d'implementation
# config/packages/warp_messenger.yaml warp_messenger: channels: sms: enabled: true adapter: 'mon_adapter_sms' options: param1: 'valeur1' param2: 'valeur2'
// src/WarpMessenger/Channel/MonAdapterSMS.php namespace App\WarpMessenger\Channel; use Warp\MessengerBundle\Channel\AbstractChannel; class MonAdapterSMS extends AbstractChannel { public function send($to, $message, array $options = []) { // Votre logique d'envoi SMS (API, curl, etc.) // Par exemple : // $apiKey = $options['param1']; // ... } }
# config/services.yaml services: App\WarpMessenger\Channel\MonAdapterSMS: tags: ['warp_messenger.channel'] arguments: $name: 'mon_adapter_sms'
Consultez la documentation CUSTOM_CHANNEL.md pour des exemples plus détaillés d'implémentation de canaux personnalisés.
SMS
$messenger->createMessage("Votre code de vérification est 123456") ->to(['sms' => '+33612345678']) ->send();
Discord
$messenger->createMessage("Alerte : nouvel utilisateur inscrit") ->to(['discord' => 'webhook_id']) // Optionnel si configuré globalement ->usingTemplate('discord/alert.txt.twig', [ 'username' => 'Bot Notification', // Nom d'affichage du bot 'avatar_url' => 'https://example.com/avatar.png', // Avatar du bot 'embeds' => [ // Cartes enrichies Discord [ 'title' => 'Nouvel utilisateur', 'description' => 'Un nouvel utilisateur s\'est inscrit', 'color' => 5814783, // Couleur en décimal 'fields' => [ ['name' => 'Nom', 'value' => 'John Doe', 'inline' => true], ['name' => 'Email', 'value' => 'john@example.com', 'inline' => true] ] ] ] ]) ->send();
Créer un nouveau canal
- Créez une classe qui implémente
ChannelInterfaceou étendAbstractChannel
namespace App\Messenger\Channel; use Warp\MessengerBundle\Messenger\Channel\AbstractChannel; use Warp\MessengerBundle\Messenger\Message\WarpMessage; use Warp\MessengerBundle\Messenger\Result\ChannelResult; class SlackChannel extends AbstractChannel { protected array $supportedFeatures = ['attachments', 'reactions']; public function __construct( private readonly string $webhookUrl, Environment $twig, ?LoggerInterface $logger = null, string $defaultTemplate = 'slack/default.txt.twig' ) { parent::__construct($twig, $logger, $defaultTemplate); } public function getChannelIdentifier(): string { return 'slack'; } public function supportsFeature(string $feature): bool { return in_array($feature, $this->supportedFeatures, true); } public function send(WarpMessage $message): ChannelResult { try { $content = $this->renderContent($message); // Logique d'envoi à Slack // ... return $this->createSuccessResult('Message Slack envoyé avec succès'); } catch (\Exception $e) { return $this->createFailureResult('Erreur d\'envoi Slack: ' . $e->getMessage(), $e); } } }
- Déclarez votre canal comme service avec le tag approprié
# config/services.yaml services: App\Messenger\Channel\SlackChannel: arguments: - '%env(SLACK_WEBHOOK_URL)%' - '@twig' - '@logger' - 'slack/default.txt.twig' tags: - { name: 'warp_messenger.channel', alias: 'slack' }
Événements
Le bundle déclenche deux événements principaux :
warp_messenger.message.pre_send- Avant l'envoi d'un messagewarp_messenger.message.post_send- Après l'envoi d'un message
namespace App\EventListener; use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Warp\MessengerBundle\Event\MessageEvent; #[AsEventListener(event: MessageEvent::PRE_SEND)] class PreSendListener { public function __invoke(MessageEvent $event): void { $message = $event->getMessage(); // Modification du message avant envoi } } #[AsEventListener(event: MessageEvent::POST_SEND)] class PostSendListener { public function __invoke(MessageEvent $event): void { if ($event->isSuccess()) { // Traitement après envoi réussi } else { // Gestion des échecs } } }
Documentation avancée
Pour une documentation plus détaillée sur toutes les fonctionnalités :
- 📝 Guide d'installation détaillé
- 🔌 Création de canaux personnalisés
- 🌐 Notifications Mercure
- 📊 Journalisation des messages
- 📱 Communication multi-canal
- 📋 Exemples d'utilisation avancés
- 🖥️ Commandes CLI
Compatibilité
- PHP 8.0 ou supérieur
- Symfony 5.4, 6.x
Licence
Ce bundle est disponible sous licence MIT. Voir le fichier LICENSE pour plus de détails.
Contribuer
Les contributions sont les bienvenues ! N'hésitez pas à soumettre des pull requests ou à ouvrir des issues pour signaler des bugs ou proposer des améliorations.
WarpMessenger
Modular multi-channel messaging bundle for Symfony 7.3 / PHP 8.3.
📚 Table of Contents
- Features
- Installation
- Example Usage
- Custom Templates
- Custom Channels
- Channel Aliases
- Commands
- License
📬 WarpMessengerBundle
WarpMessenger is a Symfony 7.3 / PHP 8.3 bundle for sending multi-channel messages (email, SMS, Discord, etc.) using Messenger. It supports Twig templates, delayed delivery, SMS concatenation, and is fully extensible.
🚀 Features
- ✅ Fluent and chainable wrapper
- 📦 Multi-channel support: Email, SMS, Discord (extensible)
- 🧩 Twig templates (HTML/TXT) with fallback support
- ⏱️ Delayed sending via
Messenger+RabbitMQ - ✂️ Automatic SMS truncation or concatenation
- 🧪 Includes PestPHP tests
- 🔧 CLI Command:
warp:send
⚙️ Installation
composer require warp/messenger-bundle
🛠️ Configuration
# config/packages/warp_messenger.yaml parameters: warp_messenger.sms.concat: true warp_messenger.sms.truncate: false
📦 Usage Example
$warpMessenger ->to([ 'email' => 'client@example.com', 'sms' => '+33612345678' ]) ->onChannels(['email', 'sms']) ->usingTemplate('shared/order.twig', [ 'name' => 'Jean', 'orderId' => 'ABC123' ]) ->delayUntil(new \DateTime('+10 minutes')) ->send("Your order ABC123 has been shipped.");
📘 See Mercure browser channel 📘 See Message logging
📱 SMS Behavior
| Condition | Result |
|---|---|
| ≤ 160 characters | ✅ 1 SMS |
| > 160 + concat = true | 📦 Multi-SMS |
| > 160 + truncate = true | ✂️ Truncated |
| > 160 + both false | ❌ Exception |
🧪 Run Tests
vendor/bin/pest
🖥️ CLI Command
php bin/console warp:send \ "email=client@example.com,sms=+33612345678" \ "Test message" \ "email,sms" \ "+5 minutes"
📂 Template Structure
templates/
├─ emails/default.html.twig
├─ sms/default.txt.twig
└─ discord/default.txt.twig
🔌 Add a Custom Channel
Create a class that implements ChannelInterface:
class SlackChannel implements ChannelInterface { public function send(WarpMessage $message): void { // Send to Slack } }
🔄 Batch Sending with flush()
$warpMessenger ->queueMessage() ->to([...]) ->send("First message") ->queueMessage() ->to([...]) ->send("Second message") ->flush();
📧 Email with Attachments
$warpMessenger ->to(['email' => 'client@example.com']) ->onChannels(['email']) ->usingTemplate('emails/notification.html.twig', [ 'user' => 'Jean', 'summary' => 'Your order was shipped.' ]) ->withAttachments([ '/path/to/invoice.pdf', '/path/to/manual.pdf' ]) ->send('Your order ABC123 has been shipped.');
📄 Sample Twig Template
<h1>Hello {{ user }}</h1> <p>{{ summary }}</p>
🔌 Automatic Custom Channel Registration
Steps:
- Implement
ChannelInterface - Tag the service in
services.yaml:
services: App\Messenger\Channel\SlackChannel: tags: ['warp_messenger.channel']
- Use the channel by alias:
$warpMessenger ->to(['slack' => 'https://hooks.slack.com/...']) ->onChannels(['slack']) ->send('This is a custom Slack message!');
🏷️ Custom Channel Aliases
warp_messenger: aliases: App\Messenger\Channel\SlackChannel: slack App\Channel\MatrixChannel: matrix
Usage in code:
$warpMessenger ->to(['slack' => 'https://hooks.slack.com/...']) ->onChannels(['slack']) ->send("Hello from Slack via alias!");
To list aliases:
php bin/console warp:aliases:list
Expected output:
Registered WarpMessenger Channel Aliases
+--------+--------------------------------------------+
| Alias | Channel Class |
+--------+--------------------------------------------+
| slack | App\\Messenger\\Channel\\SlackChannel |
| discord| App\\Messenger\\Channel\\DiscordChannel |
+--------+--------------------------------------------+
📄 License
MIT – WarpMessengerBundle