*/ function api_notification_channels() : array { api_notification_assert_dependencies(); $channels = ['email' => new CactiEmailChannel()]; if (function_exists('api_plugin_hook_function')) { $channels = api_plugin_hook_function('notification_channels', $channels); } return api_notification_validate_channels($channels); } /** * @return array */ function api_notification_validate_channels(mixed $channels) : array { api_notification_assert_dependencies(); if (!is_array($channels)) { throw new InvalidArgumentException('The notification_channels hook must return an array.'); } foreach ($channels as $name => $channel) { if (!is_string($name) || $name === '' || !$channel instanceof ChannelInterface) { throw new InvalidArgumentException('Notification channels must be named Symfony ChannelInterface instances.'); } } return $channels; } /** * Normalizes Cacti email values and Symfony recipients for notification use. * * @return list */ function api_notification_recipients(array|string|RecipientInterface $recipients) : array { api_notification_assert_dependencies(); if ($recipients instanceof RecipientInterface) { return [$recipients]; } if (is_array($recipients) && array_filter($recipients, fn (mixed $recipient) : bool => $recipient instanceof RecipientInterface) !== []) { foreach ($recipients as $recipient) { if (!$recipient instanceof RecipientInterface) { throw new InvalidArgumentException('Symfony recipients cannot be mixed with email address values.'); } } return array_values($recipients); } $normalized = []; $emails = parse_email_details($recipients); foreach ($emails as $email) { if (($email['email'] ?? '') !== '') { $normalized[] = new CactiRecipient(trim($email['email']), '', trim($email['name'] ?? '')); } } return $normalized; } /** * Sends a notification through Symfony Notifier and Cacti delivery channels. * * The options array accepts `importance` plus channel-specific arrays. Email * options are: from, cc, bcc, reply_to, html, text, attachments, headers and * expand_ids. * * @param list $channels * @param array $options */ function api_notification_send(string $subject, string $content, array|string|RecipientInterface $recipients, array $channels = ['email'], array $options = [], ?NotifierInterface $notifier = null) : bool { try { api_notification_assert_dependencies(); $normalized = api_notification_recipients($recipients); if ($normalized === []) { throw new InvalidArgumentException('At least one notification recipient is required.'); } $notification = new CactiNotification($subject, $content, $channels, $options); $notifier ??= new Notifier(api_notification_channels()); $notifier->send($notification, ...$normalized); return true; } catch (Throwable $e) { $logSubject = str_replace(["\r", "\n"], ' ', $subject); $logError = str_replace(["\r", "\n"], ' ', $e->getMessage()); cacti_log(sprintf("ERROR: Notification '%s' failed: %s", $logSubject, $logError), false, 'NOTIFIER'); return false; } }