From 89296c0aad8e9a56b5e2da3c73eb8d3a20a86a69 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:35:58 +0100 Subject: [PATCH 1/8] Draft ibexa/notifications doc --- .../notifications/config/packages/ibexa.yaml | 18 +++++ .../src/Command/NotificationSenderCommand.php | 67 +++++++++++++++++++ .../src/Notifications/CommandExecuted.php | 55 +++++++++++++++ docs/users/notifications.md | 60 +++++++++++++++++ mkdocs.yml | 1 + 5 files changed, 201 insertions(+) create mode 100644 code_samples/user_management/notifications/config/packages/ibexa.yaml create mode 100644 code_samples/user_management/notifications/src/Command/NotificationSenderCommand.php create mode 100644 code_samples/user_management/notifications/src/Notifications/CommandExecuted.php create mode 100644 docs/users/notifications.md diff --git a/code_samples/user_management/notifications/config/packages/ibexa.yaml b/code_samples/user_management/notifications/config/packages/ibexa.yaml new file mode 100644 index 0000000000..5a385e7e5f --- /dev/null +++ b/code_samples/user_management/notifications/config/packages/ibexa.yaml @@ -0,0 +1,18 @@ +ibexa: + system: + default: + notifier: + subscriptions: + Ibexa\Contracts\User\Notification\UserPasswordReset: + channels: + - email + Ibexa\Contracts\User\Notification\UserInvitation: + channels: + - email + Ibexa\Contracts\FormBuilder\Notifications\FormSubmitted: + channels: + - email + App\Notifications\CommandExecuted: + channels: + - ibexa + - email diff --git a/code_samples/user_management/notifications/src/Command/NotificationSenderCommand.php b/code_samples/user_management/notifications/src/Command/NotificationSenderCommand.php new file mode 100644 index 0000000000..4d30f95423 --- /dev/null +++ b/code_samples/user_management/notifications/src/Command/NotificationSenderCommand.php @@ -0,0 +1,67 @@ + $recipientLogins */ + public function __construct( + private readonly NotificationServiceInterface $notificationService, + private readonly UserService $userService, + private readonly array $recipientLogins = ['admin'], + ) { + parent::__construct(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + /** @var array $exceptions */ + $exceptions = []; + + try { + // Do something + if (rand(0, 1) == 1) { + throw new \RuntimeException('Something went wrong'); + } + $exitCode = Command::SUCCESS; + } catch (\Exception $exception) { + $exceptions[] = $exception; + $exitCode = Command::FAILURE; + } + + $recipients = []; + foreach ($this->recipientLogins as $login) { + try { + $user = $this->userService->loadUserByLogin($login); + $recipients[] = new UserRecipient($user); + } catch (\Exception $exception) { + $exceptions[] = $exception; + } + } + + $this->notificationService->send( + new SymfonyNotificationAdapter(new CommandExecuted($this, $exitCode, $exceptions)), + array_map( + static fn (RecipientInterface $recipient): SymfonyRecipientAdapter => new SymfonyRecipientAdapter($recipient), + $recipients + ) + ); + + return $exitCode; + } +} diff --git a/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php b/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php new file mode 100644 index 0000000000..47f2a5b3f8 --- /dev/null +++ b/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php @@ -0,0 +1,55 @@ + $exceptions */ + public function __construct( + private readonly Command $command, + private readonly int $exitCode, + private readonly array $exceptions + ) { + parent::__construct($this->command->getName()); + } + + public function asEmailMessage(EmailRecipientInterface $recipient, ?string $transport = null): ?EmailMessage + { + $subject = (0 === $this->exitCode ? '✔' : '✖') . $this->command->getName(); + + $body = ''; + foreach ($this->exceptions as $exception) { + $body .= $exception->getMessage() . '
'; + } + + $email = NotificationEmail::asPublicEmail() + ->to($recipient->getEmail()) + ->subject($subject) + ->html($body); + + return new EmailMessage($email); + } + + public function asSystemNotification(UserRecipientInterface $recipient, ?string $transport = null): ?SystemMessage + { + $message = new SystemMessage($recipient->getUser()); + $message->setContext([ + 'icon' => 0 === $this->exitCode ? 'check-circle' : 'discard-circle', + 'subject' => $this->command->getName(), + 'content' => 0 === $this->exitCode ? 'No error' : count($this->exceptions) . ' error' . (count($this->exceptions) > 1 ? 's' : ''), + ]); + + return $message; + } +} diff --git a/docs/users/notifications.md b/docs/users/notifications.md new file mode 100644 index 0000000000..df648661aa --- /dev/null +++ b/docs/users/notifications.md @@ -0,0 +1,60 @@ +--- +description: Notify users TODO. +month_change: true +--- + +# Notifications + +TODO: [notification bar](/administration/back_office/notifications.md) VS [🔔 user notification](/administration/back_office/notifications.md#create-custom-notifications) VS this + +TODO: +[Ibexa\Contracts\Core\Repository\NotificationService](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-NotificationService.html) +versus +[Ibexa\Contracts\Notifications\Service\NotificationServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-Service-NotificationServiceInterface.html) + +Based on [Symfony notifier]([[= symfony_doc =]]/notifier.html) + +Use an existing notification class + +TODO: List available classes + +Create a notification class + +TODO: List what type of channel notification interfaces can be implemented +TODO: Namespaces, Ibexa custom vs Symfony native + +| Channel | Notification interface | Description | +|:--------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:------------| +| `ibexa` | [`SystemNotificationInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-SystemNotification-SystemNotificationInterface.html) | TODO | +| `email` | `EmailNotificationInterface` | TODO | +| `chat` | `ChatNotificationInterface` | TODO | +| `sms` | `SmsNotificationInterface` | TODO | + +TODO: About `ibexa` channel being the [🔔 user notification](/administration/back_office/notifications.md#create-custom-notifications) +https://github.com/ibexa/notifications/blob/v5.0.6/src/lib/SystemNotification/SystemNotificationChannel.php#L51 + +TODO: About `SymfonyNotificationAdapter` and `SymfonyRecipientAdapter` + +### Example + +The following example is a command that sends a notification to users on several channels simultaneously. +it could be a scheduled task, a cronjob, warning users about its final result. + +First, a `CommandExecuted` notification type is created. +It is supported by two channels for the example but could be extended to more. + +``` php +[[= include_file('code_samples/user_management/notifications/src/Notifications/CommandExecuted.php') =]] +``` + +The channels subscribing to this notification are set in `config/packages/ibexa.yaml` below the default ones: + +``` yaml +[[= include_file('code_samples/user_management/notifications/config/packages/ibexa.yaml') =]] +``` + +TODO: Explain the command + +``` php +[[= include_file('code_samples/user_management/notifications/src/Command/NotificationSenderCommand.php') =]] +``` diff --git a/mkdocs.yml b/mkdocs.yml index c7cb98d738..6262ffb473 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -479,6 +479,7 @@ nav: - User grouping: - Customer groups: users/customer_groups.md - Segment API: users/segment_api.md + - User notifications: users/notifications.md - Personalization: - Personalization: personalization/personalization.md - Personalization guide : personalization/personalization_guide.md From 0e7ca027af40d479677ba6c7d1a6c89f191a5b48 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:37:14 +0100 Subject: [PATCH 2/8] install_with_ddev.md: Mailer --- docs/getting_started/install_with_ddev.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/getting_started/install_with_ddev.md b/docs/getting_started/install_with_ddev.md index bc28a942c8..22b5122471 100644 --- a/docs/getting_started/install_with_ddev.md +++ b/docs/getting_started/install_with_ddev.md @@ -88,6 +88,14 @@ Depending on your database of choice (MySQL or PostgreSQL), use the appropriate ddev config --web-environment-add DATABASE_URL=postgresql://db:db@db:5432/db ``` +#### Configure mailer (optional) + +You can configure [Symfony Mailer]([[= symfony_doc =]]/mailer.html) to use the [integrated mail catcher Mailpit](https://docs.ddev.com/en/stable/users/usage/developer-tools/#email-capture-and-review-mailpit): + +```bash +ddev config --web-environment-add MAILER_DSN=smtp://localhost:1025 +``` + #### Enable Mutagen (optional) If you're using macOS or Windows, you might want to enable [Mutagen](https://ddev.readthedocs.io/en/latest/users/install/performance/#mutagen) to improve performance. From a137ac02d904e50162e291b856471d91545622cd Mon Sep 17 00:00:00 2001 From: adriendupuis Date: Tue, 17 Mar 2026 08:55:08 +0000 Subject: [PATCH 3/8] PHP & JS CS Fixes --- .../notifications/src/Notifications/CommandExecuted.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php b/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php index 47f2a5b3f8..819879c97e 100644 --- a/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php +++ b/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php @@ -1,4 +1,4 @@ - Date: Tue, 17 Mar 2026 12:37:08 +0100 Subject: [PATCH 4/8] BO notifications.md: Minor fixes --- docs/administration/back_office/notifications.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/administration/back_office/notifications.md b/docs/administration/back_office/notifications.md index 29c2d69f54..60e57f09bd 100644 --- a/docs/administration/back_office/notifications.md +++ b/docs/administration/back_office/notifications.md @@ -5,17 +5,17 @@ month_change: false # Notifications -You can send two types on notifications to the users. +You can send two types of notifications to the users. [Notification bar](#notification-bars) is displayed in specific situations as a message bar appearing at the bottom of the page. It appears to whoever is doing a specific operation in the back office. -![Example of an info notification](notification2.png "Example of the notification bar") +![Example of an info notification](notification2.png "Example of notification bar") [Custom notifications](#create-custom-notifications) are sent to a specific user. They appear in their profile in the back office. -![Notification in profile](notification3.png) +![Notification in profile](notification3.png "Profile notification bell menu") ## Notification bars @@ -56,7 +56,7 @@ Dispatch the event with `document.body.dispatchEvent(eventInfo);`. You can send your own custom notifications to the user which are displayed in the user menu. -To create a new notification you must use the `createNotification(Ibexa\Contracts\Core\Repository\Values\Notification\CreateStruct $createStruct)` method from `Ibexa\Contracts\Core\Repository\NotificationService`. +To create a new notification you can use the [core `NotificationService::createNotification(CreateStruct $createStruct)` method](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-NotificationService.html#method_createNotification) like in the example below. Example: @@ -117,3 +117,9 @@ ibexa: The values shown above are the defaults. `0` means the notification doesn't hide automatically. + +### `ibexa` notification channel + +You can also subscribe to a notification with the channel `ibexa` + +See [Notifications to users](users/notifications.md) for more details about notifications and channel subscription. From 43b3df8536aca850b083f1cc17be3473f51c2257 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 17 Mar 2026 12:39:13 +0100 Subject: [PATCH 5/8] Users notifications.md: Continue --- .../config/packages/custom_notifications.yaml | 22 ++++++++++ .../notifications/config/packages/ibexa.yaml | 18 -------- docs/users/notifications.md | 44 ++++++++++++++----- 3 files changed, 56 insertions(+), 28 deletions(-) create mode 100644 code_samples/user_management/notifications/config/packages/custom_notifications.yaml delete mode 100644 code_samples/user_management/notifications/config/packages/ibexa.yaml diff --git a/code_samples/user_management/notifications/config/packages/custom_notifications.yaml b/code_samples/user_management/notifications/config/packages/custom_notifications.yaml new file mode 100644 index 0000000000..5674488f6d --- /dev/null +++ b/code_samples/user_management/notifications/config/packages/custom_notifications.yaml @@ -0,0 +1,22 @@ +framework: + notifier: + chatter_transports: + slack: '%env(SLACK_DSN)%' +ibexa: + system: + default: + notifier: + subscriptions: + Ibexa\OrderManagement\Notification\OrderStatusChange: + channels: + - chat + Ibexa\Payment\Notification\PaymentStatusChange: + channels: + - chat + Ibexa\Shipping\Notification\ShipmentStatusChange: + channels: + - chat + App\Notifications\CommandExecuted: + channels: + - ibexa + - email diff --git a/code_samples/user_management/notifications/config/packages/ibexa.yaml b/code_samples/user_management/notifications/config/packages/ibexa.yaml deleted file mode 100644 index 5a385e7e5f..0000000000 --- a/code_samples/user_management/notifications/config/packages/ibexa.yaml +++ /dev/null @@ -1,18 +0,0 @@ -ibexa: - system: - default: - notifier: - subscriptions: - Ibexa\Contracts\User\Notification\UserPasswordReset: - channels: - - email - Ibexa\Contracts\User\Notification\UserInvitation: - channels: - - email - Ibexa\Contracts\FormBuilder\Notifications\FormSubmitted: - channels: - - email - App\Notifications\CommandExecuted: - channels: - - ibexa - - email diff --git a/docs/users/notifications.md b/docs/users/notifications.md index df648661aa..41d7bb3e0f 100644 --- a/docs/users/notifications.md +++ b/docs/users/notifications.md @@ -5,18 +5,39 @@ month_change: true # Notifications -TODO: [notification bar](/administration/back_office/notifications.md) VS [🔔 user notification](/administration/back_office/notifications.md#create-custom-notifications) VS this +the `ibexa/notifications` package offers an extension to the [Symfony notifier]([[= symfony_doc =]]/notifier.html) allowing to subscribe to notifications and sent them to information channels like email addresses, SMS, communication platforms, etc., including the [🔔 Back Office user profile notification](/administration/back_office/notifications.md#create-custom-notifications). -TODO: -[Ibexa\Contracts\Core\Repository\NotificationService](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-NotificationService.html) -versus -[Ibexa\Contracts\Notifications\Service\NotificationServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-Service-NotificationServiceInterface.html) +Those notifications must not be confused with the [notification bars](/administration/back_office/notifications.md) (sent with [`TranslatableNotificationHandlerInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-AdminUi-Notification-TranslatableNotificationHandlerInterface.html)) +or the [🔔 user notifications](/administration/back_office/notifications.md#create-custom-notifications) (sent with [`Ibexa\Contracts\Core\Repository\NotificationService`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-NotificationService.html)). -Based on [Symfony notifier]([[= symfony_doc =]]/notifier.html) +TODO: Introduce the [`Ibexa\Contracts\Notifications\Service\NotificationServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-Service-NotificationServiceInterface.html) -Use an existing notification class +## Subscribe to notifications -TODO: List available classes +Some events send notifications you can subscribe to with one or more channels. + +Available notifications: + +* [`Ibexa\Contracts\FormBuilder\Notifications\FormSubmitted`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-FormBuilder-Notifications-FormSubmitted.html) +* [`Ibexa\Contracts\Notifications\SystemNotification\SystemNotification`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-SystemNotification-SystemNotification.html) +* [`Ibexa\Contracts\OrderManagement\Notification\OrderStatusChange`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-OrderManagement-Notification-OrderStatusChange.html) +* [`Ibexa\Contracts\Payment\Notification\PaymentStatusChange`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Payment-Notification-PaymentStatusChange.html) +* [`Ibexa\Contracts\Shipping\Notification\ShipmentStatusChange`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Shipping-Notification-ShipmentStatusChange.html) +* [`Ibexa\Contracts\User\Notification\UserInvitation`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-User-Notification-UserInvitation.html) +* [`Ibexa\Contracts\User\Notification\UserPasswordReset`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-User-Notification-UserPasswordReset.html) +* [`Ibexa\Contracts\User\Notification\UserRegister`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-User-Notification-UserRegister.html) + +TODO: What about notifications outside the `Ibexa\Contracts` namespace?? + +* `Ibexa\Share\Notification\ContentEditInvitationNotification` +* `Ibexa\Share\Notification\ContentViewInvitationNotification` +* `Ibexa\Share\Notification\ExternalParticipantContentViewInvitationNotification` + +For example, let's subscribe to Commerce activity with a Slack channel: + +``` yaml +[[= include_file('code_samples/user_management/notifications/config/packages/custom_notifications.yaml', 0, 18) =]] +``` Create a notification class @@ -33,6 +54,8 @@ TODO: Namespaces, Ibexa custom vs Symfony native TODO: About `ibexa` channel being the [🔔 user notification](/administration/back_office/notifications.md#create-custom-notifications) https://github.com/ibexa/notifications/blob/v5.0.6/src/lib/SystemNotification/SystemNotificationChannel.php#L51 +TODO: How to deal with channels not needing a user like `chat` + Slack channel? + TODO: About `SymfonyNotificationAdapter` and `SymfonyRecipientAdapter` ### Example @@ -47,10 +70,11 @@ It is supported by two channels for the example but could be extended to more. [[= include_file('code_samples/user_management/notifications/src/Notifications/CommandExecuted.php') =]] ``` -The channels subscribing to this notification are set in `config/packages/ibexa.yaml` below the default ones: +The channels subscribing to this notification are set in `config/packages/ibexa.yaml`: ``` yaml -[[= include_file('code_samples/user_management/notifications/config/packages/ibexa.yaml') =]] +[[= include_file('code_samples/user_management/notifications/config/packages/custom_notifications.yaml', 5, 9) =]] # … +[[= include_file('code_samples/user_management/notifications/config/packages/custom_notifications.yaml', 18) =]] ``` TODO: Explain the command From 96f91460842aaddd8291035126154cd51dcb06dd Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:35:42 +0100 Subject: [PATCH 6/8] CommandExecuted enhancement --- .../src/Notifications/CommandExecuted.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php b/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php index 819879c97e..489cce61bb 100644 --- a/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php +++ b/code_samples/user_management/notifications/src/Notifications/CommandExecuted.php @@ -21,13 +21,12 @@ public function __construct( private readonly int $exitCode, private readonly array $exceptions ) { - parent::__construct($this->command->getName()); + parent::__construct((Command::SUCCESS === $this->exitCode ? '✔' : '✖') . $this->command->getName()); + $this->importance(Command::SUCCESS === $this->exitCode ? Notification::IMPORTANCE_LOW : Notification::IMPORTANCE_HIGH); } public function asEmailMessage(EmailRecipientInterface $recipient, ?string $transport = null): ?EmailMessage { - $subject = (0 === $this->exitCode ? '✔' : '✖') . $this->command->getName(); - $body = ''; foreach ($this->exceptions as $exception) { $body .= $exception->getMessage() . '
'; @@ -35,7 +34,7 @@ public function asEmailMessage(EmailRecipientInterface $recipient, ?string $tran $email = NotificationEmail::asPublicEmail() ->to($recipient->getEmail()) - ->subject($subject) + ->subject($this->getSubject()) ->html($body); return new EmailMessage($email); @@ -45,9 +44,9 @@ public function asSystemNotification(UserRecipientInterface $recipient, ?string { $message = new SystemMessage($recipient->getUser()); $message->setContext([ - 'icon' => 0 === $this->exitCode ? 'check-circle' : 'discard-circle', + 'icon' => Command::SUCCESS === $this->exitCode ? 'check-circle' : 'discard-circle', 'subject' => $this->command->getName(), - 'content' => 0 === $this->exitCode ? 'No error' : count($this->exceptions) . ' error' . (count($this->exceptions) > 1 ? 's' : ''), + 'content' => Command::SUCCESS === $this->exitCode ? 'No error' : count($this->exceptions) . ' error' . (count($this->exceptions) > 1 ? 's' : ''), ]); return $message; From ffe904df8902bf2c69657316d13fab5caf93f8ff Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:42:55 +0100 Subject: [PATCH 7/8] Continue users/notifications.md; Add channel examples --- .../notifications/config/services.yaml | 4 ++ .../src/Notifier/Channel/LogChannel.php | 28 +++++++++ docs/users/notifications.md | 61 ++++++++++++++++--- 3 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 code_samples/user_management/notifications/config/services.yaml create mode 100644 code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php diff --git a/code_samples/user_management/notifications/config/services.yaml b/code_samples/user_management/notifications/config/services.yaml new file mode 100644 index 0000000000..51d97cdfbe --- /dev/null +++ b/code_samples/user_management/notifications/config/services.yaml @@ -0,0 +1,4 @@ +services: + App\Notifier\Channel\LogChannel: + tags: + - { name: 'notifier.channel', channel: 'log' } diff --git a/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php b/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php new file mode 100644 index 0000000000..8611a69a3d --- /dev/null +++ b/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php @@ -0,0 +1,28 @@ +logger->info($notification->getSubject(), [ + 'class' => get_class($notification), + 'importance' => $notification->getImportance(), + 'content' => $notification->getContent(), + ]); + } + + public function supports(Notification $notification, RecipientInterface $recipient): bool + { + return true; + } +} diff --git a/docs/users/notifications.md b/docs/users/notifications.md index 41d7bb3e0f..fb2e10864a 100644 --- a/docs/users/notifications.md +++ b/docs/users/notifications.md @@ -33,23 +33,54 @@ TODO: What about notifications outside the `Ibexa\Contracts` namespace?? * `Ibexa\Share\Notification\ContentViewInvitationNotification` * `Ibexa\Share\Notification\ExternalParticipantContentViewInvitationNotification` +Available notification channels: + +```bash +php bin/console debug:container --tag=notifier.channel +``` + For example, let's subscribe to Commerce activity with a Slack channel: +```bash +composer require symfony/slack-notifier +``` + +* `browser` - Notification as flash message TODO: Test from a controller to see if it works +* `chat` - Notification sent to a communication platform like Slack, Microsoft Teams, Google Chat, etc. +* `desktop` - Notification sent to JoliNotif TODO: Do we support this? +* `email` - Notification sent to email addresses +* `ibexa` - Notification sent to back office user profiles +* `push` - TODO +* `sms` - Notification sent to phone numbers + +In a .env file, [set the DSN for the targetted Slack channel or user](https://github.com/symfony/slack-notifier?tab=readme-ov-file#dsn-example): + +```dotenv +SLACK_DSN=slack://xoxb-token@default?channel=ibexa-notifications +``` + ``` yaml [[= include_file('code_samples/user_management/notifications/config/packages/custom_notifications.yaml', 0, 18) =]] ``` -Create a notification class +## Create a notification class + +A new notification class can be created to send a new type of message to a new set of channels. +It must extend `Symfony\Component\Notifier\Notification\Notification` +and optionally implements some interfaces depending on the channels it could be sent to. + +- Some channels don't accept the notification if it doesn't implement its related notification interface. +- Some channels accept every notification and have a default behavior if the notification doesn't implement their related notification interface. TODO: List what type of channel notification interfaces can be implemented TODO: Namespaces, Ibexa custom vs Symfony native -| Channel | Notification interface | Description | -|:--------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:------------| -| `ibexa` | [`SystemNotificationInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-SystemNotification-SystemNotificationInterface.html) | TODO | -| `email` | `EmailNotificationInterface` | TODO | -| `chat` | `ChatNotificationInterface` | TODO | -| `sms` | `SmsNotificationInterface` | TODO | +| Channel | Notification interface | ! | Description | +|:--------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|---|:------------| +| `chat` | `ChatNotificationInterface` | | TODO | +| `email` | `EmailNotificationInterface` | ✔ | TODO | +| `ibexa` | [`SystemNotificationInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Notifications-SystemNotification-SystemNotificationInterface.html) | ✔ | TODO | +| `sms` | `SmsNotificationInterface` | ✔ | TODO | TODO: About `ibexa` channel being the [🔔 user notification](/administration/back_office/notifications.md#create-custom-notifications) https://github.com/ibexa/notifications/blob/v5.0.6/src/lib/SystemNotification/SystemNotificationChannel.php#L51 @@ -82,3 +113,19 @@ TODO: Explain the command ``` php [[= include_file('code_samples/user_management/notifications/src/Command/NotificationSenderCommand.php') =]] ``` + +TODO: Screenshots + +## Create a channel + +A channel is a service implementing `Symfony\Component\Notifier\Channel\ChannelInterface`, and tagged `notifier.channel` alongside a `channel` shortname. + +The following example is a custom channel that sends notifications to the logger. + +``` php +[[= include_file('code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php') =]] +``` + +``` yaml +[[= include_file('code_samples/user_management/notifications/config/services.yaml') =]] +``` From 0d9abdcc33723ab68c5dd5a701d9f87c945105a4 Mon Sep 17 00:00:00 2001 From: adriendupuis Date: Tue, 17 Mar 2026 14:53:04 +0000 Subject: [PATCH 8/8] PHP & JS CS Fixes --- .../notifications/src/Notifier/Channel/LogChannel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php b/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php index 8611a69a3d..3bf3bda913 100644 --- a/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php +++ b/code_samples/user_management/notifications/src/Notifier/Channel/LogChannel.php @@ -1,4 +1,4 @@ -