vendor/symfony/notifier/Notifier.php line 36

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Notifier;
  11. use Psr\Container\ContainerInterface;
  12. use Symfony\Component\Notifier\Channel\ChannelInterface;
  13. use Symfony\Component\Notifier\Channel\ChannelPolicy;
  14. use Symfony\Component\Notifier\Channel\ChannelPolicyInterface;
  15. use Symfony\Component\Notifier\Channel\SmsChannel;
  16. use Symfony\Component\Notifier\Exception\LogicException;
  17. use Symfony\Component\Notifier\Notification\Notification;
  18. use Symfony\Component\Notifier\Recipient\NoRecipient;
  19. use Symfony\Component\Notifier\Recipient\RecipientInterface;
  20. /**
  21.  * @author Fabien Potencier <fabien@symfony.com>
  22.  */
  23. final class Notifier implements NotifierInterface
  24. {
  25.     private array $adminRecipients = [];
  26.     private array|ContainerInterface $channels;
  27.     private ?ChannelPolicyInterface $policy;
  28.     /**
  29.      * @param ChannelInterface[]|ContainerInterface $channels
  30.      */
  31.     public function __construct(array|ContainerInterface $channels, ChannelPolicyInterface $policy = null)
  32.     {
  33.         $this->channels = $channels;
  34.         $this->policy = $policy;
  35.     }
  36.     public function send(Notification $notification, RecipientInterface ...$recipients): void
  37.     {
  38.         if (!$recipients) {
  39.             $recipients = [new NoRecipient()];
  40.         }
  41.         foreach ($recipients as $recipient) {
  42.             foreach ($this->getChannels($notification, $recipient) as $channel => $transportName) {
  43.                 $channel->notify($notification, $recipient, $transportName);
  44.             }
  45.         }
  46.     }
  47.     public function addAdminRecipient(RecipientInterface $recipient): void
  48.     {
  49.         $this->adminRecipients[] = $recipient;
  50.     }
  51.     /**
  52.      * @return RecipientInterface[]
  53.      */
  54.     public function getAdminRecipients(): array
  55.     {
  56.         return $this->adminRecipients;
  57.     }
  58.     /**
  59.      * @return iterable<ChannelInterface, string|null>
  60.      */
  61.     private function getChannels(Notification $notification, RecipientInterface $recipient): iterable
  62.     {
  63.         $channels = $notification->getChannels($recipient);
  64.         if (!$channels) {
  65.             $errorPrefix = sprintf('Unable to determine which channels to use to send the "%s" notification', $notification::class);
  66.             $error = 'you should either pass channels in the constructor, override its "getChannels()" method';
  67.             if (null === $this->policy) {
  68.                 throw new LogicException(sprintf('%s; %s, or configure a "%s".', $errorPrefix, $error, ChannelPolicy::class));
  69.             }
  70.             if (!$channels = $this->policy->getChannels($notification->getImportance())) {
  71.                 throw new LogicException(sprintf('%s; the "%s" returns no channels for importance "%s"; %s.', $errorPrefix, ChannelPolicy::class, $notification->getImportance(), $error));
  72.             }
  73.         }
  74.         foreach ($channels as $channelName) {
  75.             $transportName = null;
  76.             if (false !== $pos = strpos($channelName, '/')) {
  77.                 $transportName = substr($channelName, $pos + 1);
  78.                 $channelName = substr($channelName, 0, $pos);
  79.             }
  80.             if (null === $channel = $this->getChannel($channelName)) {
  81.                 throw new LogicException(sprintf('The "%s" channel does not exist.', $channelName));
  82.             }
  83.             if ($channel instanceof SmsChannel && $recipient instanceof NoRecipient) {
  84.                 throw new LogicException(sprintf('The "%s" channel needs a Recipient.', $channelName));
  85.             }
  86.             if (!$channel->supports($notification, $recipient)) {
  87.                 throw new LogicException(sprintf('The "%s" channel is not supported.', $channelName));
  88.             }
  89.             yield $channel => $transportName;
  90.         }
  91.     }
  92.     private function getChannel(string $name): ?ChannelInterface
  93.     {
  94.         if ($this->channels instanceof ContainerInterface) {
  95.             return $this->channels->has($name) ? $this->channels->get($name) : null;
  96.         }
  97.         return $this->channels[$name] ?? null;
  98.     }
  99. }