# Notification System Multi-channel notification system with support for email, database, push, SMS, and webhooks. ## Features - **Multi-Channel Delivery**: Email, Database (in-app), Push, SMS, Webhook - **Queue Integration**: Async delivery via framework Queue system - **Event System**: NotificationSent and NotificationFailed events - **Priority Levels**: LOW, NORMAL, HIGH, URGENT - **Read Tracking**: Mark notifications as read, count unread - **Action Buttons**: Optional action URL and label - **Type Safety**: Fully typed with Value Objects and Enums - **Framework Integration**: Uses existing Mail, Queue, EventBus, Database modules ## Basic Usage ### Creating and Sending a Notification ```php use App\Framework\Notification\Notification; use App\Framework\Notification\NotificationDispatcher; use App\Framework\Notification\ValueObjects\NotificationChannel; use App\Framework\Notification\ValueObjects\NotificationPriority; use App\Framework\Notification\ValueObjects\NotificationType; // Create notification $notification = Notification::create( recipientId: 'user-123', type: NotificationType::system(), title: 'System Update', body: 'Your system has been updated to version 2.0', NotificationChannel::DATABASE, NotificationChannel::EMAIL ); // Add optional features $notification = $notification ->withPriority(NotificationPriority::HIGH) ->withAction('/changelog', 'View Changelog') ->withData([ 'version' => '2.0.0', 'features' => ['performance', 'security'] ]); // Send asynchronously (via Queue) $dispatcher->sendLater($notification); // Or send immediately $result = $dispatcher->sendNow($notification); ``` ### Common Notification Types ```php // System notifications NotificationType::system() // Security alerts NotificationType::security() // Marketing messages NotificationType::marketing() // Social interactions NotificationType::social() // Transactional emails NotificationType::transactional() // Custom types NotificationType::fromString('order-status') ``` ### Retrieving Notifications ```php use App\Framework\Notification\Storage\NotificationRepository; // Get user's notifications $notifications = $repository->findByUser('user-123', limit: 20); // Get unread notifications $unread = $repository->findUnreadByUser('user-123'); // Count unread $count = $repository->countUnreadByUser('user-123'); // Mark as read $repository->markAsRead($notificationId); // Mark all as read $repository->markAllAsReadForUser('user-123'); ``` ## Channels ### Database Channel (In-App Notifications) Stores notifications in database for user inbox/notification center. ```php NotificationChannel::DATABASE ``` **Features**: - Persistent storage - Read/unread tracking - Pagination support - Automatic cleanup of old notifications ### Email Channel Sends notifications via email using framework's Mail module. ```php NotificationChannel::EMAIL ``` **Features**: - HTML and plain text emails - Priority mapping - Action buttons in email - Automatic HTML formatting **Requirements**: - UserEmailResolver implementation to map user IDs to email addresses ```php class DatabaseUserEmailResolver implements UserEmailResolver { public function resolveEmail(string $userId): ?Email { // Lookup user email from database return $this->userRepository->findEmailById($userId); } } ``` ### Push Channel (Placeholder) For web push and mobile push notifications. ```php NotificationChannel::PUSH ``` **Status**: Interface defined, implementation needed. ### SMS Channel (Placeholder) For SMS notifications via external provider. ```php NotificationChannel::SMS ``` **Status**: Interface defined, implementation needed. ### Webhook Channel (Placeholder) For sending notifications to external systems via HTTP webhooks. ```php NotificationChannel::WEBHOOK ``` **Status**: Interface defined, implementation needed. ## Queue Integration The notification system integrates seamlessly with the framework's Queue system for asynchronous delivery. ### Async Delivery ```php // Queue for background processing $dispatcher->sendLater($notification); // Priority is mapped from notification priority: // URGENT → HIGH // HIGH → MEDIUM // NORMAL → LOW // LOW → LOW ``` ### Immediate Delivery ```php // Send immediately (blocks until complete) $result = $dispatcher->sendNow($notification); if ($result->isSuccess()) { echo "Sent via: " . count($result->getSuccessful()) . " channels\n"; } else { echo "Errors: " . implode(', ', $result->getErrors()) . "\n"; } ``` ## Event System The notification system dispatches events via the framework's EventBus. ### NotificationSent Event Dispatched when a notification is successfully sent via at least one channel. ```php use App\Framework\Notification\Events\NotificationSent; use App\Framework\EventBus\Attributes\EventHandler; #[EventHandler] final class NotificationLogger { public function handleNotificationSent(NotificationSent $event): void { $this->logger->info('Notification sent', [ 'notification_id' => $event->notification->id->toString(), 'recipient' => $event->notification->recipientId, 'channels' => count($event->result->getSuccessful()) ]); } } ``` ### NotificationFailed Event Dispatched when a notification fails on all channels. ```php use App\Framework\Notification\Events\NotificationFailed; use App\Framework\EventBus\Attributes\EventHandler; #[EventHandler] final class NotificationFailureHandler { public function handleNotificationFailure(NotificationFailed $event): void { $this->alerting->sendAlert( 'Notification delivery failed', $event->result->getErrors() ); } } ``` ## Database Schema The notifications table is created via migration: ```php src/Framework/Notification/Migrations/CreateNotificationsTable.php ``` **Table Structure**: - `id` (ULID) - Primary key - `recipient_id` - User/entity receiving notification - `type` - Notification category - `title` - Notification title - `body` - Notification message - `data` - JSON structured data - `channels` - JSON array of delivery channels - `priority` - Delivery priority - `status` - Current status (pending, sent, delivered, failed, read, archived) - `created_at` - Creation timestamp - `sent_at` - Delivery timestamp - `read_at` - Read timestamp - `action_url` - Optional action URL - `action_label` - Optional action button label **Indexes**: - `recipient_id` + `status` + `created_at` (composite) - `recipient_id` + `type` (composite) - `read_at` (for unread queries) ## Configuration ### Setting Up Channels ```php // In your Initializer use App\Framework\Notification\Channels\DatabaseChannel; use App\Framework\Notification\Channels\EmailChannel; use App\Framework\Notification\NotificationDispatcher; $container->singleton(NotificationDispatcher::class, function($c) { return new NotificationDispatcher( channels: [ $c->get(DatabaseChannel::class), $c->get(EmailChannel::class), // Add more channels as needed ], queue: $c->get(Queue::class), eventBus: $c->get(EventBus::class) ); }); ``` ### Email Channel Setup ```php $container->singleton(EmailChannel::class, function($c) { return new EmailChannel( mailer: $c->get(MailerInterface::class), fromAddress: new Email('notifications@example.com'), userEmailResolver: $c->get(UserEmailResolver::class) ); }); ``` ## Best Practices 1. **Use Async Delivery**: Always prefer `sendLater()` for better performance 2. **Set Appropriate Priority**: Reserve URGENT for critical notifications 3. **Include Actions**: Add action URLs when user interaction is expected 4. **Structured Data**: Use `withData()` for additional context 5. **Type Classification**: Use proper NotificationType for filtering 6. **Cleanup Old Notifications**: Periodically delete old read/archived notifications ## Examples ### Welcome Notification ```php $notification = Notification::create( recipientId: $user->id, type: NotificationType::system(), title: 'Welcome to Our Platform!', body: 'Thank you for signing up. Get started by completing your profile.', NotificationChannel::DATABASE, NotificationChannel::EMAIL )->withAction('/profile/complete', 'Complete Profile'); $dispatcher->sendLater($notification); ``` ### Security Alert ```php $notification = Notification::create( recipientId: $user->id, type: NotificationType::security(), title: 'New Login Detected', body: "We detected a login from {$location} at {$time}", NotificationChannel::DATABASE, NotificationChannel::EMAIL ) ->withPriority(NotificationPriority::HIGH) ->withData([ 'ip_address' => $ipAddress, 'location' => $location, 'device' => $device ]); $dispatcher->sendNow($notification); // Immediate for security ``` ### Order Confirmation ```php $notification = Notification::create( recipientId: $order->userId, type: NotificationType::transactional(), title: 'Order Confirmed', body: "Your order #{$order->number} has been confirmed", NotificationChannel::EMAIL ) ->withData([ 'order_id' => $order->id, 'total' => $order->total->toDecimal(), 'items' => count($order->items) ]) ->withAction("/orders/{$order->id}", 'View Order'); $dispatcher->sendLater($notification); ``` ## Testing Run tests with: ```bash ./vendor/bin/pest tests/Feature/NotificationSystemTest.php ``` ## Extending the System ### Adding a New Channel 1. Implement `NotificationChannelInterface` 2. Add channel to `NotificationChannel` enum 3. Register channel in dispatcher initialization 4. Implement `send()` method with delivery logic ```php final readonly class SmsChannel implements NotificationChannelInterface { public function __construct( private SmsProvider $provider ) {} public function send(Notification $notification): ChannelResult { // Implementation } public function supports(Notification $notification): bool { return $notification->supportsChannel(NotificationChannel::SMS); } public function getChannel(): NotificationChannel { return NotificationChannel::SMS; } } ``` ## Architecture The notification system follows framework principles: - ✅ **Readonly Value Objects**: Notification, NotificationId, etc. - ✅ **Final Classes**: All implementation classes are final - ✅ **Composition over Inheritance**: Channel interface composition - ✅ **Event-Driven**: Integration with EventBus - ✅ **Queue Integration**: Async delivery via Queue system - ✅ **Module Reuse**: Leverages Mail, Queue, EventBus, Database modules ## Future Enhancements - [ ] User preference management for notification types - [ ] Notification templates with variables - [ ] Push notification implementation (Web Push API) - [ ] SMS channel implementation - [ ] Webhook channel implementation - [ ] Notification batching/digest mode - [ ] Quiet hours / Do Not Disturb - [ ] A/B testing for notification content - [ ] Analytics tracking