From 91c25303f7267a81c207dd7076b7d46985ab0697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Szepczy=C5=84ski?= Date: Thu, 28 May 2020 14:59:42 +0200 Subject: [PATCH] [Notifier] add support for smsapi-notifier --- .../FrameworkExtension.php | 2 + .../Resources/config/notifier_transports.php | 5 ++ .../Notifier/Bridge/Smsapi/.gitattributes | 3 + .../Component/Notifier/Bridge/Smsapi/LICENSE | 19 +++++ .../Notifier/Bridge/Smsapi/README.md | 26 +++++++ .../Bridge/Smsapi/SmsapiTransport.php | 77 +++++++++++++++++++ .../Bridge/Smsapi/SmsapiTransportFactory.php | 47 +++++++++++ .../Notifier/Bridge/Smsapi/composer.json | 37 +++++++++ .../Notifier/Bridge/Smsapi/phpunit.xml.dist | 31 ++++++++ .../Exception/UnsupportedSchemeException.php | 4 + src/Symfony/Component/Notifier/Transport.php | 2 + 11 files changed, 253 insertions(+) create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/.gitattributes create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/README.md create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransportFactory.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/composer.json create mode 100644 src/Symfony/Component/Notifier/Bridge/Smsapi/phpunit.xml.dist diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f1abf157d86a7..e6f5f031f136a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -106,6 +106,7 @@ use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; +use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory; use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; @@ -2104,6 +2105,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ SinchTransportFactory::class => 'notifier.transport_factory.sinch', ZulipTransportFactory::class => 'notifier.transport_factory.zulip', MobytTransportFactory::class => 'notifier.transport_factory.mobyt', + SmsapiTransportFactory::class => 'notifier.transport_factory.smsapi', ]; foreach ($classToServices as $class => $service) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php index 222dec83ac1a9..397631f757f9a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php @@ -22,6 +22,7 @@ use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; +use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory; use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; @@ -90,6 +91,10 @@ ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') + ->set('notifier.transport_factory.smsapi', SmsapiTransportFactory::class) + ->parent('notifier.transport_factory.abstract') + ->tag('texter.transport_factory') + ->set('notifier.transport_factory.null', NullTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('chatter.transport_factory') diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/.gitattributes b/src/Symfony/Component/Notifier/Bridge/Smsapi/.gitattributes new file mode 100644 index 0000000000000..ebb9287043dc4 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE b/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE new file mode 100644 index 0000000000000..5593b1d84f74a --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 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. diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/README.md b/src/Symfony/Component/Notifier/Bridge/Smsapi/README.md new file mode 100644 index 0000000000000..804ad6c399793 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/README.md @@ -0,0 +1,26 @@ +SMSAPI Notifier +=============== + +Provides Smsapi integration for Symfony Notifier. + +DSN example +----------- + +``` +// .env file +SMSAPI_DSN=smsapi://TOKEN@default?from=FROM +``` + +where: + - `TOKEN` is API Token (OAuth) + - `FROM` is sender name + +See your account info at https://ssl.smsapi.pl/ + +Resources +--------- + + * [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) diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php b/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php new file mode 100644 index 0000000000000..83c3b1aaabeb6 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Smsapi; + +use Symfony\Component\Notifier\Exception\LogicException; +use Symfony\Component\Notifier\Exception\TransportException; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\SentMessage; +use Symfony\Component\Notifier\Message\SmsMessage; +use Symfony\Component\Notifier\Transport\AbstractTransport; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Marcin Szepczynski + * @experimental in 5.2 + */ +final class SmsapiTransport extends AbstractTransport +{ + protected const HOST = 'api.smsapi.pl'; + + private $authToken; + private $from; + + public function __construct(string $authToken, string $from, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null) + { + $this->authToken = $authToken; + $this->from = $from; + + parent::__construct($client, $dispatcher); + } + + public function __toString(): string + { + return sprintf('smsapi://%s?from=%s', $this->getEndpoint(), $this->from); + } + + public function supports(MessageInterface $message): bool + { + return $message instanceof SmsMessage; + } + + protected function doSend(MessageInterface $message): SentMessage + { + if (!$message instanceof SmsMessage) { + throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, SmsMessage::class, get_debug_type($message))); + } + + $endpoint = sprintf('https://%s/sms.do', $this->getEndpoint()); + $response = $this->client->request('POST', $endpoint, [ + 'auth_bearer' => $this->authToken, + 'body' => [ + 'from' => $this->from, + 'to' => $message->getPhone(), + 'message' => $message->getSubject(), + 'format' => 'json', + ], + ]); + + if (200 !== $response->getStatusCode()) { + $error = $response->toArray(false); + + throw new TransportException(sprintf('Unable to send the SMS: "%s".', $error['message']), $response); + } + + return new SentMessage($message, (string) $this); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransportFactory.php new file mode 100644 index 0000000000000..a573dbbb133a2 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransportFactory.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Smsapi; + +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\AbstractTransportFactory; +use Symfony\Component\Notifier\Transport\Dsn; +use Symfony\Component\Notifier\Transport\TransportInterface; + +/** + * @author Marcin Szepczynski + * @experimental in 5.2 + */ +class SmsapiTransportFactory extends AbstractTransportFactory +{ + /** + * @return SmsapiTransport + */ + public function create(Dsn $dsn): TransportInterface + { + $scheme = $dsn->getScheme(); + $authToken = $dsn->getUser(); + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $from = $dsn->getOption('from'); + $port = $dsn->getPort(); + + if ('smsapi' === $scheme) { + return (new SmsapiTransport($authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port); + } + + throw new UnsupportedSchemeException($dsn, 'smsapi', $this->getSupportedSchemes()); + } + + protected function getSupportedSchemes(): array + { + return ['smsapi']; + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/composer.json b/src/Symfony/Component/Notifier/Bridge/Smsapi/composer.json new file mode 100644 index 0000000000000..3378f8f951061 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/composer.json @@ -0,0 +1,37 @@ +{ + "name": "symfony/smsapi-notifier", + "type": "symfony-bridge", + "description": "Symfony Smsapi Notifier Bridge", + "keywords": ["sms", "smsapi", "notifier"], + "homepage": "https://mvpdoers.com", + "license": "MIT", + "authors": [ + { + "name": "Marcin Szepczynski", + "email": "szepczynski@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "symfony/http-client": "^4.3|^5.0", + "symfony/notifier": "^5.2" + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Notifier\\Bridge\\Smsapi\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.2-dev" + } + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/phpunit.xml.dist b/src/Symfony/Component/Notifier/Bridge/Smsapi/phpunit.xml.dist new file mode 100644 index 0000000000000..d6c9a4d787544 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/src/Symfony/Component/Notifier/Exception/UnsupportedSchemeException.php b/src/Symfony/Component/Notifier/Exception/UnsupportedSchemeException.php index c4569430512ee..84e0f5cc7d18e 100644 --- a/src/Symfony/Component/Notifier/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Notifier/Exception/UnsupportedSchemeException.php @@ -74,6 +74,10 @@ class UnsupportedSchemeException extends LogicException 'class' => Bridge\Zulip\ZulipTransportFactory::class, 'package' => 'symfony/zulip-notifier', ], + 'smsapi' => [ + 'class' => Bridge\Smsapi\SmsapiTransportFactory::class, + 'package' => 'symfony/smsapi-notifier', + ], ]; /** diff --git a/src/Symfony/Component/Notifier/Transport.php b/src/Symfony/Component/Notifier/Transport.php index a674ec3f515fb..20726a549663a 100644 --- a/src/Symfony/Component/Notifier/Transport.php +++ b/src/Symfony/Component/Notifier/Transport.php @@ -21,6 +21,7 @@ use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; +use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory; use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; @@ -56,6 +57,7 @@ class Transport FreeMobileTransportFactory::class, ZulipTransportFactory::class, MobytTransportFactory::class, + SmsapiTransportFactory::class, ]; private $factories;