Skip to content

[Notifier] add support for gatewayapi-notifier #38685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 53 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
962b19b
[Notifier] add support for gatewayapi-notifier
PGLongo Oct 22, 2020
8de3bdd
Make GatewayAPITransportFactory final
PGLongo Oct 22, 2020
6b9eca0
Fix typo in gatewaypi
PGLongo Oct 22, 2020
86018e7
Fix typo
PGLongo Oct 22, 2020
2a4c6a8
Update README.md
PGLongo Oct 22, 2020
da125b5
Rename GatewayAPI -> GatewayApi
PGLongo Oct 23, 2020
8231389
Add GatewayApiTransportFactory tests
PGLongo Oct 23, 2020
f5a5f3b
Add GatewayApiTransportTest testSend
PGLongo Oct 23, 2020
c5dd5d8
Add GatewayApiTransportTest testSupportsSmsMessage
PGLongo Oct 23, 2020
3ec6c59
Add GatewayApiTransportTest testNotSupportsChatMessage
PGLongo Oct 23, 2020
c10d7d6
Lint code
PGLongo Oct 23, 2020
56aefa1
Fix name and email in composer.json
PGLongo Oct 30, 2020
2575ca2
[Notifier] add support for gatewayapi-notifier
PGLongo Oct 22, 2020
ef3e509
Make GatewayAPITransportFactory final
PGLongo Oct 22, 2020
10c8269
Fix typo in gatewaypi
PGLongo Oct 22, 2020
633941b
Fix typo
PGLongo Oct 22, 2020
9ce1bab
Update README.md
PGLongo Oct 22, 2020
c7f7d5f
Rename GatewayAPI -> GatewayApi
PGLongo Oct 23, 2020
622a8bf
Add GatewayApiTransportFactory tests
PGLongo Oct 23, 2020
4d9ef5c
Add GatewayApiTransportTest testSend
PGLongo Oct 23, 2020
2faa1de
Add GatewayApiTransportTest testSupportsSmsMessage
PGLongo Oct 23, 2020
fc8fba8
Add GatewayApiTransportTest testNotSupportsChatMessage
PGLongo Oct 23, 2020
0c03fa2
Lint code
PGLongo Oct 23, 2020
88d533a
Fix name and email in composer.json
PGLongo Oct 30, 2020
1010e7c
Remove extra from composer.json
PGLongo Dec 7, 2020
e2fe4fb
Update version tag in GatewayApiTransport
PGLongo Dec 7, 2020
d0e94db
Add /.gitattributes export-ignore in .gitattributes
PGLongo Dec 7, 2020
9c482dc
Update UnsupportedSchemeException
PGLongo Dec 7, 2020
716c3b6
Add required space in phpdoc
PGLongo Dec 7, 2020
628fb46
Update GatewayApiTransportFactory.php
PGLongo Dec 7, 2020
208899c
Merge branch '5.x' of https://github.com/PGLongo/symfony into 5.x
PGLongo Dec 7, 2020
48002b5
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/README.md
PGLongo Dec 10, 2020
f6e7cbe
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/README.md
PGLongo Dec 10, 2020
8c7e6d1
Update authors in composer.json
PGLongo Dec 10, 2020
3370b92
Remove :void in GatewayApiTransportTest
PGLongo Dec 10, 2020
9c084ff
Remove :void in GatewayApiTransportFactoryTest
PGLongo Dec 10, 2020
afff051
Rename initFactory to createFactory
PGLongo Dec 10, 2020
fd7144b
Remove not used createMock from getTransport
PGLongo Dec 10, 2020
0d2b491
Update .gitattributes
PGLongo Dec 10, 2020
f9bbdb7
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/composer.json
PGLongo Dec 15, 2020
9506724
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/composer.json
PGLongo Dec 15, 2020
8ae74ff
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/Tests/Gateway…
PGLongo Dec 15, 2020
0e069b2
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/Tests/Gateway…
PGLongo Dec 15, 2020
23fc6ef
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/Tests/Gateway…
PGLongo Dec 15, 2020
d41d30e
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/Tests/Gateway…
PGLongo Dec 15, 2020
09613da
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/Tests/Gateway…
PGLongo Dec 15, 2020
b8412ee
Merge remote-tracking branch 'upstream/5.x' into 5.x
PGLongo Dec 15, 2020
fe9473d
Use UnsupportedMessageTypeException instead of LogicException in Gate…
PGLongo Dec 15, 2020
139728f
Add first check if schema is supported in GatewayApiTransportFactory
PGLongo Dec 15, 2020
0a848b0
Update GatewayApiTransportFactory.php
PGLongo Dec 15, 2020
24fac37
Update src/Symfony/Component/Notifier/Bridge/GatewayApi/Tests/Gateway…
PGLongo Dec 15, 2020
7bb93b8
Update composer.json
PGLongo Dec 18, 2020
ffbd0de
Fix code style issue in GatewayApiTransport
PGLongo Dec 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory;
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\GoogleChat\GoogleChatTransportFactory;
use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory;
use Symfony\Component\Notifier\Bridge\LinkedIn\LinkedInTransportFactory;
Expand Down Expand Up @@ -2239,6 +2240,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
SendinblueNotifierTransportFactory::class => 'notifier.transport_factory.sendinblue',
DiscordTransportFactory::class => 'notifier.transport_factory.discord',
LinkedInTransportFactory::class => 'notifier.transport_factory.linkedin',
GatewayApiTransportFactory::class => 'notifier.transport_factory.gatewayapi',
];

