ヤミRoot VoidGate
User / IP
:
216.73.216.143
Host / Server
:
146.88.233.70 / dev.loger.cm
System
:
Linux hybrid1120.fr.ns.planethoster.net 3.10.0-957.21.2.el7.x86_64 #1 SMP Wed Jun 5 14:26:44 UTC 2019 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
logercm
/
dev.loger.cm
/
fixtures
/
assert
/
Viewing: notifier.tar
Channel/AbstractChannel.php 0000644 00000001740 15120140573 0011661 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Transport\TransportInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ abstract class AbstractChannel implements ChannelInterface { protected $transport; protected $bus; public function __construct(TransportInterface $transport = null, MessageBusInterface $bus = null) { if (null === $transport && null === $bus) { throw new LogicException(sprintf('"%s" needs a Transport or a Bus but both cannot be "null".', static::class)); } $this->transport = $transport; $this->bus = $bus; } } Channel/BrowserChannel.php 0000644 00000002414 15120140573 0011540 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class BrowserChannel implements ChannelInterface { private $stack; public function __construct(RequestStack $stack) { $this->stack = $stack; } public function notify(Notification $notification, RecipientInterface $recipient, string $transportName = null): void { if (null === $request = $this->stack->getCurrentRequest()) { return; } $message = $notification->getSubject(); if ($notification->getEmoji()) { $message = $notification->getEmoji().' '.$message; } $request->getSession()->getFlashBag()->add('notification', $message); } public function supports(Notification $notification, RecipientInterface $recipient): bool { return true; } } Channel/ChannelInterface.php 0000644 00000001310 15120140573 0012007 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ interface ChannelInterface { public function notify(Notification $notification, RecipientInterface $recipient, string $transportName = null): void; public function supports(Notification $notification, RecipientInterface $recipient): bool; } Channel/ChannelPolicy.php 0000644 00000001563 15120140573 0011360 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Notifier\Exception\InvalidArgumentException; /** * @author Fabien Potencier <fabien@symfony.com> */ final class ChannelPolicy implements ChannelPolicyInterface { private $policy; public function __construct(array $policy) { $this->policy = $policy; } public function getChannels(string $importance): array { if (!isset($this->policy[$importance])) { throw new InvalidArgumentException(sprintf('Importance "%s" is not defined in the Policy.', $importance)); } return $this->policy[$importance]; } } Channel/ChannelPolicyInterface.php 0000644 00000000737 15120140573 0013203 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; /** * @author Fabien Potencier <fabien@symfony.com> */ interface ChannelPolicyInterface { /** * @return string[] */ public function getChannels(string $importance): array; } Channel/ChatChannel.php 0000644 00000002640 15120140573 0010775 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Notifier\Message\ChatMessage; use Symfony\Component\Notifier\Notification\ChatNotificationInterface; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class ChatChannel extends AbstractChannel { public function notify(Notification $notification, RecipientInterface $recipient, string $transportName = null): void { $message = null; if ($notification instanceof ChatNotificationInterface) { $message = $notification->asChatMessage($recipient, $transportName); } if (null === $message) { $message = ChatMessage::fromNotification($notification); } if (null !== $transportName) { $message->transport($transportName); } if (null === $this->bus) { $this->transport->send($message); } else { $this->bus->dispatch($message); } } public function supports(Notification $notification, RecipientInterface $recipient): bool { return true; } } Channel/EmailChannel.php 0000644 00000006367 15120140573 0011157 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Messenger\SendEmailMessage; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Mime\Email; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Message\EmailMessage; use Symfony\Component\Notifier\Notification\EmailNotificationInterface; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\EmailRecipientInterface; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class EmailChannel implements ChannelInterface { private $transport; private $bus; private $from; private $envelope; public function __construct(TransportInterface $transport = null, MessageBusInterface $bus = null, string $from = null, Envelope $envelope = null) { if (null === $transport && null === $bus) { throw new LogicException(sprintf('"%s" needs a Transport or a Bus but both cannot be "null".', static::class)); } $this->transport = $transport; $this->bus = $bus; $this->from = $from ?: ($envelope ? $envelope->getSender() : null); $this->envelope = $envelope; } public function notify(Notification $notification, RecipientInterface $recipient, string $transportName = null): void { $message = null; if ($notification instanceof EmailNotificationInterface) { $message = $notification->asEmailMessage($recipient, $transportName); } $message = $message ?: EmailMessage::fromNotification($notification, $recipient, $transportName); $email = $message->getMessage(); if ($email instanceof Email) { if (!$email->getFrom()) { if (null === $this->from) { throw new LogicException(sprintf('To send the "%s" notification by email, you should either configure a global "from" header, set a sender in the global "envelope" of the mailer configuration or set a "from" header in the "asEmailMessage()" method.', get_debug_type($notification))); } $email->from($this->from); } if (!$email->getTo()) { $email->to($recipient->getEmail()); } } if (null !== $this->envelope) { $message->envelope($this->envelope); } if (null !== $transportName) { $message->transport($transportName); } if (null === $this->bus) { $this->transport->send($message->getMessage(), $message->getEnvelope()); } else { $this->bus->dispatch(new SendEmailMessage($message->getMessage(), $message->getEnvelope())); } } public function supports(Notification $notification, RecipientInterface $recipient): bool { return $recipient instanceof EmailRecipientInterface; } } Channel/PushChannel.php 0000644 00000002643 15120140573 0011040 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Notifier\Message\PushMessage; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Notification\PushNotificationInterface; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Tomas Norkūnas <norkunas.tom@gmail.com> */ class PushChannel extends AbstractChannel { public function notify(Notification $notification, RecipientInterface $recipient, string $transportName = null): void { $message = null; if ($notification instanceof PushNotificationInterface) { $message = $notification->asPushMessage($recipient, $transportName); } if (null === $message) { $message = PushMessage::fromNotification($notification); } if (null !== $transportName) { $message->transport($transportName); } if (null === $this->bus) { $this->transport->send($message); } else { $this->bus->dispatch($message); } } public function supports(Notification $notification, RecipientInterface $recipient): bool { return true; } } Channel/SmsChannel.php 0000644 00000003015 15120140573 0010655 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Channel; use Symfony\Component\Notifier\Message\SmsMessage; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Notification\SmsNotificationInterface; use Symfony\Component\Notifier\Recipient\RecipientInterface; use Symfony\Component\Notifier\Recipient\SmsRecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class SmsChannel extends AbstractChannel { public function notify(Notification $notification, RecipientInterface $recipient, string $transportName = null): void { $message = null; if ($notification instanceof SmsNotificationInterface) { $message = $notification->asSmsMessage($recipient, $transportName); } if (null === $message) { $message = SmsMessage::fromNotification($notification, $recipient); } if (null !== $transportName) { $message->transport($transportName); } if (null === $this->bus) { $this->transport->send($message); } else { $this->bus->dispatch($message); } } public function supports(Notification $notification, RecipientInterface $recipient): bool { return $recipient instanceof SmsRecipientInterface; } } DataCollector/NotificationDataCollector.php 0000644 00000002521 15120140573 0015062 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\Notifier\Event\NotificationEvents; use Symfony\Component\Notifier\EventListener\NotificationLoggerListener; /** * @author Fabien Potencier <fabien@symfony.com> */ final class NotificationDataCollector extends DataCollector { private $logger; public function __construct(NotificationLoggerListener $logger) { $this->logger = $logger; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Throwable $exception = null) { $this->data['events'] = $this->logger->getEvents(); } public function getEvents(): NotificationEvents { return $this->data['events']; } /** * {@inheritdoc} */ public function reset() { $this->data = []; } /** * {@inheritdoc} */ public function getName(): string { return 'notifier'; } } Event/FailedMessageEvent.php 0000644 00000001556 15120140573 0012036 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Event; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Contracts\EventDispatcher\Event; /** * @author Smaïne Milianni <smaine.milianni@gmail.com> */ final class FailedMessageEvent extends Event { private $message; private $error; public function __construct(MessageInterface $message, \Throwable $error) { $this->message = $message; $this->error = $error; } public function getMessage(): MessageInterface { return $this->message; } public function getError(): \Throwable { return $this->error; } } Event/MessageEvent.php 0000644 00000001542 15120140573 0010724 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Event; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Contracts\EventDispatcher\Event; /** * @author Fabien Potencier <fabien@symfony.com> */ final class MessageEvent extends Event { private $message; private $queued; public function __construct(MessageInterface $message, bool $queued = false) { $this->message = $message; $this->queued = $queued; } public function getMessage(): MessageInterface { return $this->message; } public function isQueued(): bool { return $this->queued; } } Event/NotificationEvents.php 0000644 00000002727 15120140573 0012157 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Event; use Symfony\Component\Notifier\Message\MessageInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class NotificationEvents { private $events = []; private $transports = []; public function add(MessageEvent $event): void { $this->events[] = $event; $this->transports[(string) $event->getMessage()->getTransport()] = true; } public function getTransports(): array { return array_keys($this->transports); } /** * @return MessageEvent[] */ public function getEvents(string $name = null): array { if (null === $name) { return $this->events; } $events = []; foreach ($this->events as $event) { if ($name === (string) $event->getMessage()->getTransport()) { $events[] = $event; } } return $events; } /** * @return MessageInterface[] */ public function getMessages(string $name = null): array { $events = $this->getEvents($name); $messages = []; foreach ($events as $event) { $messages[] = $event->getMessage(); } return $messages; } } Event/SentMessageEvent.php 0000644 00000001302 15120140573 0011550 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Event; use Symfony\Component\Notifier\Message\SentMessage; use Symfony\Contracts\EventDispatcher\Event; /** * @author Smaïne Milianni <smaine.milianni@gmail.com> */ final class SentMessageEvent extends Event { private $message; public function __construct(SentMessage $message) { $this->message = $message; } public function getMessage(): SentMessage { return $this->message; } } EventListener/NotificationLoggerListener.php 0000644 00000002353 15120140573 0015341 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Notifier\Event\MessageEvent; use Symfony\Component\Notifier\Event\NotificationEvents; use Symfony\Contracts\Service\ResetInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class NotificationLoggerListener implements EventSubscriberInterface, ResetInterface { private $events; public function __construct() { $this->events = new NotificationEvents(); } /** * {@inheritdoc} */ public function reset() { $this->events = new NotificationEvents(); } public function onNotification(MessageEvent $event): void { $this->events->add($event); } public function getEvents(): NotificationEvents { return $this->events; } public static function getSubscribedEvents() { return [ MessageEvent::class => ['onNotification', -255], ]; } } EventListener/SendFailedMessageToNotifierListener.php 0000644 00000003345 15120140573 0017063 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Notifier; /** * Sends a rejected message to the notifier. * * @author Fabien Potencier <fabien@symfony.com> */ class SendFailedMessageToNotifierListener implements EventSubscriberInterface { private $notifier; public function __construct(Notifier $notifier) { $this->notifier = $notifier; } public function onMessageFailed(WorkerMessageFailedEvent $event) { if ($event->willRetry()) { return; } $throwable = $event->getThrowable(); if ($throwable instanceof HandlerFailedException) { $throwable = $throwable->getNestedExceptions()[0]; } $envelope = $event->getEnvelope(); $notification = Notification::fromThrowable($throwable)->importance(Notification::IMPORTANCE_HIGH); $notification->subject(sprintf('A "%s" message has just failed: %s.', \get_class($envelope->getMessage()), $notification->getSubject())); $this->notifier->send($notification, ...$this->notifier->getAdminRecipients()); } public static function getSubscribedEvents() { return [ WorkerMessageFailedEvent::class => 'onMessageFailed', ]; } } Exception/ExceptionInterface.php 0000644 00000000722 15120140573 0012771 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier <fabien@symfony.com> */ interface ExceptionInterface extends \Throwable { } Exception/IncompleteDsnException.php 0000644 00000001460 15120140573 0013635 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class IncompleteDsnException extends InvalidArgumentException { private $dsn; public function __construct(string $message, string $dsn = null, \Throwable $previous = null) { $this->dsn = $dsn; if ($dsn) { $message = sprintf('Invalid "%s" notifier DSN: %s', $dsn, $message); } parent::__construct($message, 0, $previous); } public function getOriginalDsn(): string { return $this->dsn; } } Exception/InvalidArgumentException.php 0000644 00000000673 15120140573 0014167 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } Exception/LengthException.php 0000644 00000000613 15120140573 0012311 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Oskar Stark <oskarstark@googlemail.com> */ class LengthException extends LogicException { } Exception/LogicException.php 0000644 00000000647 15120140573 0012134 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class LogicException extends \LogicException implements ExceptionInterface { } Exception/MissingRequiredOptionException.php 0000644 00000001231 15120140573 0015370 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Oskar Stark <oskarstark@googlemail.com> */ class MissingRequiredOptionException extends IncompleteDsnException { public function __construct(string $option, string $dsn = null, \Throwable $previous = null) { $message = sprintf('The option "%s" is required but missing.', $option); parent::__construct($message, $dsn, $previous); } } Exception/RuntimeException.php 0000644 00000000653 15120140573 0012517 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } Exception/TransportException.php 0000644 00000001756 15120140573 0013075 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; use Symfony\Contracts\HttpClient\ResponseInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class TransportException extends RuntimeException implements TransportExceptionInterface { private $response; private $debug = ''; public function __construct(string $message, ResponseInterface $response, int $code = 0, \Throwable $previous = null) { $this->response = $response; $this->debug .= $response->getInfo('debug') ?? ''; parent::__construct($message, $code, $previous); } public function getResponse(): ResponseInterface { return $this->response; } public function getDebug(): string { return $this->debug; } } Exception/TransportExceptionInterface.php 0000644 00000000705 15120140573 0014707 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; /** * @author Fabien Potencier <fabien@symfony.com> */ interface TransportExceptionInterface extends ExceptionInterface { public function getDebug(): string; } Exception/UnsupportedMessageTypeException.php 0000644 00000001476 15120140573 0015577 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; use Symfony\Component\Notifier\Message\MessageInterface; /** * @author Oskar Stark <oskarstark@googlemail.com> */ class UnsupportedMessageTypeException extends LogicException { public function __construct(string $transport, string $supported, MessageInterface $given) { $message = sprintf( 'The "%s" transport only supports instances of "%s" (instance of "%s" given).', $transport, $supported, get_debug_type($given) ); parent::__construct($message); } } Exception/UnsupportedSchemeException.php 0000644 00000020553 15120140573 0014552 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Exception; use Symfony\Component\Notifier\Bridge; use Symfony\Component\Notifier\Transport\Dsn; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ class UnsupportedSchemeException extends LogicException { private const SCHEME_TO_PACKAGE_MAP = [ 'allmysms' => [ 'class' => Bridge\AllMySms\AllMySmsTransportFactory::class, 'package' => 'symfony/all-my-sms-notifier', ], 'clickatell' => [ 'class' => Bridge\Clickatell\ClickatellTransportFactory::class, 'package' => 'symfony/clickatell-notifier', ], 'discord' => [ 'class' => Bridge\Discord\DiscordTransportFactory::class, 'package' => 'symfony/discord-notifier', ], 'esendex' => [ 'class' => Bridge\Esendex\EsendexTransportFactory::class, 'package' => 'symfony/esendex-notifier', ], 'expo' => [ 'class' => Bridge\Expo\ExpoTransportFactory::class, 'package' => 'symfony/expo-notifier', ], 'fakechat' => [ 'class' => Bridge\FakeChat\FakeChatTransportFactory::class, 'package' => 'symfony/fake-chat-notifier', ], 'fakesms' => [ 'class' => Bridge\FakeSms\FakeSmsTransportFactory::class, 'package' => 'symfony/fake-sms-notifier', ], 'firebase' => [ 'class' => Bridge\Firebase\FirebaseTransportFactory::class, 'package' => 'symfony/firebase-notifier', ], 'freemobile' => [ 'class' => Bridge\FreeMobile\FreeMobileTransportFactory::class, 'package' => 'symfony/free-mobile-notifier', ], 'gatewayapi' => [ 'class' => Bridge\GatewayApi\GatewayApiTransportFactory::class, 'package' => 'symfony/gateway-api-notifier', ], 'gitter' => [ 'class' => Bridge\Gitter\GitterTransportFactory::class, 'package' => 'symfony/gitter-notifier', ], 'googlechat' => [ 'class' => Bridge\GoogleChat\GoogleChatTransportFactory::class, 'package' => 'symfony/google-chat-notifier', ], 'infobip' => [ 'class' => Bridge\Infobip\InfobipTransportFactory::class, 'package' => 'symfony/infobip-notifier', ], 'iqsms' => [ 'class' => Bridge\Iqsms\IqsmsTransportFactory::class, 'package' => 'symfony/iqsms-notifier', ], 'lightsms' => [ 'class' => Bridge\LightSms\LightSmsTransportFactory::class, 'package' => 'symfony/light-sms-notifier', ], 'linkedin' => [ 'class' => Bridge\LinkedIn\LinkedInTransportFactory::class, 'package' => 'symfony/linked-in-notifier', ], 'mailjet' => [ 'class' => Bridge\Mailjet\MailjetTransportFactory::class, 'package' => 'symfony/mailjet-notifier', ], 'mattermost' => [ 'class' => Bridge\Mattermost\MattermostTransportFactory::class, 'package' => 'symfony/mattermost-notifier', ], 'mercure' => [ 'class' => Bridge\Mercure\MercureTransportFactory::class, 'package' => 'symfony/mercure-notifier', ], 'messagebird' => [ 'class' => Bridge\MessageBird\MessageBirdTransportFactory::class, 'package' => 'symfony/message-bird-notifier', ], 'messagemedia' => [ 'class' => Bridge\MessageMedia\MessageMediaTransportFactory::class, 'package' => 'symfony/message-media-notifier', ], 'microsoftteams' => [ 'class' => Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class, 'package' => 'symfony/microsoft-teams-notifier', ], 'mobyt' => [ 'class' => Bridge\Mobyt\MobytTransportFactory::class, 'package' => 'symfony/mobyt-notifier', ], 'nexmo' => [ 'class' => Bridge\Nexmo\NexmoTransportFactory::class, 'package' => 'symfony/nexmo-notifier', ], 'octopush' => [ 'class' => Bridge\Octopush\OctopushTransportFactory::class, 'package' => 'symfony/octopush-notifier', ], 'onesignal' => [ 'class' => Bridge\OneSignal\OneSignalTransportFactory::class, 'package' => 'symfony/one-signal-notifier', ], 'ovhcloud' => [ 'class' => Bridge\OvhCloud\OvhCloudTransportFactory::class, 'package' => 'symfony/ovh-cloud-notifier', ], 'rocketchat' => [ 'class' => Bridge\RocketChat\RocketChatTransportFactory::class, 'package' => 'symfony/rocket-chat-notifier', ], 'sendinblue' => [ 'class' => Bridge\Sendinblue\SendinblueTransportFactory::class, 'package' => 'symfony/sendinblue-notifier', ], 'sinch' => [ 'class' => Bridge\Sinch\SinchTransportFactory::class, 'package' => 'symfony/sinch-notifier', ], 'slack' => [ 'class' => Bridge\Slack\SlackTransportFactory::class, 'package' => 'symfony/slack-notifier', ], 'sms77' => [ 'class' => Bridge\Sms77\Sms77TransportFactory::class, 'package' => 'symfony/sms77-notifier', ], 'smsapi' => [ 'class' => Bridge\Smsapi\SmsapiTransportFactory::class, 'package' => 'symfony/smsapi-notifier', ], 'smsbiuras' => [ 'class' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, 'package' => 'symfony/sms-biuras-notifier', ], 'smsc' => [ 'class' => Bridge\Smsc\SmscTransportFactory::class, 'package' => 'symfony/smsc-notifier', ], 'sns' => [ 'class' => Bridge\AmazonSns\AmazonSnsTransportFactory::class, 'package' => 'symfony/amazon-sns-notifier', ], 'spothit' => [ 'class' => Bridge\SpotHit\SpotHitTransportFactory::class, 'package' => 'symfony/spot-hit-notifier', ], 'telegram' => [ 'class' => Bridge\Telegram\TelegramTransportFactory::class, 'package' => 'symfony/telegram-notifier', ], 'telnyx' => [ 'class' => Bridge\Telnyx\TelnyxTransportFactory::class, 'package' => 'symfony/telnyx-notifier', ], 'turbosms' => [ 'class' => Bridge\TurboSms\TurboSmsTransportFactory::class, 'package' => 'symfony/turbo-sms-notifier', ], 'twilio' => [ 'class' => Bridge\Twilio\TwilioTransportFactory::class, 'package' => 'symfony/twilio-notifier', ], 'vonage' => [ 'class' => Bridge\Vonage\VonageTransportFactory::class, 'package' => 'symfony/vonage-notifier', ], 'yunpian' => [ 'class' => Bridge\Yunpian\YunpianTransportFactory::class, 'package' => 'symfony/yunpian-notifier', ], 'zulip' => [ 'class' => Bridge\Zulip\ZulipTransportFactory::class, 'package' => 'symfony/zulip-notifier', ], ]; /** * @param string[] $supported */ public function __construct(Dsn $dsn, string $name = null, array $supported = [], \Throwable $previous = null) { $provider = $dsn->getScheme(); if (false !== $pos = strpos($provider, '+')) { $provider = substr($provider, 0, $pos); } $package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null; if ($package && !class_exists($package['class'])) { parent::__construct(sprintf('Unable to send notification via "%s" as the bridge is not installed; try running "composer require %s".', $provider, $package['package'])); return; } $message = sprintf('The "%s" scheme is not supported', $dsn->getScheme()); if ($name && $supported) { $message .= sprintf('; supported schemes for notifier "%s" are: "%s"', $name, implode('", "', $supported)); } parent::__construct($message.'.', 0, $previous); } } Message/ChatMessage.php 0000644 00000003653 15120140573 0011032 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; use Symfony\Component\Notifier\Notification\Notification; /** * @author Fabien Potencier <fabien@symfony.com> */ final class ChatMessage implements MessageInterface { private $transport; private $subject; private $options; private $notification; public function __construct(string $subject, MessageOptionsInterface $options = null) { $this->subject = $subject; $this->options = $options; } public static function fromNotification(Notification $notification): self { $message = new self($notification->getSubject()); $message->notification = $notification; return $message; } /** * @return $this */ public function subject(string $subject): self { $this->subject = $subject; return $this; } public function getSubject(): string { return $this->subject; } public function getRecipientId(): ?string { return $this->options ? $this->options->getRecipientId() : null; } /** * @return $this */ public function options(MessageOptionsInterface $options): self { $this->options = $options; return $this; } public function getOptions(): ?MessageOptionsInterface { return $this->options; } /** * @return $this */ public function transport(?string $transport): self { $this->transport = $transport; return $this; } public function getTransport(): ?string { return $this->transport; } public function getNotification(): ?Notification { return $this->notification; } } Message/EmailMessage.php 0000644 00000006325 15120140573 0011201 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; use Symfony\Bridge\Twig\Mime\NotificationEmail; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mime\Email; use Symfony\Component\Mime\RawMessage; use Symfony\Component\Notifier\Exception\InvalidArgumentException; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\EmailRecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class EmailMessage implements MessageInterface { private $message; private $envelope; public function __construct(RawMessage $message, Envelope $envelope = null) { $this->message = $message; $this->envelope = $envelope; } public static function fromNotification(Notification $notification, EmailRecipientInterface $recipient): self { if ('' === $recipient->getEmail()) { throw new InvalidArgumentException(sprintf('"%s" needs an email, it cannot be empty.', __CLASS__)); } if (!class_exists(NotificationEmail::class)) { $email = (new Email()) ->to($recipient->getEmail()) ->subject($notification->getSubject()) ->text($notification->getContent() ?: $notification->getSubject()) ; } else { $email = (new NotificationEmail()) ->to($recipient->getEmail()) ->subject($notification->getSubject()) ->content($notification->getContent() ?: $notification->getSubject()) ->importance($notification->getImportance()) ; if ($exception = $notification->getException()) { $email->exception($exception); } } return new self($email); } public function getMessage(): RawMessage { return $this->message; } public function getEnvelope(): ?Envelope { return $this->envelope; } /** * @return $this */ public function envelope(Envelope $envelope): self { $this->envelope = $envelope; return $this; } public function getSubject(): string { return ''; } public function getRecipientId(): ?string { return null; } public function getOptions(): ?MessageOptionsInterface { return null; } /** * @return $this */ public function transport(?string $transport): self { if (!$this->message instanceof Email) { throw new LogicException('Cannot set a Transport on a RawMessage instance.'); } if (null === $transport) { return $this; } $this->message->getHeaders()->addTextHeader('X-Transport', $transport); return $this; } public function getTransport(): ?string { return $this->message instanceof Email ? $this->message->getHeaders()->getHeaderBody('X-Transport') : null; } } Message/MessageInterface.php 0000644 00000001072 15120140573 0012044 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; /** * @author Fabien Potencier <fabien@symfony.com> */ interface MessageInterface { public function getRecipientId(): ?string; public function getSubject(): string; public function getOptions(): ?MessageOptionsInterface; public function getTransport(): ?string; } Message/MessageOptionsInterface.php 0000644 00000000722 15120140573 0013421 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; /** * @author Fabien Potencier <fabien@symfony.com> */ interface MessageOptionsInterface { public function toArray(): array; public function getRecipientId(): ?string; } Message/NullMessage.php 0000644 00000002003 15120140573 0011051 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; /** * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ final class NullMessage implements MessageInterface { private $decoratedMessage; public function __construct(MessageInterface $message) { $this->decoratedMessage = $message; } public function getRecipientId(): ?string { return $this->decoratedMessage->getRecipientId(); } public function getSubject(): string { return $this->decoratedMessage->getSubject(); } public function getOptions(): ?MessageOptionsInterface { return $this->decoratedMessage->getOptions(); } public function getTransport(): ?string { return $this->decoratedMessage->getTransport() ?? 'null'; } } Message/PushMessage.php 0000644 00000004165 15120140573 0011071 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; use Symfony\Component\Notifier\Notification\Notification; /** * @author Tomas Norkūnas <norkunas.tom@gmail.com> */ final class PushMessage implements MessageInterface { private $transport; private $subject; private $content; private $options; private $notification; public function __construct(string $subject, string $content, MessageOptionsInterface $options = null) { $this->subject = $subject; $this->content = $content; $this->options = $options; } public static function fromNotification(Notification $notification): self { $message = new self($notification->getSubject(), $notification->getContent()); $message->notification = $notification; return $message; } public function getRecipientId(): ?string { return $this->options ? $this->options->getRecipientId() : null; } public function subject(string $subject): self { $this->subject = $subject; return $this; } public function getSubject(): string { return $this->subject; } public function content(string $content): self { $this->content = $content; return $this; } public function getContent(): string { return $this->content; } public function options(MessageOptionsInterface $options): self { $this->options = $options; return $this; } public function getOptions(): ?MessageOptionsInterface { return $this->options; } public function transport(?string $transport): self { $this->transport = $transport; return $this; } public function getTransport(): ?string { return $this->transport; } public function getNotification(): ?Notification { return $this->notification; } } Message/SentMessage.php 0000644 00000001734 15120140573 0011062 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; /** * @author Jérémy Romey <jeremy@free-agent.fr> */ final class SentMessage { private $original; private $transport; private $messageId; public function __construct(MessageInterface $original, string $transport) { $this->original = $original; $this->transport = $transport; } public function getOriginalMessage(): MessageInterface { return $this->original; } public function getTransport(): string { return $this->transport; } public function setMessageId(string $id): void { $this->messageId = $id; } public function getMessageId(): ?string { return $this->messageId; } } Message/SmsMessage.php 0000644 00000004271 15120140573 0010712 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Message; use Symfony\Component\Notifier\Exception\InvalidArgumentException; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\SmsRecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class SmsMessage implements MessageInterface { private $transport; private $subject; private $phone; public function __construct(string $phone, string $subject) { if ('' === $phone) { throw new InvalidArgumentException(sprintf('"%s" needs a phone number, it cannot be empty.', __CLASS__)); } $this->subject = $subject; $this->phone = $phone; } public static function fromNotification(Notification $notification, SmsRecipientInterface $recipient): self { return new self($recipient->getPhone(), $notification->getSubject()); } /** * @return $this */ public function phone(string $phone): self { if ('' === $phone) { throw new InvalidArgumentException(sprintf('"%s" needs a phone number, it cannot be empty.', static::class)); } $this->phone = $phone; return $this; } public function getPhone(): string { return $this->phone; } public function getRecipientId(): string { return $this->phone; } /** * @return $this */ public function subject(string $subject): self { $this->subject = $subject; return $this; } public function getSubject(): string { return $this->subject; } /** * @return $this */ public function transport(?string $transport): self { $this->transport = $transport; return $this; } public function getTransport(): ?string { return $this->transport; } public function getOptions(): ?MessageOptionsInterface { return null; } } Messenger/MessageHandler.php 0000644 00000001461 15120140573 0012067 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Messenger; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; use Symfony\Component\Notifier\Transport\TransportInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class MessageHandler { private $transport; public function __construct(TransportInterface $transport) { $this->transport = $transport; } public function __invoke(MessageInterface $message): ?SentMessage { return $this->transport->send($message); } } Notification/ChatNotificationInterface.php 0000644 00000001137 15120140573 0014752 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Notification; use Symfony\Component\Notifier\Message\ChatMessage; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ interface ChatNotificationInterface { public function asChatMessage(RecipientInterface $recipient, string $transport = null): ?ChatMessage; } Notification/EmailNotificationInterface.php 0000644 00000001155 15120140573 0015122 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Notification; use Symfony\Component\Notifier\Message\EmailMessage; use Symfony\Component\Notifier\Recipient\EmailRecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ interface EmailNotificationInterface { public function asEmailMessage(EmailRecipientInterface $recipient, string $transport = null): ?EmailMessage; } Notification/Notification.php 0000644 00000011657 15120140573 0012341 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Notification; use Psr\Log\LogLevel; use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class Notification { private const LEVELS = [ LogLevel::DEBUG => 100, LogLevel::INFO => 200, LogLevel::NOTICE => 250, LogLevel::WARNING => 300, LogLevel::ERROR => 400, LogLevel::CRITICAL => 500, LogLevel::ALERT => 550, LogLevel::EMERGENCY => 600, ]; public const IMPORTANCE_URGENT = 'urgent'; public const IMPORTANCE_HIGH = 'high'; public const IMPORTANCE_MEDIUM = 'medium'; public const IMPORTANCE_LOW = 'low'; private $channels = []; private $subject = ''; private $content = ''; private $emoji = ''; private $exception; private $exceptionAsString = ''; private $importance = self::IMPORTANCE_HIGH; public function __construct(string $subject = '', array $channels = []) { $this->subject = $subject; $this->channels = $channels; } public static function fromThrowable(\Throwable $exception, array $channels = []): self { $parts = explode('\\', \get_class($exception)); $notification = new self(sprintf('%s: %s', array_pop($parts), $exception->getMessage()), $channels); if (class_exists(FlattenException::class)) { $notification->exception = $exception instanceof FlattenException ? $exception : FlattenException::createFromThrowable($exception); } $notification->exceptionAsString = $notification->computeExceptionAsString($exception); return $notification; } /** * @return $this */ public function subject(string $subject): self { $this->subject = $subject; return $this; } public function getSubject(): string { return $this->subject; } /** * @return $this */ public function content(string $content): self { $this->content = $content; return $this; } public function getContent(): string { return $this->content; } /** * @return $this */ public function importance(string $importance): self { $this->importance = $importance; return $this; } public function getImportance(): string { return $this->importance; } /** * @param string $level A PSR Logger log level name * * @return $this */ public function importanceFromLogLevelName(string $level): self { $level = self::LEVELS[strtolower($level)]; $this->importance = $level >= 500 ? self::IMPORTANCE_URGENT : ($level >= 400 ? self::IMPORTANCE_HIGH : self::IMPORTANCE_LOW); return $this; } /** * @return $this */ public function emoji(string $emoji): self { $this->emoji = $emoji; return $this; } public function getEmoji(): string { return $this->emoji ?: $this->getDefaultEmoji(); } public function getException(): ?FlattenException { return $this->exception; } public function getExceptionAsString(): string { return $this->exceptionAsString; } /** * @return $this */ public function channels(array $channels): self { $this->channels = $channels; return $this; } public function getChannels(RecipientInterface $recipient): array { return $this->channels; } protected function getDefaultEmoji(): string { if (!$this->exceptionAsString) { return ''; } switch ($this->importance) { case self::IMPORTANCE_URGENT: return '🌩️'; case self::IMPORTANCE_HIGH: return '🌧️'; case self::IMPORTANCE_MEDIUM: return '🌦️'; case self::IMPORTANCE_LOW: default: return '⛅'; } } private function computeExceptionAsString(\Throwable $exception): string { if (class_exists(FlattenException::class)) { $exception = $exception instanceof FlattenException ? $exception : FlattenException::createFromThrowable($exception); return $exception->getAsString(); } $message = \get_class($exception); if ('' !== $exception->getMessage()) { $message .= ': '.$exception->getMessage(); } $message .= ' in '.$exception->getFile().':'.$exception->getLine()."\n"; $message .= "Stack trace:\n".$exception->getTraceAsString()."\n\n"; return rtrim($message); } } Notification/PushNotificationInterface.php 0000644 00000001046 15120140573 0015011 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Notification; use Symfony\Component\Notifier\Message\PushMessage; use Symfony\Component\Notifier\Recipient\RecipientInterface; interface PushNotificationInterface { public function asPushMessage(RecipientInterface $recipient, string $transport = null): ?PushMessage; } Notification/SmsNotificationInterface.php 0000644 00000001141 15120140573 0014630 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Notification; use Symfony\Component\Notifier\Message\SmsMessage; use Symfony\Component\Notifier\Recipient\SmsRecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ interface SmsNotificationInterface { public function asSmsMessage(SmsRecipientInterface $recipient, string $transport = null): ?SmsMessage; } Recipient/EmailRecipientInterface.php 0000644 00000000711 15120140573 0013707 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; /** * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ interface EmailRecipientInterface extends RecipientInterface { public function getEmail(): string; } Recipient/EmailRecipientTrait.php 0000644 00000000743 15120140573 0013077 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; /** * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ trait EmailRecipientTrait { private $email; public function getEmail(): string { return $this->email; } } Recipient/NoRecipient.php 0000644 00000000614 15120140573 0011415 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; /** * @author Fabien Potencier <fabien@symfony.com> */ class NoRecipient implements RecipientInterface { } Recipient/Recipient.php 0000644 00000002462 15120140573 0011123 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; use Symfony\Component\Notifier\Exception\InvalidArgumentException; /** * @author Fabien Potencier <fabien@symfony.com> * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ class Recipient implements EmailRecipientInterface, SmsRecipientInterface { use EmailRecipientTrait; use SmsRecipientTrait; public function __construct(string $email = '', string $phone = '') { if ('' === $email && '' === $phone) { throw new InvalidArgumentException(sprintf('"%s" needs an email or a phone but both cannot be empty.', static::class)); } $this->email = $email; $this->phone = $phone; } /** * @return $this */ public function email(string $email): self { $this->email = $email; return $this; } /** * Sets the phone number (no spaces, international code like in +3312345678). * * @return $this */ public function phone(string $phone): self { $this->phone = $phone; return $this; } } Recipient/RecipientInterface.php 0000644 00000000601 15120140573 0012735 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; /** * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ interface RecipientInterface { } Recipient/SmsRecipientInterface.php 0000644 00000000770 15120140573 0013427 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; /** * @author Fabien Potencier <fabien@symfony.com> * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ interface SmsRecipientInterface extends RecipientInterface { public function getPhone(): string; } Recipient/SmsRecipientTrait.php 0000644 00000000741 15120140573 0012610 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Recipient; /** * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> */ trait SmsRecipientTrait { private $phone; public function getPhone(): string { return $this->phone; } } Test/TransportFactoryTestCase.php 0000644 00000007011 15120140573 0013151 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Test; use PHPUnit\Framework\TestCase; use Symfony\Component\Notifier\Exception\IncompleteDsnException; use Symfony\Component\Notifier\Exception\MissingRequiredOptionException; use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; use Symfony\Component\Notifier\Transport\Dsn; use Symfony\Component\Notifier\Transport\TransportFactoryInterface; use Symfony\Component\Notifier\Transport\TransportInterface; /** * A test case to ease testing a notifier transport factory. * * @author Oskar Stark <oskarstark@googlemail.com> */ abstract class TransportFactoryTestCase extends TestCase { abstract public function createFactory(): TransportFactoryInterface; /** * @return iterable<array{0: bool, 1: string}> */ abstract public static function supportsProvider(): iterable; /** * @return iterable<array{0: string, 1: string, 2: TransportInterface}> */ abstract public static function createProvider(): iterable; /** * @return iterable<array{0: string, 1: string|null}> */ public static function unsupportedSchemeProvider(): iterable { return []; } /** * @return iterable<array{0: string, 1: string|null}> */ public static function incompleteDsnProvider(): iterable { return []; } /** * @return iterable<array{0: string, 1: string|null}> */ public static function missingRequiredOptionProvider(): iterable { return []; } /** * @dataProvider supportsProvider */ public function testSupports(bool $expected, string $dsn) { $factory = $this->createFactory(); $this->assertSame($expected, $factory->supports(new Dsn($dsn))); } /** * @dataProvider createProvider */ public function testCreate(string $expected, string $dsn) { $factory = $this->createFactory(); $transport = $factory->create(new Dsn($dsn)); $this->assertSame($expected, (string) $transport); } /** * @dataProvider unsupportedSchemeProvider */ public function testUnsupportedSchemeException(string $dsn, string $message = null) { $factory = $this->createFactory(); $dsn = new Dsn($dsn); $this->expectException(UnsupportedSchemeException::class); if (null !== $message) { $this->expectExceptionMessage($message); } $factory->create($dsn); } /** * @dataProvider incompleteDsnProvider */ public function testIncompleteDsnException(string $dsn, string $message = null) { $factory = $this->createFactory(); $dsn = new Dsn($dsn); $this->expectException(IncompleteDsnException::class); if (null !== $message) { $this->expectExceptionMessage($message); } $factory->create($dsn); } /** * @dataProvider missingRequiredOptionProvider */ public function testMissingRequiredOptionException(string $dsn, string $message = null) { $factory = $this->createFactory(); $dsn = new Dsn($dsn); $this->expectException(MissingRequiredOptionException::class); if (null !== $message) { $this->expectExceptionMessage($message); } $factory->create($dsn); } } Test/TransportTestCase.php 0000644 00000007311 15120140573 0011624 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Test; use PHPUnit\Framework\TestCase; use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Transport\TransportInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * A test case to ease testing a Notifier transport. * * @author Oskar Stark <oskarstark@googlemail.com> */ abstract class TransportTestCase extends TestCase { protected const CUSTOM_HOST = 'host.test'; protected const CUSTOM_PORT = 42; abstract public static function createTransport(HttpClientInterface $client = null): TransportInterface; /** * @return iterable<array{0: string, 1: TransportInterface}> */ abstract public static function toStringProvider(): iterable; /** * @return iterable<array{0: MessageInterface, 1: TransportInterface}> */ abstract public static function supportedMessagesProvider(): iterable; /** * @return iterable<array{0: MessageInterface, 1: TransportInterface}> */ abstract public static function unsupportedMessagesProvider(): iterable; /** * @dataProvider toStringProvider */ public function testToString(string $expected, TransportInterface $transport) { $this->assertSame($expected, (string) $transport); } /** * @dataProvider supportedMessagesProvider */ public function testSupportedMessages(MessageInterface $message, TransportInterface $transport = null) { if (null === $transport) { $transport = $this->createTransport(); } $this->assertTrue($transport->supports($message)); } /** * @dataProvider unsupportedMessagesProvider */ public function testUnsupportedMessages(MessageInterface $message, TransportInterface $transport = null) { if (null === $transport) { $transport = $this->createTransport(); } $this->assertFalse($transport->supports($message)); } /** * @dataProvider unsupportedMessagesProvider */ public function testUnsupportedMessagesTrowUnsupportedMessageTypeExceptionWhenSend(MessageInterface $message, TransportInterface $transport = null) { if (null === $transport) { $transport = $this->createTransport(); } $this->expectException(UnsupportedMessageTypeException::class); $transport->send($message); } public function testCanSetCustomHost() { $transport = $this->createTransport(); $transport->setHost($customHost = self::CUSTOM_HOST); $this->assertMatchesRegularExpression(sprintf('/^.*\:\/\/(%s|.*\@%s)/', $customHost, $customHost), (string) $transport); } public function testCanSetCustomPort() { $transport = $this->createTransport(); $transport->setPort($customPort = self::CUSTOM_PORT); /* * @see https://regex101.com/r/shT9O2/1 */ $this->assertMatchesRegularExpression(sprintf('/^.*\:\/\/.*(\@.*)?\:%s((\?.*|\/.*))?$/', $customPort), (string) $transport); } public function testCanSetCustomHostAndPort() { $transport = $this->createTransport(); $transport->setHost($customHost = self::CUSTOM_HOST); $transport->setPort($customPort = self::CUSTOM_PORT); $this->assertMatchesRegularExpression(sprintf('/^.*\:\/\/(%s|.*\@%s)\:%s/', $customHost, $customHost, $customPort), (string) $transport); } } Transport/AbstractTransport.php 0000644 00000005622 15120140573 0012734 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\Notifier\Event\FailedMessageEvent; use Symfony\Component\Notifier\Event\MessageEvent; use Symfony\Component\Notifier\Event\SentMessageEvent; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ abstract class AbstractTransport implements TransportInterface { protected const HOST = 'localhost'; private $dispatcher; protected $client; protected $host; protected $port; public function __construct(HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null) { $this->client = $client; if (null === $client) { if (!class_exists(HttpClient::class)) { throw new LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); } $this->client = HttpClient::create(); } $this->dispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($dispatcher) : $dispatcher; } /** * @return $this */ public function setHost(?string $host): self { $this->host = $host; return $this; } /** * @return $this */ public function setPort(?int $port): self { $this->port = $port; return $this; } public function send(MessageInterface $message): SentMessage { if (null === $this->dispatcher) { return $this->doSend($message); } $this->dispatcher->dispatch(new MessageEvent($message)); try { $sentMessage = $this->doSend($message); } catch (\Throwable $error) { $this->dispatcher->dispatch(new FailedMessageEvent($message, $error)); throw $error; } $this->dispatcher->dispatch(new SentMessageEvent($sentMessage)); return $sentMessage; } abstract protected function doSend(MessageInterface $message): SentMessage; protected function getEndpoint(): string { return ($this->host ?: $this->getDefaultHost()).($this->port ? ':'.$this->port : ''); } protected function getDefaultHost(): string { return static::HOST; } } Transport/AbstractTransportFactory.php 0000644 00000003505 15120140573 0014262 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Component\Notifier\Exception\IncompleteDsnException; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * @author Konstantin Myakshin <molodchick@gmail.com> * @author Fabien Potencier <fabien@symfony.com> */ abstract class AbstractTransportFactory implements TransportFactoryInterface { protected $dispatcher; protected $client; public function __construct(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null) { $this->dispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($dispatcher) : $dispatcher; $this->client = $client; } public function supports(Dsn $dsn): bool { return \in_array($dsn->getScheme(), $this->getSupportedSchemes()); } /** * @return string[] */ abstract protected function getSupportedSchemes(): array; protected function getUser(Dsn $dsn): string { $user = $dsn->getUser(); if (null === $user) { throw new IncompleteDsnException('User is not set.', $dsn->getOriginalDsn()); } return $user; } protected function getPassword(Dsn $dsn): string { $password = $dsn->getPassword(); if (null === $password) { throw new IncompleteDsnException('Password is not set.', $dsn->getOriginalDsn()); } return $password; } } Transport/Dsn.php 0000644 00000005462 15120140573 0010002 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Exception\InvalidArgumentException; use Symfony\Component\Notifier\Exception\MissingRequiredOptionException; /** * @author Fabien Potencier <fabien@symfony.com> * @author Oskar Stark <oskarstark@googlemail.com> */ final class Dsn { private $scheme; private $host; private $user; private $password; private $port; private $path; private $options; private $originalDsn; public function __construct(string $dsn) { $this->originalDsn = $dsn; if (false === $parsedDsn = parse_url($dsn)) { throw new InvalidArgumentException(sprintf('The "%s" notifier DSN is invalid.', $dsn)); } if (!isset($parsedDsn['scheme'])) { throw new InvalidArgumentException(sprintf('The "%s" notifier DSN must contain a scheme.', $dsn)); } $this->scheme = $parsedDsn['scheme']; if (!isset($parsedDsn['host'])) { throw new InvalidArgumentException(sprintf('The "%s" notifier DSN must contain a host (use "default" by default).', $dsn)); } $this->host = $parsedDsn['host']; $this->user = '' !== ($parsedDsn['user'] ?? '') ? urldecode($parsedDsn['user']) : null; $this->password = '' !== ($parsedDsn['pass'] ?? '') ? urldecode($parsedDsn['pass']) : null; $this->port = $parsedDsn['port'] ?? null; $this->path = $parsedDsn['path'] ?? null; parse_str($parsedDsn['query'] ?? '', $this->options); } public function getScheme(): string { return $this->scheme; } public function getHost(): string { return $this->host; } public function getUser(): ?string { return $this->user; } public function getPassword(): ?string { return $this->password; } public function getPort(int $default = null): ?int { return $this->port ?? $default; } public function getOption(string $key, $default = null) { return $this->options[$key] ?? $default; } public function getRequiredOption(string $key) { if (!\array_key_exists($key, $this->options) || '' === trim($this->options[$key])) { throw new MissingRequiredOptionException($key); } return $this->options[$key]; } public function getOptions(): array { return $this->options; } public function getPath(): ?string { return $this->path; } public function getOriginalDsn(): string { return $this->originalDsn; } } Transport/FailoverTransport.php 0000644 00000002007 15120140573 0012732 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Message\MessageInterface; /** * Uses several Transports using a failover algorithm. * * @author Fabien Potencier <fabien@symfony.com> */ class FailoverTransport extends RoundRobinTransport { private $currentTransport; protected function getNextTransport(MessageInterface $message): ?TransportInterface { if (null === $this->currentTransport || $this->isTransportDead($this->currentTransport)) { $this->currentTransport = parent::getNextTransport($message); } return $this->currentTransport; } protected function getInitialCursor(): int { return 0; } protected function getNameSymbol(): string { return '||'; } } Transport/NullTransport.php 0000644 00000003240 15120140573 0012075 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Component\Notifier\Event\MessageEvent; use Symfony\Component\Notifier\Event\SentMessageEvent; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\NullMessage; use Symfony\Component\Notifier\Message\SentMessage; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ class NullTransport implements TransportInterface { private $dispatcher; public function __construct(EventDispatcherInterface $dispatcher = null) { $this->dispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($dispatcher) : $dispatcher; } public function send(MessageInterface $message): SentMessage { $message = new NullMessage($message); $sentMessage = new SentMessage($message, (string) $this); if (null === $this->dispatcher) { return $sentMessage; } $this->dispatcher->dispatch(new MessageEvent($message)); $this->dispatcher->dispatch(new SentMessageEvent($sentMessage)); return $sentMessage; } public function __toString(): string { return 'null'; } public function supports(MessageInterface $message): bool { return true; } } Transport/NullTransportFactory.php 0000644 00000001572 15120140573 0013433 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; /** * @author Fabien Potencier <fabien@symfony.com> */ final class NullTransportFactory extends AbstractTransportFactory { /** * @return NullTransport */ public function create(Dsn $dsn): TransportInterface { if ('null' === $dsn->getScheme()) { return new NullTransport($this->dispatcher); } throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes()); } protected function getSupportedSchemes(): array { return ['null']; } } Transport/RoundRobinTransport.php 0000644 00000007732 15120140573 0013256 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Exception\RuntimeException; use Symfony\Component\Notifier\Exception\TransportExceptionInterface; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; /** * Uses several Transports using a round robin algorithm. * * @author Fabien Potencier <fabien@symfony.com> */ class RoundRobinTransport implements TransportInterface { /** * @var \SplObjectStorage<TransportInterface, float> */ private $deadTransports; private $transports = []; private $retryPeriod; private $cursor = -1; /** * @param TransportInterface[] $transports */ public function __construct(array $transports, int $retryPeriod = 60) { if (!$transports) { throw new LogicException(sprintf('"%s" must have at least one transport configured.', static::class)); } $this->transports = $transports; $this->deadTransports = new \SplObjectStorage(); $this->retryPeriod = $retryPeriod; } public function __toString(): string { return implode(' '.$this->getNameSymbol().' ', array_map('strval', $this->transports)); } public function supports(MessageInterface $message): bool { foreach ($this->transports as $transport) { if ($transport->supports($message)) { return true; } } return false; } public function send(MessageInterface $message): SentMessage { if (!$this->supports($message)) { throw new LogicException(sprintf('None of the configured Transports of "%s" supports the given message.', static::class)); } while ($transport = $this->getNextTransport($message)) { try { return $transport->send($message); } catch (TransportExceptionInterface $e) { $this->deadTransports[$transport] = microtime(true); } } throw new RuntimeException('All transports failed.'); } /** * Rotates the transport list around and returns the first instance. */ protected function getNextTransport(MessageInterface $message): ?TransportInterface { if (-1 === $this->cursor) { $this->cursor = $this->getInitialCursor(); } $cursor = $this->cursor; while (true) { $transport = $this->transports[$cursor]; if (!$transport->supports($message)) { $cursor = $this->moveCursor($cursor); continue; } if (!$this->isTransportDead($transport)) { break; } if ((microtime(true) - $this->deadTransports[$transport]) > $this->retryPeriod) { $this->deadTransports->detach($transport); break; } if ($this->cursor === $cursor = $this->moveCursor($cursor)) { return null; } } $this->cursor = $this->moveCursor($cursor); return $transport; } protected function isTransportDead(TransportInterface $transport): bool { return $this->deadTransports->contains($transport); } protected function getInitialCursor(): int { // the cursor initial value is randomized so that // when are not in a daemon, we are still rotating the transports return mt_rand(0, \count($this->transports) - 1); } protected function getNameSymbol(): string { return '&&'; } private function moveCursor(int $cursor): int { return ++$cursor >= \count($this->transports) ? 0 : $cursor; } } Transport/TransportFactoryInterface.php 0000644 00000001514 15120140573 0014415 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Exception\IncompleteDsnException; use Symfony\Component\Notifier\Exception\MissingRequiredOptionException; use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; /** * @author Konstantin Myakshin <molodchick@gmail.com> */ interface TransportFactoryInterface { /** * @throws UnsupportedSchemeException * @throws IncompleteDsnException * @throws MissingRequiredOptionException */ public function create(Dsn $dsn): TransportInterface; public function supports(Dsn $dsn): bool; } Transport/TransportInterface.php 0000644 00000001426 15120140573 0013067 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Exception\TransportExceptionInterface; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ interface TransportInterface { /** * @throws TransportExceptionInterface */ public function send(MessageInterface $message): ?SentMessage; public function supports(MessageInterface $message): bool; public function __toString(): string; } Transport/Transports.php 0000644 00000004472 15120140573 0011435 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier\Transport; use Symfony\Component\Notifier\Exception\InvalidArgumentException; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; /** * @author Fabien Potencier <fabien@symfony.com> */ final class Transports implements TransportInterface { private $transports; /** * @param TransportInterface[] $transports */ public function __construct(iterable $transports) { $this->transports = []; foreach ($transports as $name => $transport) { $this->transports[$name] = $transport; } } public function __toString(): string { return '['.implode(',', array_keys($this->transports)).']'; } public function supports(MessageInterface $message): bool { foreach ($this->transports as $transport) { if ($transport->supports($message)) { return true; } } return false; } public function send(MessageInterface $message): SentMessage { if (!$transport = $message->getTransport()) { foreach ($this->transports as $transportName => $transport) { if ($transport->supports($message)) { return $transport->send($message); } } throw new LogicException(sprintf('None of the available transports support the given message (available transports: "%s").', implode('", "', array_keys($this->transports)))); } if (!isset($this->transports[$transport])) { throw new InvalidArgumentException(sprintf('The "%s" transport does not exist (available transports: "%s").', $transport, implode('", "', array_keys($this->transports)))); } if (!$this->transports[$transport]->supports($message)) { throw new LogicException(sprintf('The "%s" transport does not support the given message.', $transport)); } return $this->transports[$transport]->send($message); } } CHANGELOG.md 0000644 00000004602 15120140573 0006355 0 ustar 00 CHANGELOG ========= 5.4.21 ------ * [BC BREAK] The following data providers for `TransportTestCase` are now static: `toStringProvider()`, `supportedMessagesProvider()` and `unsupportedMessagesProvider()` * [BC BREAK] `TransportTestCase::createTransport()` is now static 5.4 --- * Add `SentMessageEvent` and `FailedMessageEvent` * Add `push` channel 5.3 --- * The component is not marked as `@experimental` anymore * [BC BREAK] Change signature of `Dsn::__construct()` method from: `public function __construct(string $scheme, string $host, ?string $user = null, ?string $password = null, ?int $port = null, array $options = [], ?string $path = null)` to: `public function __construct(string $dsn)` * [BC BREAK] Remove `Dsn::fromString()` method * [BC BREAK] Changed the return type of `AbstractTransportFactory::getEndpoint()` from `?string` to `string` * Added `DSN::getRequiredOption` method which throws a new `MissingRequiredOptionException`. 5.2.0 ----- * [BC BREAK] The `TransportInterface::send()` and `AbstractTransport::doSend()` methods changed to return a `?SentMessage` instance instead of `void`. * The `EmailRecipientInterface` and `RecipientInterface` were introduced. * Added `email` and `phone` properties to `Recipient`. * [BC BREAK] Changed the type-hint of the `$recipient` argument in the `as*Message()` method of `EmailNotificationInterface` and `SmsNotificationInterface` to `EmailRecipientInterface` and `SmsRecipientInterface`. * [BC BREAK] Removed the `AdminRecipient`. * The `EmailRecipientInterface` and `SmsRecipientInterface` now extend the `RecipientInterface`. * The `EmailRecipient` and `SmsRecipient` were introduced. * [BC BREAK] Changed the type-hint of the `$recipient` argument in `NotifierInterface::send()`, `Notifier::getChannels()`, `ChannelInterface::notifiy()` and `ChannelInterface::supports()` to `RecipientInterface`. * Changed `EmailChannel` to only support recipients which implement the `EmailRecipientInterface`. * Changed `SmsChannel` to only support recipients which implement the `SmsRecipientInterface`. 5.1.0 ----- * [BC BREAK] The `ChatMessage::fromNotification()` method's `$recipient` and `$transport` arguments were removed. * [BC BREAK] The `EmailMessage::fromNotification()` and `SmsMessage::fromNotification()` methods' `$transport` argument was removed. 5.0.0 ----- * Introduced the component as experimental Chatter.php 0000644 00000003432 15120140573 0006647 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Notifier\Event\MessageEvent; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; use Symfony\Component\Notifier\Transport\TransportInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class Chatter implements ChatterInterface { private $transport; private $bus; private $dispatcher; public function __construct(TransportInterface $transport, MessageBusInterface $bus = null, EventDispatcherInterface $dispatcher = null) { $this->transport = $transport; $this->bus = $bus; $this->dispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($dispatcher) : $dispatcher; } public function __toString(): string { return 'chat'; } public function supports(MessageInterface $message): bool { return $this->transport->supports($message); } public function send(MessageInterface $message): ?SentMessage { if (null === $this->bus) { return $this->transport->send($message); } if (null !== $this->dispatcher) { $this->dispatcher->dispatch(new MessageEvent($message, true)); } $this->bus->dispatch($message); return null; } } ChatterInterface.php 0000644 00000001036 15120140573 0010466 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Symfony\Component\Notifier\Transport\TransportInterface; /** * Interface for classes able to send chat messages synchronous and/or asynchronous. * * @author Fabien Potencier <fabien@symfony.com> */ interface ChatterInterface extends TransportInterface { } LICENSE 0000644 00000002054 15120140573 0005550 0 ustar 00 Copyright (c) 2019-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Notifier.php 0000644 00000007745 15120140573 0007047 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Psr\Container\ContainerInterface; use Symfony\Component\Notifier\Channel\ChannelInterface; use Symfony\Component\Notifier\Channel\ChannelPolicy; use Symfony\Component\Notifier\Channel\ChannelPolicyInterface; use Symfony\Component\Notifier\Channel\SmsChannel; use Symfony\Component\Notifier\Exception\LogicException; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\NoRecipient; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class Notifier implements NotifierInterface { private $adminRecipients = []; private $channels; private $policy; /** * @param ChannelInterface[]|ContainerInterface $channels */ public function __construct($channels, ChannelPolicyInterface $policy = null) { $this->channels = $channels; $this->policy = $policy; } public function send(Notification $notification, RecipientInterface ...$recipients): void { if (!$recipients) { $recipients = [new NoRecipient()]; } foreach ($recipients as $recipient) { foreach ($this->getChannels($notification, $recipient) as $channel => $transportName) { $channel->notify($notification, $recipient, $transportName); } } } public function addAdminRecipient(RecipientInterface $recipient): void { $this->adminRecipients[] = $recipient; } /** * @return RecipientInterface[] */ public function getAdminRecipients(): array { return $this->adminRecipients; } private function getChannels(Notification $notification, RecipientInterface $recipient): iterable { $channels = $notification->getChannels($recipient); if (!$channels) { $errorPrefix = sprintf('Unable to determine which channels to use to send the "%s" notification', \get_class($notification)); $error = 'you should either pass channels in the constructor, override its "getChannels()" method'; if (null === $this->policy) { throw new LogicException(sprintf('%s; %s, or configure a "%s".', $errorPrefix, $error, ChannelPolicy::class)); } if (!$channels = $this->policy->getChannels($notification->getImportance())) { throw new LogicException(sprintf('%s; the "%s" returns no channels for importance "%s"; %s.', $errorPrefix, ChannelPolicy::class, $notification->getImportance(), $error)); } } foreach ($channels as $channelName) { $transportName = null; if (false !== $pos = strpos($channelName, '/')) { $transportName = substr($channelName, $pos + 1); $channelName = substr($channelName, 0, $pos); } if (null === $channel = $this->getChannel($channelName)) { throw new LogicException(sprintf('The "%s" channel does not exist.', $channelName)); } if ($channel instanceof SmsChannel && $recipient instanceof NoRecipient) { throw new LogicException(sprintf('The "%s" channel needs a Recipient.', $channelName)); } if (!$channel->supports($notification, $recipient)) { throw new LogicException(sprintf('The "%s" channel is not supported.', $channelName)); } yield $channel => $transportName; } } private function getChannel(string $name): ?ChannelInterface { if ($this->channels instanceof ContainerInterface) { return $this->channels->has($name) ? $this->channels->get($name) : null; } return $this->channels[$name] ?? null; } } NotifierInterface.php 0000644 00000001156 15120140573 0010656 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Recipient\RecipientInterface; /** * Interface for the Notifier system. * * @author Fabien Potencier <fabien@symfony.com> */ interface NotifierInterface { public function send(Notification $notification, RecipientInterface ...$recipients): void; } README.md 0000644 00000002125 15120140573 0006021 0 ustar 00 Notifier Component ================== The Notifier component sends notifications via one or more channels (email, SMS, ...). Sponsor ------- The Notifier component for Symfony 5.4/6.0 is [backed][1] by [Mercure.rocks][2]. Create real-time experiences in minutes! Mercure.rocks provides a realtime API service that is tightly integrated with Symfony: create UIs that update in live with UX Turbo, send notifications with the Notifier component, expose async APIs with API Platform and create low level stuffs with the Mercure component. We maintain and scale the complex infrastructure for you! Help Symfony by [sponsoring][3] its development! Resources --------- * [Documentation](https://symfony.com/doc/current/notifier.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) [1]: https://symfony.com/backers [2]: https://mercure.rocks [3]: https://symfony.com/sponsor Texter.php 0000644 00000003432 15120140573 0006530 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Notifier\Event\MessageEvent; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Message\SentMessage; use Symfony\Component\Notifier\Transport\TransportInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * @author Fabien Potencier <fabien@symfony.com> */ final class Texter implements TexterInterface { private $transport; private $bus; private $dispatcher; public function __construct(TransportInterface $transport, MessageBusInterface $bus = null, EventDispatcherInterface $dispatcher = null) { $this->transport = $transport; $this->bus = $bus; $this->dispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($dispatcher) : $dispatcher; } public function __toString(): string { return 'texter'; } public function supports(MessageInterface $message): bool { return $this->transport->supports($message); } public function send(MessageInterface $message): ?SentMessage { if (null === $this->bus) { return $this->transport->send($message); } if (null !== $this->dispatcher) { $this->dispatcher->dispatch(new MessageEvent($message, true)); } $this->bus->dispatch($message); return null; } } TexterInterface.php 0000644 00000001034 15120140573 0010345 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Symfony\Component\Notifier\Transport\TransportInterface; /** * Interface for classes able to send SMS messages synchronous and/or asynchronous. * * @author Fabien Potencier <fabien@symfony.com> */ interface TexterInterface extends TransportInterface { } Transport.php 0000644 00000017106 15120140573 0007254 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Notifier; use Symfony\Component\Notifier\Bridge\AllMySms\AllMySmsTransportFactory; use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory; use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory; use Symfony\Component\Notifier\Bridge\Discord\DiscordTransportFactory; use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory; use Symfony\Component\Notifier\Bridge\Expo\ExpoTransportFactory; use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory; use Symfony\Component\Notifier\Bridge\FreeMobile\FreeMobileTransportFactory; use Symfony\Component\Notifier\Bridge\GatewayApi\GatewayApiTransportFactory; use Symfony\Component\Notifier\Bridge\Gitter\GitterTransportFactory; use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory; use Symfony\Component\Notifier\Bridge\Iqsms\IqsmsTransportFactory; use Symfony\Component\Notifier\Bridge\LightSms\LightSmsTransportFactory; use Symfony\Component\Notifier\Bridge\Mailjet\MailjetTransportFactory; use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransportFactory; use Symfony\Component\Notifier\Bridge\MessageBird\MessageBirdTransportFactory; use Symfony\Component\Notifier\Bridge\MessageMedia\MessageMediaTransportFactory; use Symfony\Component\Notifier\Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory; use Symfony\Component\Notifier\Bridge\Mobyt\MobytTransportFactory; use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; use Symfony\Component\Notifier\Bridge\Octopush\OctopushTransportFactory; use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory; use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; use Symfony\Component\Notifier\Bridge\Sms77\Sms77TransportFactory; use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory; use Symfony\Component\Notifier\Bridge\SmsBiuras\SmsBiurasTransportFactory; use Symfony\Component\Notifier\Bridge\Smsc\SmscTransportFactory; use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; use Symfony\Component\Notifier\Bridge\Telnyx\TelnyxTransportFactory; use Symfony\Component\Notifier\Bridge\TurboSms\TurboSmsTransportFactory; use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; use Symfony\Component\Notifier\Bridge\Vonage\VonageTransportFactory; use Symfony\Component\Notifier\Bridge\Yunpian\YunpianTransportFactory; use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; use Symfony\Component\Notifier\Transport\Dsn; use Symfony\Component\Notifier\Transport\FailoverTransport; use Symfony\Component\Notifier\Transport\NullTransportFactory; use Symfony\Component\Notifier\Transport\RoundRobinTransport; use Symfony\Component\Notifier\Transport\TransportFactoryInterface; use Symfony\Component\Notifier\Transport\TransportInterface; use Symfony\Component\Notifier\Transport\Transports; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * @author Fabien Potencier <fabien@symfony.com> * * @final since Symfony 5.4 */ class Transport { private const FACTORY_CLASSES = [ AllMySmsTransportFactory::class, AmazonSnsTransportFactory::class, ClickatellTransportFactory::class, DiscordTransportFactory::class, EsendexTransportFactory::class, ExpoTransportFactory::class, FirebaseTransportFactory::class, FreeMobileTransportFactory::class, GatewayApiTransportFactory::class, GitterTransportFactory::class, InfobipTransportFactory::class, IqsmsTransportFactory::class, LightSmsTransportFactory::class, MailjetTransportFactory::class, MattermostTransportFactory::class, MessageBirdTransportFactory::class, MessageMediaTransportFactory::class, MicrosoftTeamsTransportFactory::class, MobytTransportFactory::class, NexmoTransportFactory::class, OctopushTransportFactory::class, OvhCloudTransportFactory::class, RocketChatTransportFactory::class, SendinblueTransportFactory::class, SinchTransportFactory::class, SlackTransportFactory::class, Sms77TransportFactory::class, SmsapiTransportFactory::class, SmsBiurasTransportFactory::class, SmscTransportFactory::class, TelegramTransportFactory::class, TelnyxTransportFactory::class, TurboSmsTransportFactory::class, TwilioTransportFactory::class, VonageTransportFactory::class, YunpianTransportFactory::class, ZulipTransportFactory::class, ]; private $factories; public static function fromDsn(string $dsn, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null): TransportInterface { $factory = new self(self::getDefaultFactories($dispatcher, $client)); return $factory->fromString($dsn); } public static function fromDsns(array $dsns, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null): TransportInterface { $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client))); return $factory->fromStrings($dsns); } /** * @param TransportFactoryInterface[] $factories */ public function __construct(iterable $factories) { $this->factories = $factories; } public function fromStrings(array $dsns): Transports { $transports = []; foreach ($dsns as $name => $dsn) { $transports[$name] = $this->fromString($dsn); } return new Transports($transports); } public function fromString(string $dsn): TransportInterface { $dsns = preg_split('/\s++\|\|\s++/', $dsn); if (\count($dsns) > 1) { return new FailoverTransport($this->createFromDsns($dsns)); } $dsns = preg_split('/\s++&&\s++/', $dsn); if (\count($dsns) > 1) { return new RoundRobinTransport($this->createFromDsns($dsns)); } return $this->fromDsnObject(new Dsn($dsn)); } public function fromDsnObject(Dsn $dsn): TransportInterface { foreach ($this->factories as $factory) { if ($factory->supports($dsn)) { return $factory->create($dsn); } } throw new UnsupportedSchemeException($dsn); } /** * @return TransportInterface[] */ private function createFromDsns(array $dsns): array { $transports = []; foreach ($dsns as $dsn) { $transports[] = $this->fromDsnObject(new Dsn($dsn)); } return $transports; } /** * @return TransportFactoryInterface[] */ private static function getDefaultFactories(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null): iterable { foreach (self::FACTORY_CLASSES as $factoryClass) { if (class_exists($factoryClass)) { yield new $factoryClass($dispatcher, $client); } } yield new NullTransportFactory($dispatcher, $client); } } composer.json 0000644 00000003617 15120140573 0007273 0 ustar 00 { "name": "symfony/notifier", "type": "library", "description": "Sends notifications via one or more channels (email, SMS, ...)", "keywords": ["notifier", "notification"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/polyfill-php80": "^1.15", "psr/log": "^1|^2|^3" }, "require-dev": { "symfony/event-dispatcher-contracts": "^2|^3", "symfony/http-client-contracts": "^2|^3", "symfony/messenger": "^4.4|^5.0|^6.0" }, "conflict": { "symfony/http-kernel": "<4.4", "symfony/discord-notifier": "<5.3", "symfony/esendex-notifier": "<5.3", "symfony/firebase-notifier": "<5.3", "symfony/free-mobile-notifier": "<5.3", "symfony/google-chat-notifier": "<5.3", "symfony/infobip-notifier": "<5.3", "symfony/linked-in-notifier": "<5.3", "symfony/mattermost-notifier": "<5.3", "symfony/mobyt-notifier": "<5.3", "symfony/nexmo-notifier": "<5.3", "symfony/ovh-cloud-notifier": "<5.3", "symfony/rocket-chat-notifier": "<5.3", "symfony/sendinblue-notifier": "<5.3", "symfony/sinch-notifier": "<5.3", "symfony/slack-notifier": "<5.3", "symfony/sms77-notifier": "<5.3", "symfony/smsapi-notifier": "<5.3", "symfony/telegram-notifier": "<5.3", "symfony/twilio-notifier": "<5.3", "symfony/zulip-notifier": "<5.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" }
Coded With 💗 by
0x6ick