diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 578e83bf1a401..41cca1fef4ac6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -93,6 +93,7 @@ use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory; use Symfony\Component\Notifier\Bridge\FreeMobile\FreeMobileTransportFactory; +use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory; use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransportFactory; use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; @@ -2043,6 +2044,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ MattermostTransportFactory::class => 'notifier.transport_factory.mattermost', NexmoTransportFactory::class => 'notifier.transport_factory.nexmo', RocketChatTransportFactory::class => 'notifier.transport_factory.rocketchat', + InfobipTransportFactory::class => 'notifier.transport_factory.infobip', TwilioTransportFactory::class => 'notifier.transport_factory.twilio', FirebaseTransportFactory::class => 'notifier.transport_factory.firebase', FreeMobileTransportFactory::class => 'notifier.transport_factory.freemobile', diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.xml index 045eb52a1b96e..b34e58074238b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.xml @@ -34,6 +34,10 @@ + + + + diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/.gitattributes b/src/Symfony/Component/Notifier/Bridge/Infobip/.gitattributes new file mode 100644 index 0000000000000..ebb9287043dc4 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/CHANGELOG.md b/src/Symfony/Component/Notifier/Bridge/Infobip/CHANGELOG.md new file mode 100644 index 0000000000000..10f7e1ea8506e --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +5.0.0 +----- + + * Added the bridge diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/InfobipTransport.php b/src/Symfony/Component/Notifier/Bridge/Infobip/InfobipTransport.php new file mode 100644 index 0000000000000..a4f7a21cf4404 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/InfobipTransport.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Infobip; + +use Symfony\Component\Notifier\Exception\LogicException; +use Symfony\Component\Notifier\Exception\TransportException; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\SmsMessage; +use Symfony\Component\Notifier\Transport\AbstractTransport; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Fabien Potencier + * @author Jérémy Romey + * + * @experimental in 5.0 + */ +final class InfobipTransport extends AbstractTransport +{ + protected const HOST = 'jgpe9.api.infobip.com'; + + private $username; + private $password; + private $from; + + public function __construct(string $username, string $password, string $from, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null) + { + $this->username = $username; + $this->password = $password; + $this->from = $from; + + parent::__construct($client, $dispatcher); + } + + public function __toString(): string + { + return \sprintf('infobip://%s?from=%s', $this->getEndpoint(), $this->from); + } + + public function supports(MessageInterface $message): bool + { + return $message instanceof SmsMessage; + } + + protected function doSend(MessageInterface $message): void + { + 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/2/text/advanced', $this->getEndpoint()); + + $response = $this->client->request('POST', $endpoint, [ + 'auth_basic' => $this->username.':'.$this->password, + 'json' => [ + 'messages' => [ + [ + 'from' => $this->from, + 'destinations' => [ + [ + 'to' => $message->getPhone(), + ], + ], + 'text' => $message->getSubject(), + ], + ], + ], + ]); + + if (201 !== $response->getStatusCode()) { + $error = $response->toArray(false); + + throw new TransportException(\sprintf('Unable to send the SMS: '.$error['message'].' (see %s).', $error['more_info']), $response); + } + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/InfobipTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/Infobip/InfobipTransportFactory.php new file mode 100644 index 0000000000000..a620b8ba2d654 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/InfobipTransportFactory.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Infobip; + +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 Fabien Potencier + * @author Jérémy Romey + * + * @experimental in 5.0 + */ +final class InfobipTransportFactory extends AbstractTransportFactory +{ + /** + * @return InfobipTransport + */ + public function create(Dsn $dsn): TransportInterface + { + $scheme = $dsn->getScheme(); + $username = $this->getUser($dsn); + $password = $this->getPassword($dsn); + $from = $dsn->getOption('from'); + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $port = $dsn->getPort(); + + if ('infobip' === $scheme) { + return (new InfobipTransport($username, $password, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port); + } + + throw new UnsupportedSchemeException($dsn, 'infobip', $this->getSupportedSchemes()); + } + + protected function getSupportedSchemes(): array + { + return ['infobip']; + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE b/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE new file mode 100644 index 0000000000000..4bf0fef4ff3b0 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019-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/Infobip/README.md b/src/Symfony/Component/Notifier/Bridge/Infobip/README.md new file mode 100644 index 0000000000000..210440ed3de4d --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/README.md @@ -0,0 +1,12 @@ +Infobip Notifier +=============== + +Provides Infobip integration for Symfony Notifier. + +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/Infobip/composer.json b/src/Symfony/Component/Notifier/Bridge/Infobip/composer.json new file mode 100644 index 0000000000000..2d99bad3ed15c --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/composer.json @@ -0,0 +1,39 @@ +{ + "name": "symfony/infobip-notifier", + "type": "symfony-bridge", + "description": "Symfony Infobip Notifier Bridge", + "keywords": ["sms", "infobip", "notifier"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jérémy Romey", + "email": "jeremy@free-agent.fr" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/http-client": "^4.3|^5.0", + "symfony/notifier": "^5.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Infobip\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/phpunit.xml.dist b/src/Symfony/Component/Notifier/Bridge/Infobip/phpunit.xml.dist new file mode 100644 index 0000000000000..09783ef58cdfb --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/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 0d45a7d065863..53ea51b5792be 100644 --- a/src/Symfony/Component/Notifier/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Notifier/Exception/UnsupportedSchemeException.php @@ -46,6 +46,10 @@ class UnsupportedSchemeException extends LogicException 'class' => Bridge\Twilio\TwilioTransportFactory::class, 'package' => 'symfony/twilio-notifier', ], + 'infobip' => [ + 'class' => Bridge\Infobip\InfobipTransportFactory::class, + 'package' => 'symfony/infobip-notifier', + ], 'firebase' => [ 'class' => Bridge\Firebase\FirebaseTransportFactory::class, 'package' => 'symfony/firebase-notifier', diff --git a/src/Symfony/Component/Notifier/Transport.php b/src/Symfony/Component/Notifier/Transport.php index 1e7d8dcd9afd8..25086e14e6052 100644 --- a/src/Symfony/Component/Notifier/Transport.php +++ b/src/Symfony/Component/Notifier/Transport.php @@ -13,6 +13,7 @@ use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory; use Symfony\Component\Notifier\Bridge\FreeMobile\FreeMobileTransportFactory; +use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory; use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransportFactory; use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; @@ -46,6 +47,7 @@ class Transport NexmoTransportFactory::class, RocketChatTransportFactory::class, TwilioTransportFactory::class, + InfobipTransportFactory::class, OvhCloudTransportFactory::class, FirebaseTransportFactory::class, SinchTransportFactory::class,