foreach ($classToServices as $class => $service) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory;
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\GoogleChat\GoogleChatTransportFactory;
use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory;
use Symfony\Component\Notifier\Bridge\LinkedIn\LinkedInTransportFactory;
Expand Down Expand Up @@ -115,6 +116,10 @@
->parent('notifier.transport_factory.abstract')
->tag('chatter.transport_factory')

->set('notifier.transport_factory.gatewayapi', GatewayApiTransportFactory::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')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Version;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\PdoAdapter;
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/Tests export-ignore
/phpunit.xml.dist export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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\GatewayApi;

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\HttpClientInterface;

/**
* @author Piergiuseppe Longo <piergiuseppe.longo@gmail.com>
*
* @experimental in 5.3
*/
final class GatewayApiTransport extends AbstractTransport
{
protected const HOST = 'gatewayapi.com';

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('gatewayapi://%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 UnsupportedMessageTypeException(__CLASS__, SmsMessage::class, $message);
}

$endpoint = sprintf('https://%s/rest/mtsms', $this->getEndpoint());

$response = $this->client->request('POST', $endpoint, [
'auth_basic' => [$this->authToken, ''],
'json' => [
'sender' => $this->from,
'recipients' => [['msisdn' => $message->getPhone()]],
'message' => $message->getSubject(),
],
]);

$statusCode = $response->getStatusCode();
if (200 !== $statusCode) {
throw new TransportException(sprintf('Unable to send the SMS: error %d.', $statusCode), $response);
}

return new SentMessage($message, (string) $this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?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\GatewayApi;

use Symfony\Component\Notifier\Exception\IncompleteDsnException;
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 Piergiuseppe Longo <piergiuseppe.longo@gmail.com>
*
* @experimental in 5.3
*/
final class GatewayApiTransportFactory extends AbstractTransportFactory
{
/**
* @return GatewayApiTransport
*/
public function create(Dsn $dsn): TransportInterface
{
$scheme = $dsn->getScheme();

if ('gatewayapi' !== $scheme) {
throw new UnsupportedSchemeException($dsn, 'gatewayapi', $this->getSupportedSchemes());
}

$authToken = $this->getUser($dsn);
$from = $dsn->getOption('from');

if (!$from) {
throw new IncompleteDsnException('Missing from.', $dsn->getOriginalDsn());
}

$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
$port = $dsn->getPort();

return (new GatewayApiTransport($authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
}

protected function getSupportedSchemes(): array
{
return ['gatewayapi'];
}
}
19 changes: 19 additions & 0 deletions src/Symfony/Component/Notifier/Bridge/GatewayApi/LICENSE
Original file line number Diff line number Diff line change
@@ -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.
25 changes: 25 additions & 0 deletions src/Symfony/Component/Notifier/Bridge/GatewayApi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
GatewayAPI Notifier
===================

Provides [GatewayAPI](https://gatewayapi.com) integration for Symfony Notifier.

DSN example
-----------

```
GATEWAYAPI_DSN=gatewayapi://TOKEN@default?from=FROM
```

where:
- `TOKEN` is API Token (OAuth)
- `FROM` is sender name

See your account info at https://gatewayapi.com

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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Symfony\Component\Notifier\Bridge\GatewayApi\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Notifier\Bridge\GatewayApi\GatewayApiTransportFactory;
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
use Symfony\Component\Notifier\Transport\Dsn;

final class GatewayApiTransportFactoryTest extends TestCase
{
public function testSupportsGatewayApiScheme()
{
$factory = $this->createFactory();

$this->assertTrue($factory->supports(Dsn::fromString('gatewayapi://token@host.test?from=Symfony')));
}

public function testUnSupportedGatewayShouldThrowsUnsupportedSchemeException()
{
$factory = $this->createFactory();

$this->expectException(UnsupportedSchemeException::class);

$factory->create(Dsn::fromString('somethingElse://token@default?from=Symfony'));
}

public function testCreateWithNoTokenThrowsIncompleteDsnException()
{
$factory = $this->createFactory();

$this->expectException(IncompleteDsnException::class);

$factory->create(Dsn::fromString('gatewayapi://host.test?from=Symfony'));
}

public function testCreateWithNoFromShouldThrowsIncompleteDsnException()
{
$factory = $this->createFactory();

$this->expectException(IncompleteDsnException::class);

$factory->create(Dsn::fromString('gatewayapi://token@host.test'));
}

private function createFactory(): GatewayApiTransportFactory
{
return new GatewayApiTransportFactory();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Symfony\Component\Notifier\Bridge\GatewayApi\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\Notifier\Bridge\GatewayApi\GatewayApiTransport;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Contracts\HttpClient\ResponseInterface;

final class GatewayApiTransportTest extends TestCase
{
public function testSend()
{
$response = $this->createMock(ResponseInterface::class);
$response->expects($this->exactly(2))
->method('getStatusCode')
->willReturn(200);

$client = new MockHttpClient(static function () use ($response): ResponseInterface {
return $response;
});

$transport = $this->getTransport($client);
$message = new SmsMessage('3333333333', 'Test Messgage');
$sentMessage = $transport->send($message);
$this->assertNotNull($sentMessage);
}

public function testSupportsSmsMessage()
{
$transport = $this->getTransport();
$message = new SmsMessage('3333333333', 'Test Messgage');
$this->assertTrue($transport->supports($message));
}

public function testNotSupportsChatMessage()
{
$transport = $this->getTransport();
$message = new ChatMessage('3333333333');
$this->assertFalse($transport->supports($message));
}

private function getTransport(MockHttpClient $client = null): GatewayApiTransport
{
return (new GatewayApiTransport('authtoken', 'Symfony', $client))->setHost('host.test');
}
}
34 changes: 34 additions & 0 deletions src/Symfony/Component/Notifier/Bridge/GatewayApi/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "symfony/gatewayapi-notifier",
"type": "symfony-bridge",
"description": "Symfony GatewayAPI Notifier Bridge",
"keywords": ["sms", "gatewayapi", "notifier"],
"homepage": "https://gatewayapi.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Piergiuseppe Longo",
"email": "piergiuseppe.longo@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.3.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Notifier\\Bridge\\GatewayApi\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev"
}
31 changes: 31 additions & 0 deletions src/Symfony/Component/Notifier/Bridge/GatewayApi/phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -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 GatewayAPI Notifier Bridge 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>
Loading