feature #39948 [Notifier] [SpotHit] Add the bridge (JamesHemery)
This PR was squashed before being merged into the 5.3-dev branch.
Discussion
----------
[Notifier] [SpotHit] Add the bridge
| Q | A
| ------------- | ---
| Branch? | 5.x
| Bug fix? | no
| New feature? | yes
| Deprecations? | no
| License | MIT
| Doc PR | symfony/symfony-docs#14869
| Recipe PR | symfony/recipes#881
@OskarStark Bridge added :)
Commits
-------
afcca88af2
[Notifier] [SpotHit] Add the bridge
This commit is contained in:
commit
3eb8a42036
@ -126,6 +126,7 @@ use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory as S
|
||||
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\SpotHit\SpotHitTransportFactory;
|
||||
use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory;
|
||||
use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory;
|
||||
use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory;
|
||||
@ -2236,6 +2237,7 @@ class FrameworkExtension extends Extension
|
||||
AllMySmsTransportFactory::class => 'notifier.transport_factory.allmysms',
|
||||
FirebaseTransportFactory::class => 'notifier.transport_factory.firebase',
|
||||
FreeMobileTransportFactory::class => 'notifier.transport_factory.freemobile',
|
||||
SpotHitTransportFactory::class => 'notifier.transport_factory.spothit',
|
||||
OvhCloudTransportFactory::class => 'notifier.transport_factory.ovhcloud',
|
||||
SinchTransportFactory::class => 'notifier.transport_factory.sinch',
|
||||
ZulipTransportFactory::class => 'notifier.transport_factory.zulip',
|
||||
|
@ -34,6 +34,7 @@ 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\Smsapi\SmsapiTransportFactory;
|
||||
use Symfony\Component\Notifier\Bridge\SpotHit\SpotHitTransportFactory;
|
||||
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 @@ return static function (ContainerConfigurator $container) {
|
||||
->parent('notifier.transport_factory.abstract')
|
||||
->tag('texter.transport_factory')
|
||||
|
||||
->set('notifier.transport_factory.spothit', SpotHitTransportFactory::class)
|
||||
->parent('notifier.transport_factory.abstract')
|
||||
->tag('texter.transport_factory')
|
||||
|
||||
->set('notifier.transport_factory.ovhcloud', OvhCloudTransportFactory::class)
|
||||
->parent('notifier.transport_factory.abstract')
|
||||
->tag('texter.transport_factory')
|
||||
|
@ -0,0 +1,7 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Add the bridge
|
23
src/Symfony/Component/Notifier/Bridge/SpotHit/README.md
Normal file
23
src/Symfony/Component/Notifier/Bridge/SpotHit/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
Spot-Hit Notifier
|
||||
=================
|
||||
|
||||
Provides [Spot-Hit](https://www.spot-hit.fr/) integration for Symfony Notifier.
|
||||
|
||||
#### DSN example
|
||||
|
||||
```
|
||||
SPOTHIT_DSN=spothit://TOKEN@default?from=FROM
|
||||
```
|
||||
|
||||
where:
|
||||
- `TOKEN` is your Spot-Hit API key
|
||||
- `FROM` is the custom sender (3-11 letters, default is a 5 digits phone number)
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Spot-Hit API doc](https://www.spot-hit.fr/documentation-api).
|
||||
* [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)
|
@ -0,0 +1,96 @@
|
||||
<?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\Bridge\SpotHit;
|
||||
|
||||
use Symfony\Component\Notifier\Exception\TransportException;
|
||||
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
|
||||
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\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
/**
|
||||
* @author James Hemery <james@yieldstudio.fr>
|
||||
*/
|
||||
final class SpotHitTransport extends AbstractTransport
|
||||
{
|
||||
protected const HOST = 'spot-hit.fr';
|
||||
|
||||
private $token;
|
||||
private $from;
|
||||
|
||||
public function __construct(string $token, ?string $from = null, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
$this->token = $token;
|
||||
$this->from = $from;
|
||||
|
||||
parent::__construct($client, $dispatcher);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
if (!$this->from) {
|
||||
return sprintf('spothit://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
return sprintf('spothit://%s?from=%s', $this->getEndpoint(), $this->from);
|
||||
}
|
||||
|
||||
public function supports(MessageInterface $message): bool
|
||||
{
|
||||
return $message instanceof SmsMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MessageInterface|SmsMessage $message
|
||||
*
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
protected function doSend(MessageInterface $message): SentMessage
|
||||
{
|
||||
if (!$this->supports($message)) {
|
||||
throw new UnsupportedMessageTypeException(__CLASS__, SmsMessage::class, $message);
|
||||
}
|
||||
|
||||
$endpoint = sprintf('https://www.%s/api/envoyer/sms', $this->getEndpoint());
|
||||
$response = $this->client->request('POST', $endpoint, [
|
||||
'body' => [
|
||||
'key' => $this->token,
|
||||
'destinataires' => $message->getPhone(),
|
||||
'type' => 'premium',
|
||||
'message' => $message->getSubject(),
|
||||
'expediteur' => $this->from,
|
||||
],
|
||||
]);
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
|
||||
if (!$data['resultat']) {
|
||||
$errors = \is_array($data['erreurs']) ? implode(',', $data['erreurs']) : $data['erreurs'];
|
||||
throw new TransportException(sprintf('[HTTP %d] Unable to send the SMS: error(s) "%s".', $response->getStatusCode(), $errors), $response);
|
||||
}
|
||||
|
||||
$sentMessage = new SentMessage($message, (string) $this);
|
||||
$sentMessage->setMessageId($data['id']);
|
||||
|
||||
return $sentMessage;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?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\Bridge\SpotHit;
|
||||
|
||||
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 James Hemery <james@yieldstudio.fr>
|
||||
*/
|
||||
final class SpotHitTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
/**
|
||||
* @return SpotHitTransport
|
||||
*/
|
||||
public function create(Dsn $dsn): TransportInterface
|
||||
{
|
||||
$scheme = $dsn->getScheme();
|
||||
|
||||
if ('spothit' !== $scheme) {
|
||||
throw new UnsupportedSchemeException($dsn, 'spothit', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
$token = $this->getUser($dsn);
|
||||
$from = $dsn->getOption('from');
|
||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||
$port = $dsn->getPort();
|
||||
|
||||
return (new SpotHitTransport($token, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return ['spothit'];
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
<?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\Bridge\SpotHit\Tests;
|
||||
|
||||
use Symfony\Component\Notifier\Bridge\SpotHit\SpotHitTransportFactory;
|
||||
use Symfony\Component\Notifier\Tests\TransportFactoryTestCase;
|
||||
use Symfony\Component\Notifier\Transport\TransportFactoryInterface;
|
||||
|
||||
final class SpotHitTransportFactoryTest extends TransportFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @return SpotHitTransportFactory
|
||||
*/
|
||||
public function createFactory(): TransportFactoryInterface
|
||||
{
|
||||
return new SpotHitTransportFactory();
|
||||
}
|
||||
|
||||
public function createProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
'spothit://spot-hit.fr',
|
||||
'spothit://api_token@default',
|
||||
];
|
||||
yield [
|
||||
'spothit://spot-hit.fr?from=MyCompany',
|
||||
'spothit://api_token@default?from=MyCompany',
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [true, 'spothit://api_token@default?from=MyCompany'];
|
||||
yield [false, 'somethingElse://api_token@default?from=MyCompany'];
|
||||
}
|
||||
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield ['foobar://api_token@default?from=MyCompany'];
|
||||
yield ['foobar://api_token@default'];
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?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\Bridge\SpotHit\Tests;
|
||||
|
||||
use Symfony\Component\Notifier\Bridge\SpotHit\SpotHitTransport;
|
||||
use Symfony\Component\Notifier\Message\ChatMessage;
|
||||
use Symfony\Component\Notifier\Message\MessageInterface;
|
||||
use Symfony\Component\Notifier\Message\SmsMessage;
|
||||
use Symfony\Component\Notifier\Tests\TransportTestCase;
|
||||
use Symfony\Component\Notifier\Transport\TransportInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
final class SpotHitTransportTest extends TransportTestCase
|
||||
{
|
||||
/**
|
||||
* @return SpotHitTransport
|
||||
*/
|
||||
public function createTransport(?HttpClientInterface $client = null): TransportInterface
|
||||
{
|
||||
return (new SpotHitTransport('api_token', 'MyCompany', $client ?: $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||
}
|
||||
|
||||
public function toStringProvider(): iterable
|
||||
{
|
||||
yield ['spothit://host.test?from=MyCompany', $this->createTransport()];
|
||||
}
|
||||
|
||||
public function supportedMessagesProvider(): iterable
|
||||
{
|
||||
yield [new SmsMessage('0611223344', 'Hello!')];
|
||||
yield [new SmsMessage('+33611223344', 'Hello!')];
|
||||
}
|
||||
|
||||
public function unsupportedMessagesProvider(): iterable
|
||||
{
|
||||
yield [new ChatMessage('Hello!')];
|
||||
yield [$this->createMock(MessageInterface::class)];
|
||||
}
|
||||
}
|
34
src/Symfony/Component/Notifier/Bridge/SpotHit/composer.json
Normal file
34
src/Symfony/Component/Notifier/Bridge/SpotHit/composer.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "symfony/spothit-notifier",
|
||||
"type": "symfony-bridge",
|
||||
"description": "Symfony Spot-Hit Notifier Bridge",
|
||||
"keywords": ["sms", "spot-hit", "notifier", "symfony"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "James Hemery",
|
||||
"homepage": "https://github.com/JamesHemery"
|
||||
},
|
||||
{
|
||||
"name": "Yield Studio",
|
||||
"homepage": "https://github.com/YieldStudio"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/http-client": "^4.3|^5.1",
|
||||
"symfony/notifier": "^5.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Notifier\\Bridge\\SpotHit\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
>
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Symfony Spot-Hit Notifier Test Suite">
|
||||
<directory>./Tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./</directory>
|
||||
<exclude>
|
||||
<directory>./Resources</directory>
|
||||
<directory>./Tests</directory>
|
||||
<directory>./vendor</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
@ -68,6 +68,10 @@ class UnsupportedSchemeException extends LogicException
|
||||
'class' => Bridge\FreeMobile\FreeMobileTransportFactory::class,
|
||||
'package' => 'symfony/free-mobile-notifier',
|
||||
],
|
||||
'spothit' => [
|
||||
'class' => Bridge\SpotHit\SpotHitTransportFactory::class,
|
||||
'package' => 'symfony/spothit-notifier',
|
||||
],
|
||||
'ovhcloud' => [
|
||||
'class' => Bridge\OvhCloud\OvhCloudTransportFactory::class,
|
||||
'package' => 'symfony/ovh-cloud-notifier',
|
||||
|
Reference in New Issue
Block a user