[Notifier] Rework/streamline bridges (5.2)
This commit is contained in:
parent
6ead4a273e
commit
a5d78787e6
@ -30,6 +30,11 @@ final class DiscordTransportFactory extends AbstractTransportFactory
|
|||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('discord' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'discord', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
$token = $this->getUser($dsn);
|
$token = $this->getUser($dsn);
|
||||||
$webhookId = $dsn->getOption('webhook_id');
|
$webhookId = $dsn->getOption('webhook_id');
|
||||||
|
|
||||||
@ -40,11 +45,7 @@ final class DiscordTransportFactory extends AbstractTransportFactory
|
|||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||||
$port = $dsn->getPort();
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
if ('discord' === $scheme) {
|
return (new DiscordTransport($token, $webhookId, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new DiscordTransport($token, $webhookId, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'discord', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
Discord Notifier
|
Discord Notifier
|
||||||
================
|
================
|
||||||
|
|
||||||
Provides Discord integration for Symfony Notifier.
|
Provides [Discord](https://discord.com) integration for Symfony Notifier.
|
||||||
|
|
||||||
DSN example
|
DSN example
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
|
||||||
DISCORD_DSN=discord://TOKEN@default?webhook_id=ID
|
DISCORD_DSN=discord://TOKEN@default?webhook_id=ID
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -21,46 +21,64 @@ final class DiscordTransportFactoryTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testCreateWithDsn()
|
public function testCreateWithDsn()
|
||||||
{
|
{
|
||||||
$factory = new DiscordTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$host = 'testHost';
|
$transport = $factory->create(Dsn::fromString('discord://token@host.test?webhook_id=testWebhookId'));
|
||||||
$webhookId = 'testChannel';
|
|
||||||
|
|
||||||
$transport = $factory->create(Dsn::fromString(sprintf('discord://%s@%s/?webhook_id=%s', 'token', $host, $webhookId)));
|
$this->assertSame('discord://host.test?webhook_id=testWebhookId', (string) $transport);
|
||||||
|
|
||||||
$this->assertSame(sprintf('discord://%s?webhook_id=%s', $host, $webhookId), (string) $transport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithNoWebhookIdThrowsMalformed()
|
public function testCreateWithMissingOptionWebhookIdThrowsIncompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = new DiscordTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('discord://token@host'));
|
$factory->create(Dsn::fromString('discord://token@host'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithNoTokenThrowsMalformed()
|
public function testCreateWithNoTokenThrowsIncompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = new DiscordTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
$factory->create(Dsn::fromString(sprintf('discord://%s/?webhook_id=%s', 'testHost', 'testChannel')));
|
$factory->create(Dsn::fromString('discord://host.test?webhook_id=testWebhookId'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsDiscordScheme()
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new DiscordTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->assertTrue($factory->supports(Dsn::fromString('discord://host/?webhook_id=testChannel')));
|
$this->assertTrue($factory->supports(Dsn::fromString('discord://host?webhook_id=testWebhookId')));
|
||||||
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/?webhook_id=testChannel')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNonDiscordSchemeThrows()
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new DiscordTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host?webhook_id=testWebhookId')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(UnsupportedSchemeException::class);
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
$factory->create(Dsn::fromString('somethingElse://token@host/?webhook_id=testChannel'));
|
$factory->create(Dsn::fromString('somethingElse://token@host?webhook_id=testWebhookId'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
|
// unsupported scheme and missing "webhook_id" option
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://token@host'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createFactory(): DiscordTransportFactory
|
||||||
|
{
|
||||||
|
return new DiscordTransportFactory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,33 +25,31 @@ final class DiscordTransportTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testToStringContainsProperties()
|
public function testToStringContainsProperties()
|
||||||
{
|
{
|
||||||
$webhookId = 'testChannel';
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$transport = new DiscordTransport('testToken', $webhookId, $this->createMock(HttpClientInterface::class));
|
$this->assertSame('discord://host.test?webhook_id=testWebhookId', (string) $transport);
|
||||||
$transport->setHost('testHost');
|
|
||||||
|
|
||||||
$this->assertSame(sprintf('discord://%s?webhook_id=%s', 'testHost', $webhookId), (string) $transport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsChatMessage()
|
public function testSupportsChatMessage()
|
||||||
{
|
{
|
||||||
$transport = new DiscordTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonChatMessageThrows()
|
public function testSendNonChatMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
$transport = new DiscordTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
|
|
||||||
|
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendChatMessageWithMoreThan2000CharsThrowsLogicException()
|
public function testSendChatMessageWithMoreThan2000CharsThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = new DiscordTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
$this->expectExceptionMessage('The subject length of a Discord message must not exceed 2000 characters.');
|
$this->expectExceptionMessage('The subject length of a Discord message must not exceed 2000 characters.');
|
||||||
@ -61,9 +59,6 @@ final class DiscordTransportTest extends TestCase
|
|||||||
|
|
||||||
public function testSendWithErrorResponseThrows()
|
public function testSendWithErrorResponseThrows()
|
||||||
{
|
{
|
||||||
$this->expectException(TransportException::class);
|
|
||||||
$this->expectExceptionMessageMatches('/testDescription.+testErrorCode/');
|
|
||||||
|
|
||||||
$response = $this->createMock(ResponseInterface::class);
|
$response = $this->createMock(ResponseInterface::class);
|
||||||
$response->expects($this->exactly(2))
|
$response->expects($this->exactly(2))
|
||||||
->method('getStatusCode')
|
->method('getStatusCode')
|
||||||
@ -76,8 +71,16 @@ final class DiscordTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new DiscordTransport('testToken', 'testChannel', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
|
$this->expectException(TransportException::class);
|
||||||
|
$this->expectExceptionMessageMatches('/testDescription.+testErrorCode/');
|
||||||
|
|
||||||
$transport->send(new ChatMessage('testMessage'));
|
$transport->send(new ChatMessage('testMessage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function createTransport(?HttpClientInterface $client = null): DiscordTransport
|
||||||
|
{
|
||||||
|
return (new DiscordTransport('testToken', 'testWebhookId', $client ?? $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,5 +30,4 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev"
|
"minimum-stability": "dev"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ final class EsendexTransport extends AbstractTransport
|
|||||||
'to' => $message->getPhone(),
|
'to' => $message->getPhone(),
|
||||||
'body' => $message->getSubject(),
|
'body' => $message->getSubject(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (null !== $this->from) {
|
if (null !== $this->from) {
|
||||||
$messageData['from'] = $this->from;
|
$messageData['from'] = $this->from;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Notifier\Bridge\Esendex;
|
namespace Symfony\Component\Notifier\Bridge\Esendex;
|
||||||
|
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
||||||
use Symfony\Component\Notifier\Transport\Dsn;
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
@ -27,17 +28,28 @@ final class EsendexTransportFactory extends AbstractTransportFactory
|
|||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('esendex' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'esendex', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
$token = $this->getUser($dsn).':'.$this->getPassword($dsn);
|
$token = $this->getUser($dsn).':'.$this->getPassword($dsn);
|
||||||
$accountReference = $dsn->getOption('accountreference');
|
$accountReference = $dsn->getOption('accountreference');
|
||||||
|
|
||||||
|
if (!$accountReference) {
|
||||||
|
throw new IncompleteDsnException('Missing accountreference.', $dsn->getOriginalDsn());
|
||||||
|
}
|
||||||
|
|
||||||
$from = $dsn->getOption('from');
|
$from = $dsn->getOption('from');
|
||||||
|
|
||||||
|
if (!$from) {
|
||||||
|
throw new IncompleteDsnException('Missing from.', $dsn->getOriginalDsn());
|
||||||
|
}
|
||||||
|
|
||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||||
$port = $dsn->getPort();
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
if ('esendex' === $scheme) {
|
return (new EsendexTransport($token, $accountReference, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new EsendexTransport($token, $accountReference, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'esendex', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
Esendex Notifier
|
Esendex Notifier
|
||||||
================
|
================
|
||||||
|
|
||||||
Provides Esendex integration for Symfony Notifier.
|
Provides [Esendex](https://esendex.com) integration for Symfony Notifier.
|
||||||
|
|
||||||
DSN example
|
DSN example
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
ESENDEX_DSN=esendex://EMAIL:PASSWORD@default?accountreference=ACCOUNT_REFERENCE&from=FROM
|
||||||
ESENDEX_DSN='esendex://EMAIL:PASSWORD@default?accountreference=ACCOUNT_REFERENCE&from=FROM'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `EMAIL` is your Esendex account email
|
- `EMAIL` is your Esendex account email
|
||||||
- `PASSWORD` is the Esendex API password
|
- `PASSWORD` is the Esendex API password
|
||||||
- `ACCOUNT_REFERENCE` is the Esendex account reference that the messages should be sent from.
|
- `ACCOUNT_REFERENCE` is the Esendex account reference that the messages should be sent from
|
||||||
- `FROM` is the alphanumeric originator for the message to appear to originate from.
|
- `FROM` is the alphanumeric originator for the message to appear to originate from
|
||||||
|
|
||||||
See Esendex documentation at https://developers.esendex.com/api-reference#smsapis
|
See Esendex documentation at https://developers.esendex.com/api-reference#smsapis
|
||||||
|
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
<?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\Esendex\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory;
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
|
|
||||||
|
final class EsendexTransportFactoryTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCreateWithDsn()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$transport = $factory->create(Dsn::fromString('esendex://email:password@host.test?accountreference=testAccountreference&from=testFrom'));
|
||||||
|
|
||||||
|
$this->assertSame('esendex://host.test', (string) $transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithMissingOptionAccountreferenceThrowsIncompleteDsnException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
|
$factory->create(Dsn::fromString('esendex://email:password@host?from=FROM'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithMissingOptionFromThrowsIncompleteDsnException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
|
$factory->create(Dsn::fromString('esendex://email:password@host?accountreference=ACCOUNTREFERENCE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertTrue($factory->supports(Dsn::fromString('esendex://email:password@host?accountreference=ACCOUNTREFERENCE&from=FROM')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://email:password@host?accountreference=ACCOUNTREFERENCE&from=FROM')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://email:password@host?accountreference=REFERENCE&from=FROM'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
|
// unsupported scheme and missing "from" option
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://email:password@host?accountreference=REFERENCE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createFactory(): EsendexTransportFactory
|
||||||
|
{
|
||||||
|
return new EsendexTransportFactory();
|
||||||
|
}
|
||||||
|
}
|
@ -25,23 +25,22 @@ final class EsendexTransportTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testToString()
|
public function testToString()
|
||||||
{
|
{
|
||||||
$transport = new EsendexTransport('testToken', 'accountReference', 'from', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
$transport->setHost('testHost');
|
|
||||||
|
|
||||||
$this->assertSame(sprintf('esendex://%s', 'testHost'), (string) $transport);
|
$this->assertSame('esendex://host.test', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsSmsMessage()
|
public function testSupportsSmsMessage()
|
||||||
{
|
{
|
||||||
$transport = new EsendexTransport('testToken', 'accountReference', 'from', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('phone', 'testSmsMessage')));
|
$this->assertTrue($transport->supports(new SmsMessage('phone', 'testSmsMessage')));
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrows()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = new EsendexTransport('testToken', 'accountReference', 'from', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
@ -58,10 +57,11 @@ final class EsendexTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new EsendexTransport('testToken', 'accountReference', 'from', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$this->expectException(TransportException::class);
|
$this->expectException(TransportException::class);
|
||||||
$this->expectExceptionMessage('Unable to send the SMS: error 500.');
|
$this->expectExceptionMessage('Unable to send the SMS: error 500.');
|
||||||
|
|
||||||
$transport->send(new SmsMessage('phone', 'testMessage'));
|
$transport->send(new SmsMessage('phone', 'testMessage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,10 +79,16 @@ final class EsendexTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new EsendexTransport('testToken', 'accountReference', 'from', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$this->expectException(TransportException::class);
|
$this->expectException(TransportException::class);
|
||||||
$this->expectExceptionMessage('Unable to send the SMS: error 500. Details from Esendex: accountreference_invalid: "Invalid Account Reference EX0000000".');
|
$this->expectExceptionMessage('Unable to send the SMS: error 500. Details from Esendex: accountreference_invalid: "Invalid Account Reference EX0000000".');
|
||||||
|
|
||||||
$transport->send(new SmsMessage('phone', 'testMessage'));
|
$transport->send(new SmsMessage('phone', 'testMessage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function createTransport(?HttpClientInterface $client = null): EsendexTransport
|
||||||
|
{
|
||||||
|
return (new EsendexTransport('testToken', 'testAccountReference', 'testFrom', $client ?: $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,9 @@ final class FirebaseTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['results'][0]['message_id']);
|
$sentMessage->setMessageId($success['results'][0]['message_id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ final class FirebaseTransportTest extends TestCase
|
|||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->createTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
@ -22,45 +22,53 @@ final class FreeMobileTransportTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testToStringContainsProperties()
|
public function testToStringContainsProperties()
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport('0611223344');
|
$transport = $this->createTransport('0611223344');
|
||||||
|
|
||||||
$this->assertSame('freemobile://host.test?phone=0611223344', (string) $transport);
|
$this->assertSame('freemobile://host.test?phone=0611223344', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsMessageInterface()
|
/**
|
||||||
|
* @dataProvider supportsProvider
|
||||||
|
*/
|
||||||
|
public function testSupportsMessageInterface(bool $expected, string $configuredPhoneNumber, MessageInterface $message)
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport('0611223344');
|
$transport = $this->createTransport($configuredPhoneNumber);
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
$this->assertSame($expected, $transport->supports($message));
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('+33611223344', 'Hello!')));
|
|
||||||
$this->assertFalse($transport->supports(new SmsMessage('0699887766', 'Hello!')));
|
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
|
||||||
|
|
||||||
$transport = $this->getTransport('+33611223344');
|
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('+33611223344', 'Hello!')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
/**
|
||||||
|
* @return iterable<array{0: bool, 1: string, 2: MessageInterface}>
|
||||||
|
*/
|
||||||
|
public function supportsProvider(): iterable
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport('0611223344');
|
yield [true, '0611223344', new SmsMessage('0611223344', 'Hello!')];
|
||||||
|
yield [true, '0611223344', new SmsMessage('+33611223344', 'Hello!')];
|
||||||
|
yield [false, '0611223344', new SmsMessage('0699887766', 'Hello!')];
|
||||||
|
yield [false, '0611223344', $this->createMock(MessageInterface::class)];
|
||||||
|
yield [true, '+33611223344', new SmsMessage('0611223344', 'Hello!')];
|
||||||
|
yield [true, '+33611223344', new SmsMessage('+33611223344', 'Hello!')];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport('0611223344');
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendSmsMessageButInvalidPhoneThrowsException()
|
public function testSendSmsMessageButInvalidPhoneThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport('0611223344');
|
$transport = $this->createTransport('0611223344');
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
$transport->send(new SmsMessage('0699887766', 'Hello!'));
|
$transport->send(new SmsMessage('0699887766', 'Hello!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getTransport(string $phone): FreeMobileTransport
|
private function createTransport(string $phone): FreeMobileTransport
|
||||||
{
|
{
|
||||||
return (new FreeMobileTransport('login', 'pass', $phone, $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
return (new FreeMobileTransport('login', 'pass', $phone, $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ final class GoogleChatOptions implements MessageOptionsInterface
|
|||||||
if ($notification->getContent()) {
|
if ($notification->getContent()) {
|
||||||
$text .= "\r\n".$notification->getContent();
|
$text .= "\r\n".$notification->getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($exception = $notification->getExceptionAsString()) {
|
if ($exception = $notification->getExceptionAsString()) {
|
||||||
$text .= "\r\n".'```'.$notification->getExceptionAsString().'```';
|
$text .= "\r\n".'```'.$notification->getExceptionAsString().'```';
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,7 @@ final class GoogleChatTransport extends AbstractTransport
|
|||||||
if (!$message instanceof ChatMessage) {
|
if (!$message instanceof ChatMessage) {
|
||||||
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, ChatMessage::class, \get_class($message)));
|
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, ChatMessage::class, \get_class($message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message->getOptions() && !$message->getOptions() instanceof GoogleChatOptions) {
|
if ($message->getOptions() && !$message->getOptions() instanceof GoogleChatOptions) {
|
||||||
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, GoogleChatOptions::class));
|
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, GoogleChatOptions::class));
|
||||||
}
|
}
|
||||||
|
@ -32,21 +32,18 @@ final class GoogleChatTransportFactory extends AbstractTransportFactory
|
|||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
if ('googlechat' === $scheme) {
|
if ('googlechat' !== $scheme) {
|
||||||
$space = explode('/', $dsn->getPath())[1];
|
throw new UnsupportedSchemeException($dsn, 'googlechat', $this->getSupportedSchemes());
|
||||||
$accessKey = $this->getUser($dsn);
|
|
||||||
$accessToken = $this->getPassword($dsn);
|
|
||||||
$threadKey = $dsn->getOption('threadKey');
|
|
||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
|
||||||
$port = $dsn->getPort();
|
|
||||||
|
|
||||||
return (new GoogleChatTransport($space, $accessKey, $accessToken, $this->client, $this->dispatcher))
|
|
||||||
->setThreadKey($threadKey)
|
|
||||||
->setHost($host)
|
|
||||||
->setPort($port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'googlechat', $this->getSupportedSchemes());
|
$space = explode('/', $dsn->getPath())[1];
|
||||||
|
$accessKey = $this->getUser($dsn);
|
||||||
|
$accessToken = $this->getPassword($dsn);
|
||||||
|
$threadKey = $dsn->getOption('threadKey');
|
||||||
|
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||||
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
|
return (new GoogleChatTransport($space, $accessKey, $accessToken, $this->client, $this->dispatcher))->setThreadKey($threadKey)->setHost($host)->setPort($port);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -7,15 +7,14 @@ DSN example
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
GOOGLE_CHAT_DSN=googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE?threadKey=THREAD_KEY
|
||||||
INFOBIP_DSN=googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE?threadKey=THREAD_KEY
|
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `ACCESS_KEY` is your Google Chat access key
|
- `ACCESS_KEY` is your Google Chat access key
|
||||||
- `ACCESS_TOKEN` is your Google Chat access token
|
- `ACCESS_TOKEN` is your Google Chat access token
|
||||||
- `SPACE` is the Google Chat space
|
- `SPACE` is the Google Chat space
|
||||||
- `THREAD_KEY` is the the Google Chat message thread to group messages into a single thread
|
- `THREAD_KEY` is the the Google Chat message thread to group messages into a single thread (optional)
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
@ -21,47 +21,55 @@ final class GoogleChatTransportFactoryTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testCreateWithDsn()
|
public function testCreateWithDsn()
|
||||||
{
|
{
|
||||||
$factory = new GoogleChatTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'googlechat://abcde-fghij:kl_mnopqrstwxyz%3D@chat.googleapis.com/AAAAA_YYYYY';
|
$transport = $factory->create(Dsn::fromString('googlechat://abcde-fghij:kl_mnopqrstwxyz%3D@chat.googleapis.com/AAAAA_YYYYY'));
|
||||||
$transport = $factory->create(Dsn::fromString($dsn));
|
|
||||||
|
|
||||||
$this->assertSame('googlechat://chat.googleapis.com/AAAAA_YYYYY', (string) $transport);
|
$this->assertSame('googlechat://chat.googleapis.com/AAAAA_YYYYY', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithThreadKeyInDsn()
|
public function testCreateWithThreadKeyInDsn()
|
||||||
{
|
{
|
||||||
$factory = new GoogleChatTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'googlechat://abcde-fghij:kl_mnopqrstwxyz%3D@chat.googleapis.com/AAAAA_YYYYY?threadKey=abcdefg';
|
$transport = $factory->create(Dsn::fromString('googlechat://abcde-fghij:kl_mnopqrstwxyz%3D@chat.googleapis.com/AAAAA_YYYYY?threadKey=abcdefg'));
|
||||||
$transport = $factory->create(Dsn::fromString($dsn));
|
|
||||||
|
|
||||||
$this->assertSame('googlechat://chat.googleapis.com/AAAAA_YYYYY?threadKey=abcdefg', (string) $transport);
|
$this->assertSame('googlechat://chat.googleapis.com/AAAAA_YYYYY?threadKey=abcdefg', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateRequiresCredentials()
|
public function testCreateRequiresCredentials()
|
||||||
{
|
{
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$factory = $this->createFactory();
|
||||||
$factory = new GoogleChatTransportFactory();
|
|
||||||
|
|
||||||
$dsn = 'googlechat://chat.googleapis.com/v1/spaces/AAAAA_YYYYY/messages';
|
$this->expectException(IncompleteDsnException::class);
|
||||||
$factory->create(Dsn::fromString($dsn));
|
|
||||||
|
$factory->create(Dsn::fromString('googlechat://chat.googleapis.com/v1/spaces/AAAAA_YYYYY/messages'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsGoogleChatScheme()
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new GoogleChatTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->assertTrue($factory->supports(Dsn::fromString('googlechat://host/path')));
|
$this->assertTrue($factory->supports(Dsn::fromString('googlechat://host/path')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/path')));
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/path')));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNonGoogleChatSchemeThrows()
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
{
|
{
|
||||||
$factory = new GoogleChatTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(UnsupportedSchemeException::class);
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('somethingElse://host/path'));
|
$factory->create(Dsn::fromString('somethingElse://host/path'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function createFactory(): GoogleChatTransportFactory
|
||||||
|
{
|
||||||
|
return new GoogleChatTransportFactory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testToStringContainsProperties()
|
public function testToStringContainsProperties()
|
||||||
{
|
{
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
$transport->setHost(null);
|
$transport->setHost(null);
|
||||||
|
|
||||||
$this->assertSame('googlechat://chat.googleapis.com/My-Space', (string) $transport);
|
$this->assertSame('googlechat://chat.googleapis.com/My-Space', (string) $transport);
|
||||||
@ -36,17 +36,17 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
|
|
||||||
public function testSupportsChatMessage()
|
public function testSupportsChatMessage()
|
||||||
{
|
{
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $this->createMock(HttpClientInterface::class));
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonChatMessageThrows()
|
public function testSendNonChatMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$this->expectException(LogicException::class);
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $this->createMock(HttpClientInterface::class));
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client);
|
$transport = $this->createTransport($client);
|
||||||
$transport->setThreadKey('My-Thread');
|
$transport->setThreadKey('My-Thread');
|
||||||
|
|
||||||
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
||||||
@ -157,7 +157,7 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$sentMessage = $transport->send($chatMessage);
|
$sentMessage = $transport->send($chatMessage);
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
return $this->createMock(ResponseInterface::class);
|
return $this->createMock(ResponseInterface::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class)));
|
$transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class)));
|
||||||
}
|
}
|
||||||
@ -202,10 +202,15 @@ class GoogleChatTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
$sentMessage = $transport->send(new ChatMessage('testMessage'));
|
||||||
|
|
||||||
$this->assertSame('spaces/My-Space/messages/abcdefg.hijklmno', $sentMessage->getMessageId());
|
$this->assertSame('spaces/My-Space/messages/abcdefg.hijklmno', $sentMessage->getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function createTransport(?HttpClientInterface $client = null): GoogleChatTransport
|
||||||
|
{
|
||||||
|
return new GoogleChatTransport('My-Space', 'theAccessKey', 'theAccessToken=', $client ?: $this->createMock(HttpClientInterface::class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,11 @@ final class InfobipTransportFactory extends AbstractTransportFactory
|
|||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('infobip' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'infobip', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
$authToken = $this->getUser($dsn);
|
$authToken = $this->getUser($dsn);
|
||||||
$from = $dsn->getOption('from');
|
$from = $dsn->getOption('from');
|
||||||
$host = $dsn->getHost();
|
$host = $dsn->getHost();
|
||||||
@ -40,11 +45,7 @@ final class InfobipTransportFactory extends AbstractTransportFactory
|
|||||||
throw new IncompleteDsnException('Missing from.', $dsn->getOriginalDsn());
|
throw new IncompleteDsnException('Missing from.', $dsn->getOriginalDsn());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('infobip' === $scheme) {
|
return (new InfobipTransport($authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new InfobipTransport($authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'infobip', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -7,7 +7,6 @@ DSN example
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
|
||||||
INFOBIP_DSN=infobip://AUTH_TOKEN@INFOBIP_HOST?from=FROM
|
INFOBIP_DSN=infobip://AUTH_TOKEN@INFOBIP_HOST?from=FROM
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -21,43 +21,55 @@ final class InfobipTransportFactoryTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testCreateWithDsn()
|
public function testCreateWithDsn()
|
||||||
{
|
{
|
||||||
$factory = new InfobipTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'infobip://authtoken@default?from=0611223344';
|
$transport = $factory->create(Dsn::fromString('infobip://authtoken@host.test?from=0611223344'));
|
||||||
$transport = $factory->create(Dsn::fromString($dsn));
|
|
||||||
$transport->setHost('host.test');
|
|
||||||
|
|
||||||
$this->assertSame('infobip://host.test?from=0611223344', (string) $transport);
|
$this->assertSame('infobip://host.test?from=0611223344', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithNoFromThrowsMalformed()
|
public function testCreateWithNoFromThrowsIncompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = new InfobipTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
$factory->create(Dsn::fromString('infobip://authtoken@default'));
|
||||||
$dsnIncomplete = 'infobip://authtoken@default';
|
|
||||||
$factory->create(Dsn::fromString($dsnIncomplete));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsInfobipScheme()
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new InfobipTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'infobip://authtoken@default?from=0611223344';
|
$this->assertTrue($factory->supports(Dsn::fromString('infobip://authtoken@default?from=0611223344')));
|
||||||
$dsnUnsupported = 'unsupported://authtoken@default?from=0611223344';
|
|
||||||
|
|
||||||
$this->assertTrue($factory->supports(Dsn::fromString($dsn)));
|
|
||||||
$this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNonInfobipSchemeThrows()
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new InfobipTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://authtoken@default?from=0611223344')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://authtoken@default?from=FROM'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(UnsupportedSchemeException::class);
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
$dsnUnsupported = 'unsupported://authtoken@default?from=0611223344';
|
// unsupported scheme and missing "from" option
|
||||||
$factory->create(Dsn::fromString($dsnUnsupported));
|
$factory->create(Dsn::fromString('somethingElse://authtoken@default'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createFactory(): InfobipTransportFactory
|
||||||
|
{
|
||||||
|
return new InfobipTransportFactory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,34 +22,30 @@ final class InfobipTransportTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testToStringContainsProperties()
|
public function testToStringContainsProperties()
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertSame('infobip://host.test?from=0611223344', (string) $transport);
|
$this->assertSame('infobip://host.test?from=0611223344', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsMessageInterface()
|
public function testSupportsMessageInterface()
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getTransport(): InfobipTransport
|
private function createTransport(): InfobipTransport
|
||||||
{
|
{
|
||||||
return (new InfobipTransport(
|
return (new InfobipTransport('authtoken', '0611223344', $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||||
'authtoken',
|
|
||||||
'0611223344',
|
|
||||||
$this->createMock(HttpClientInterface::class)
|
|
||||||
))->setHost('host.test');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ final class LinkedInTransport extends AbstractTransport
|
|||||||
if (!$message instanceof ChatMessage) {
|
if (!$message instanceof ChatMessage) {
|
||||||
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, ChatMessage::class, \get_class($message)));
|
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, ChatMessage::class, \get_class($message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message->getOptions() && !$message->getOptions() instanceof LinkedInOptions) {
|
if ($message->getOptions() && !$message->getOptions() instanceof LinkedInOptions) {
|
||||||
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, LinkedInOptions::class));
|
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, LinkedInOptions::class));
|
||||||
}
|
}
|
||||||
@ -87,7 +88,7 @@ final class LinkedInTransport extends AbstractTransport
|
|||||||
$result = $response->toArray(false);
|
$result = $response->toArray(false);
|
||||||
|
|
||||||
if (!$result['id']) {
|
if (!$result['id']) {
|
||||||
throw new TransportException(sprintf('Unable to post the Linkedin message : "%s".', $result['error']), $response);
|
throw new TransportException(sprintf('Unable to post the Linkedin message: "%s".', $result['error']), $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sentMessage = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
|
@ -26,16 +26,17 @@ class LinkedInTransportFactory extends AbstractTransportFactory
|
|||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('linkedin' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'linkedin', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
$authToken = $this->getUser($dsn);
|
$authToken = $this->getUser($dsn);
|
||||||
$accountId = $this->getPassword($dsn);
|
$accountId = $this->getPassword($dsn);
|
||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||||
$port = $dsn->getPort();
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
if ('linkedin' === $scheme) {
|
return (new LinkedInTransport($authToken, $accountId, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new LinkedInTransport($authToken, $accountId, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'linkedin', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -7,8 +7,7 @@ DSN example
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
LINKEDIN_DSN=linkedin://ACCESS_TOKEN:USER_ID@default
|
||||||
LINKEDIN_DSN='linkedin://ACCESS_TOKEN:USER_ID@default'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
|
@ -12,39 +12,45 @@ final class LinkedInTransportFactoryTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testCreateWithDsn()
|
public function testCreateWithDsn()
|
||||||
{
|
{
|
||||||
$factory = new LinkedInTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'linkedin://login:pass@default';
|
$transport = $factory->create(Dsn::fromString('linkedin://accessToken:UserId@host.test'));
|
||||||
$transport = $factory->create(Dsn::fromString($dsn));
|
|
||||||
$transport->setHost('testHost');
|
|
||||||
|
|
||||||
$this->assertSame('linkedin://testHost', (string) $transport);
|
$this->assertSame('linkedin://host.test', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsLinkedinScheme()
|
public function testCreateWithOnlyAccessTokenOrUserIdThrowsIncompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = new LinkedInTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
$factory->create(Dsn::fromString('linkedin://AccessTokenOrUserId@default'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->assertTrue($factory->supports(Dsn::fromString('linkedin://host/path')));
|
$this->assertTrue($factory->supports(Dsn::fromString('linkedin://host/path')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/path')));
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/path')));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNonLinkedinSchemeThrows()
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
{
|
{
|
||||||
$factory = new LinkedInTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(UnsupportedSchemeException::class);
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://accessToken:UserId@default'));
|
||||||
$dsn = 'foo://login:pass@default';
|
|
||||||
$factory->create(Dsn::fromString($dsn));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIncompleteDsnMissingUserThrows()
|
private function createFactory(): LinkedInTransportFactory
|
||||||
{
|
{
|
||||||
$factory = new LinkedInTransportFactory();
|
return new LinkedInTransportFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('somethingElse://host/path'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,16 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
|||||||
|
|
||||||
final class LinkedInTransportTest extends TestCase
|
final class LinkedInTransportTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testToString()
|
public function testToStringContainsProperties()
|
||||||
{
|
{
|
||||||
$this->assertSame(sprintf('linkedin://host.test'), (string) $this->getTransport());
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->assertSame('linkedin://host.test', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsChatMessage()
|
public function testSupportsChatMessage()
|
||||||
{
|
{
|
||||||
$transport = $this->getTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
@ -31,10 +33,9 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
|
|
||||||
public function testSendNonChatMessageThrows()
|
public function testSendNonChatMessageThrows()
|
||||||
{
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
$transport = $this->getTransport();
|
|
||||||
|
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = $this->getTransport($client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$transport->send(new ChatMessage('testMessage'));
|
$transport->send(new ChatMessage('testMessage'));
|
||||||
}
|
}
|
||||||
@ -77,7 +78,7 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = $this->getTransport($client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$transport->send(new ChatMessage('testMessage'));
|
$transport->send(new ChatMessage('testMessage'));
|
||||||
}
|
}
|
||||||
@ -98,19 +99,19 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
|
|
||||||
$expectedBody = json_encode([
|
$expectedBody = json_encode([
|
||||||
'specificContent' => [
|
'specificContent' => [
|
||||||
'com.linkedin.ugc.ShareContent' => [
|
'com.linkedin.ugc.ShareContent' => [
|
||||||
'shareCommentary' => [
|
'shareCommentary' => [
|
||||||
'attributes' => [],
|
'attributes' => [],
|
||||||
'text' => 'testMessage',
|
'text' => 'testMessage',
|
||||||
],
|
|
||||||
'shareMediaCategory' => 'NONE',
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
'visibility' => [
|
'shareMediaCategory' => 'NONE',
|
||||||
'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC',
|
|
||||||
],
|
],
|
||||||
|
],
|
||||||
|
'visibility' => [
|
||||||
|
'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC',
|
||||||
|
],
|
||||||
'lifecycleState' => 'PUBLISHED',
|
'lifecycleState' => 'PUBLISHED',
|
||||||
'author' => 'urn:li:person:MyLogin',
|
'author' => 'urn:li:person:AccountId',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use (
|
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use (
|
||||||
@ -121,7 +122,7 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
$transport = $this->getTransport($client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$transport->send(new ChatMessage($message));
|
$transport->send(new ChatMessage($message));
|
||||||
}
|
}
|
||||||
@ -145,19 +146,19 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
|
|
||||||
$expectedBody = json_encode([
|
$expectedBody = json_encode([
|
||||||
'specificContent' => [
|
'specificContent' => [
|
||||||
'com.linkedin.ugc.ShareContent' => [
|
'com.linkedin.ugc.ShareContent' => [
|
||||||
'shareCommentary' => [
|
'shareCommentary' => [
|
||||||
'attributes' => [],
|
'attributes' => [],
|
||||||
'text' => 'testMessage',
|
'text' => 'testMessage',
|
||||||
],
|
|
||||||
'shareMediaCategory' => 'NONE',
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
'visibility' => [
|
'shareMediaCategory' => 'NONE',
|
||||||
'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC',
|
|
||||||
],
|
],
|
||||||
|
],
|
||||||
|
'visibility' => [
|
||||||
|
'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC',
|
||||||
|
],
|
||||||
'lifecycleState' => 'PUBLISHED',
|
'lifecycleState' => 'PUBLISHED',
|
||||||
'author' => 'urn:li:person:MyLogin',
|
'author' => 'urn:li:person:AccountId',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use (
|
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use (
|
||||||
@ -169,7 +170,7 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = $this->getTransport($client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$transport->send($chatMessage);
|
$transport->send($chatMessage);
|
||||||
}
|
}
|
||||||
@ -182,17 +183,13 @@ final class LinkedInTransportTest extends TestCase
|
|||||||
return $this->createMock(ResponseInterface::class);
|
return $this->createMock(ResponseInterface::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = $this->getTransport($client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class)));
|
$transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTransport($client = null)
|
private function createTransport(?HttpClientInterface $client = null): LinkedInTransport
|
||||||
{
|
{
|
||||||
return (new LinkedInTransport(
|
return (new LinkedInTransport('AuthToken', 'AccountId', $client ?? $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||||
'MyToken',
|
|
||||||
'MyLogin',
|
|
||||||
$client ?? $this->createMock(HttpClientInterface::class)
|
|
||||||
))->setHost('host.test');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,9 +78,9 @@ final class MattermostTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($sentMessage, (string) $this);
|
||||||
$message->setMessageId($success['id']);
|
$sentMessage->setMessageId($success['id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ final class MattermostTransportFactoryTest extends TestCase
|
|||||||
$factory = $this->createFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('mattermost://host.test?channel=testChannel'));
|
$factory->create(Dsn::fromString('mattermost://host.test?channel=testChannel'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ final class MobytOptions implements MessageOptionsInterface
|
|||||||
public const MESSAGE_TYPE_QUALITY_MEDIUM = 'L';
|
public const MESSAGE_TYPE_QUALITY_MEDIUM = 'L';
|
||||||
public const MESSAGE_TYPE_QUALITY_LOW = 'LL';
|
public const MESSAGE_TYPE_QUALITY_LOW = 'LL';
|
||||||
|
|
||||||
private $options = [];
|
private $options;
|
||||||
|
|
||||||
public function __construct(array $options = [])
|
public function __construct(array $options = [])
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ final class MobytTransport extends AbstractTransport
|
|||||||
private $from;
|
private $from;
|
||||||
private $typeQuality;
|
private $typeQuality;
|
||||||
|
|
||||||
public function __construct(string $accountSid, string $authToken, $from, string $typeQuality, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null)
|
public function __construct(string $accountSid, string $authToken, string $from, string $typeQuality, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null)
|
||||||
{
|
{
|
||||||
$this->accountSid = $accountSid;
|
$this->accountSid = $accountSid;
|
||||||
$this->authToken = $authToken;
|
$this->authToken = $authToken;
|
||||||
@ -93,9 +93,9 @@ final class MobytTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['order_id']);
|
$sentMessage->setMessageId($success['order_id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Notifier\Bridge\Mobyt;
|
namespace Symfony\Component\Notifier\Bridge\Mobyt;
|
||||||
|
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
||||||
use Symfony\Component\Notifier\Transport\Dsn;
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
@ -29,18 +30,24 @@ final class MobytTransportFactory extends AbstractTransportFactory
|
|||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('mobyt' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'mobyt', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
$accountSid = $this->getUser($dsn);
|
$accountSid = $this->getUser($dsn);
|
||||||
$authToken = $this->getPassword($dsn);
|
$authToken = $this->getPassword($dsn);
|
||||||
$from = $dsn->getOption('from');
|
$from = $dsn->getOption('from');
|
||||||
|
|
||||||
|
if (!$from) {
|
||||||
|
throw new IncompleteDsnException('Missing from.', $dsn->getOriginalDsn());
|
||||||
|
}
|
||||||
|
|
||||||
$typeQuality = $dsn->getOption('type_quality', MobytOptions::MESSAGE_TYPE_QUALITY_LOW);
|
$typeQuality = $dsn->getOption('type_quality', MobytOptions::MESSAGE_TYPE_QUALITY_LOW);
|
||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||||
$port = $dsn->getPort();
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
if ('mobyt' === $scheme) {
|
return (new MobytTransport($accountSid, $authToken, $from, $typeQuality, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new MobytTransport($accountSid, $authToken, $from, $typeQuality, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'mobyt', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -7,15 +7,14 @@ DSN example
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
|
||||||
MOBYT_DSN=mobyt://USER_KEY:ACCESS_TOKEN@default?from=FROM&type_quality=TYPE_QUALITY
|
MOBYT_DSN=mobyt://USER_KEY:ACCESS_TOKEN@default?from=FROM&type_quality=TYPE_QUALITY
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `USER_KEY` is your Mobyt user key
|
- `USER_KEY` is your Mobyt user key
|
||||||
- `ACCESS_TOKEN` is your Mobyt access token
|
- `ACCESS_TOKEN` is your Mobyt access token
|
||||||
- `TYPE_QUALITY` is the quality : `N` for high, `L` for medium, `LL` for low (default: `L`)
|
|
||||||
- `FROM` is the sender
|
- `FROM` is the sender
|
||||||
|
- `TYPE_QUALITY` is the quality : `N` for high, `L` for medium, `LL` for low (default: `L`)
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
@ -6,29 +6,23 @@ use PHPUnit\Framework\TestCase;
|
|||||||
use Symfony\Component\Notifier\Bridge\Mobyt\MobytOptions;
|
use Symfony\Component\Notifier\Bridge\Mobyt\MobytOptions;
|
||||||
use Symfony\Component\Notifier\Notification\Notification;
|
use Symfony\Component\Notifier\Notification\Notification;
|
||||||
|
|
||||||
class MobytOptionsTest extends TestCase
|
final class MobytOptionsTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider fromNotificationDataProvider
|
* @dataProvider fromNotificationDataProvider
|
||||||
*/
|
*/
|
||||||
public function testFromNotification($importance, $expectedMessageType)
|
public function testFromNotification(string $importance, string $expectedMessageType)
|
||||||
{
|
{
|
||||||
$notification = (new Notification('Foo'))->importance($importance);
|
$notification = (new Notification('Foo'))->importance($importance);
|
||||||
|
|
||||||
$options = (MobytOptions::fromNotification($notification))->toArray();
|
$options = (MobytOptions::fromNotification($notification))->toArray();
|
||||||
|
|
||||||
$this->assertEquals($expectedMessageType, $options['message_type']);
|
$this->assertSame($expectedMessageType, $options['message_type']);
|
||||||
}
|
|
||||||
|
|
||||||
public function testFromNotificationDefaultLevel()
|
|
||||||
{
|
|
||||||
$notification = (new Notification('Foo'))->importance('Bar');
|
|
||||||
|
|
||||||
$options = (MobytOptions::fromNotification($notification))->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals(MobytOptions::MESSAGE_TYPE_QUALITY_HIGH, $options['message_type']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Generator<array{0: string, 1: string}>
|
||||||
|
*/
|
||||||
public function fromNotificationDataProvider(): \Generator
|
public function fromNotificationDataProvider(): \Generator
|
||||||
{
|
{
|
||||||
yield [Notification::IMPORTANCE_URGENT, MobytOptions::MESSAGE_TYPE_QUALITY_HIGH];
|
yield [Notification::IMPORTANCE_URGENT, MobytOptions::MESSAGE_TYPE_QUALITY_HIGH];
|
||||||
@ -37,14 +31,22 @@ class MobytOptionsTest extends TestCase
|
|||||||
yield [Notification::IMPORTANCE_LOW, MobytOptions::MESSAGE_TYPE_QUALITY_LOW];
|
yield [Notification::IMPORTANCE_LOW, MobytOptions::MESSAGE_TYPE_QUALITY_LOW];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFromNotificationDefaultLevel()
|
||||||
|
{
|
||||||
|
$notification = (new Notification('Foo'))->importance('Bar');
|
||||||
|
|
||||||
|
$options = (MobytOptions::fromNotification($notification))->toArray();
|
||||||
|
|
||||||
|
$this->assertSame(MobytOptions::MESSAGE_TYPE_QUALITY_HIGH, $options['message_type']);
|
||||||
|
}
|
||||||
|
|
||||||
public function testGetRecipientIdWhenSet()
|
public function testGetRecipientIdWhenSet()
|
||||||
{
|
{
|
||||||
$options = [
|
$mobytOptions = new MobytOptions([
|
||||||
'recipient' => 'foo',
|
'recipient' => 'foo',
|
||||||
];
|
]);
|
||||||
$mobytOptions = new MobytOptions($options);
|
|
||||||
|
|
||||||
$this->assertEquals('foo', $mobytOptions->getRecipientId());
|
$this->assertSame('foo', $mobytOptions->getRecipientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetRecipientIdWhenNotSet()
|
public function testGetRecipientIdWhenNotSet()
|
||||||
@ -54,11 +56,12 @@ class MobytOptionsTest extends TestCase
|
|||||||
|
|
||||||
public function testToArray()
|
public function testToArray()
|
||||||
{
|
{
|
||||||
$options = [
|
$mobytOptions = new MobytOptions([
|
||||||
'message' => 'foo',
|
'message' => 'foo',
|
||||||
'recipient' => 'bar',
|
'recipient' => 'bar',
|
||||||
];
|
]);
|
||||||
$this->assertEmpty((new MobytOptions($options))->toArray());
|
|
||||||
|
$this->assertEmpty($mobytOptions->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMessageType()
|
public function testMessageType()
|
||||||
@ -66,6 +69,6 @@ class MobytOptionsTest extends TestCase
|
|||||||
$mobytOptions = new MobytOptions();
|
$mobytOptions = new MobytOptions();
|
||||||
$mobytOptions->messageType('foo');
|
$mobytOptions->messageType('foo');
|
||||||
|
|
||||||
$this->assertEquals(['message_type' => 'foo'], $mobytOptions->toArray());
|
$this->assertSame(['message_type' => 'foo'], $mobytOptions->toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,9 @@ final class NexmoTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['messages'][0]['message-id']);
|
$sentMessage->setMessageId($success['messages'][0]['message-id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ final class NexmoTransportTest extends TestCase
|
|||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->createTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
@ -94,10 +94,10 @@ final class OvhCloudTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['ids'][0]);
|
$sentMessage->setMessageId($success['ids'][0]);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,7 +35,7 @@ final class OvhCloudTransportTest extends TestCase
|
|||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->createTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ final class RocketChatTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['message']['_id']);
|
$sentMessage->setMessageId($success['message']['_id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ final class RocketChatTransportFactoryTest extends TestCase
|
|||||||
$factory = $this->createFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('rocketchat://host.test?channel=testChannel'));
|
$factory->create(Dsn::fromString('rocketchat://host.test?channel=testChannel'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
Sendinblue Notifier
|
Sendinblue Notifier
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Provides Sendinblue integration for Symfony Notifier.
|
Provides [Sendinblue](https://sendinblue.com) integration for Symfony Notifier.
|
||||||
|
|
||||||
DSN example
|
DSN example
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
SENDINBLUE_DSN=sendinblue://API_KEY@default?sender=SENDER
|
||||||
SENDINBLUE_DSN=sendinblue://API_KEY@default?sender=PHONE
|
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `API_KEY` is your api key from your Sendinblue account
|
- `API_KEY` is your api key from your Sendinblue account
|
||||||
- `PHONE` is your sender's phone number
|
- `SENDER` is your sender's phone number
|
||||||
|
|
||||||
See more info at https://developers.sendinblue.com/reference#sendtransacsms
|
See more info at https://developers.sendinblue.com/reference#sendtransacsms
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ final class SendinblueTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['messageId']);
|
$sentMessage->setMessageId($success['messageId']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,20 +29,23 @@ final class SendinblueTransportFactory extends AbstractTransportFactory
|
|||||||
*/
|
*/
|
||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
if (!$sender = $dsn->getOption('sender')) {
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('sendinblue' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'sendinblue', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiKey = $this->getUser($dsn);
|
||||||
|
$sender = $dsn->getOption('sender');
|
||||||
|
|
||||||
|
if (!$sender) {
|
||||||
throw new IncompleteDsnException('Missing sender.', $dsn->getOriginalDsn());
|
throw new IncompleteDsnException('Missing sender.', $dsn->getOriginalDsn());
|
||||||
}
|
}
|
||||||
|
|
||||||
$scheme = $dsn->getScheme();
|
|
||||||
$apiKey = $this->getUser($dsn);
|
|
||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||||
$port = $dsn->getPort();
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
if ('sendinblue' === $scheme) {
|
return (new SendinblueTransport($apiKey, $sender, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new SendinblueTransport($apiKey, $sender, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'sendinblue', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -14,43 +14,72 @@ namespace Symfony\Component\Notifier\Bridge\Sendinblue\Tests;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory;
|
use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory;
|
||||||
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
use Symfony\Component\Notifier\Transport\Dsn;
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
|
|
||||||
final class SendinblueTransportFactoryTest extends TestCase
|
final class SendinblueTransportFactoryTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testCreateWithDsn()
|
public function testCreateWithDsn()
|
||||||
{
|
{
|
||||||
$factory = $this->initFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'sendinblue://apiKey@default?sender=0611223344';
|
$transport = $factory->create(Dsn::fromString('sendinblue://apiKey@host.test?sender=0611223344'));
|
||||||
$transport = $factory->create(Dsn::fromString($dsn));
|
|
||||||
$transport->setHost('host.test');
|
|
||||||
|
|
||||||
$this->assertSame('sendinblue://host.test?sender=0611223344', (string) $transport);
|
$this->assertSame('sendinblue://host.test?sender=0611223344', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithNoPhoneThrowsMalformed()
|
public function testCreateWithMissingOptionSenderThrowsIncompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = $this->initFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
$dsnIncomplete = 'sendinblue://apiKey@default';
|
$factory->create(Dsn::fromString('sendinblue://apiKey@host.test'));
|
||||||
$factory->create(Dsn::fromString($dsnIncomplete));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsSendinblueScheme()
|
public function testCreateWithNoApiKeyThrowsIncompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = $this->initFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$dsn = 'sendinblue://apiKey@default?sender=0611223344';
|
$this->expectException(IncompleteDsnException::class);
|
||||||
$dsnUnsupported = 'foobarmobile://apiKey@default?sender=0611223344';
|
|
||||||
|
|
||||||
$this->assertTrue($factory->supports(Dsn::fromString($dsn)));
|
$factory->create(Dsn::fromString('sendinblue://default?sender=0611223344'));
|
||||||
$this->assertFalse($factory->supports(Dsn::fromString($dsnUnsupported)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initFactory(): SendinblueTransportFactory
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertTrue($factory->supports(Dsn::fromString('sendinblue://apiKey@default?sender=0611223344')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://apiKey@default?sender=0611223344')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://apiKey@default?sender=0611223344'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
|
// unsupported scheme and missing "from" option
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://apiKey@host'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createFactory(): SendinblueTransportFactory
|
||||||
{
|
{
|
||||||
return new SendinblueTransportFactory();
|
return new SendinblueTransportFactory();
|
||||||
}
|
}
|
||||||
|
@ -25,22 +25,22 @@ final class SendinblueTransportTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testToStringContainsProperties()
|
public function testToStringContainsProperties()
|
||||||
{
|
{
|
||||||
$transport = $this->initTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertSame('sendinblue://host.test?sender=0611223344', (string) $transport);
|
$this->assertSame('sendinblue://host.test?sender=0611223344', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsMessageInterface()
|
public function testSupportsMessageInterface()
|
||||||
{
|
{
|
||||||
$transport = $this->initTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->initTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
@ -60,17 +60,15 @@ final class SendinblueTransportTest extends TestCase
|
|||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
$transport = $this->initTransport($client);
|
$transport = $this->createTransport($client);
|
||||||
|
|
||||||
$this->expectException(TransportException::class);
|
$this->expectException(TransportException::class);
|
||||||
$this->expectExceptionMessage('Unable to send the SMS: bad request');
|
$this->expectExceptionMessage('Unable to send the SMS: bad request');
|
||||||
$transport->send(new SmsMessage('phone', 'testMessage'));
|
$transport->send(new SmsMessage('phone', 'testMessage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initTransport(?HttpClientInterface $client = null): SendinblueTransport
|
private function createTransport(?HttpClientInterface $client = null): SendinblueTransport
|
||||||
{
|
{
|
||||||
return (new SendinblueTransport(
|
return (new SendinblueTransport('api-key', '0611223344', $client ?: $this->createMock(HttpClientInterface::class)))->setHost('host.test');
|
||||||
'api-key', '0611223344', $client ?: $this->createMock(HttpClientInterface::class)
|
|
||||||
))->setHost('host.test');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,9 @@ final class SinchTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['id']);
|
$sentMessage->setMessageId($success['id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ final class SinchTransportTest extends TestCase
|
|||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->createTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
@ -7,28 +7,24 @@ DSN example
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
SLACK_DSN=slack://default/ID
|
|
||||||
```
|
|
||||||
|
|
||||||
where:
|
|
||||||
- `ID` is your webhook id (e.g. `/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX`)
|
|
||||||
|
|
||||||
in this case:
|
|
||||||
```
|
|
||||||
SLACK_DSN=slack://default/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX
|
|
||||||
```
|
|
||||||
|
|
||||||
DSN example
|
|
||||||
-----------
|
|
||||||
|
|
||||||
```
|
|
||||||
// .env file
|
|
||||||
SLACK_DSN=slack://TOKEN@default?channel=CHANNEL
|
SLACK_DSN=slack://TOKEN@default?channel=CHANNEL
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `TOKEN` is your Bot User OAuth Access Token
|
- `TOKEN` is your Bot User OAuth Access Token (they begin with `xoxb-`)
|
||||||
- `CHANNEL` is a Channel, private group, or IM channel to send message to. Can be an encoded ID, or a name
|
- `CHANNEL` is a channel, private group, or IM channel to send message to, it can be an encoded ID, or a name.
|
||||||
|
|
||||||
|
valid DSN's are:
|
||||||
|
```
|
||||||
|
SLACK_DSN=slack://xoxb-......@default?channel=my-channel-name
|
||||||
|
SLACK_DSN=slack://xoxb-......@default?channel=@fabien
|
||||||
|
```
|
||||||
|
|
||||||
|
invalid DSN's are:
|
||||||
|
```
|
||||||
|
SLACK_DSN=slack://xoxb-......@default?channel=#my-channel-name
|
||||||
|
SLACK_DSN=slack://xoxb-......@default?channel=fabien
|
||||||
|
```
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
@ -59,6 +59,7 @@ final class SlackTransport extends AbstractTransport
|
|||||||
if (!$message instanceof ChatMessage) {
|
if (!$message instanceof ChatMessage) {
|
||||||
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, ChatMessage::class, get_debug_type($message)));
|
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, ChatMessage::class, get_debug_type($message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message->getOptions() && !$message->getOptions() instanceof SlackOptions) {
|
if ($message->getOptions() && !$message->getOptions() instanceof SlackOptions) {
|
||||||
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, SlackOptions::class));
|
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, SlackOptions::class));
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock;
|
|||||||
|
|
||||||
final class SlackSectionBlockTest extends TestCase
|
final class SlackSectionBlockTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testCanBeInstantiated(): void
|
public function testCanBeInstantiated()
|
||||||
{
|
{
|
||||||
$section = new SlackSectionBlock();
|
$section = new SlackSectionBlock();
|
||||||
$section->text('section text');
|
$section->text('section text');
|
||||||
@ -44,7 +44,7 @@ final class SlackSectionBlockTest extends TestCase
|
|||||||
], $section->toArray());
|
], $section->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testThrowsWhenFieldsLimitReached(): void
|
public function testThrowsWhenFieldsLimitReached()
|
||||||
{
|
{
|
||||||
$section = new SlackSectionBlock();
|
$section = new SlackSectionBlock();
|
||||||
for ($i = 0; $i < 10; ++$i) {
|
for ($i = 0; $i < 10; ++$i) {
|
||||||
|
@ -22,44 +22,55 @@ final class SlackTransportFactoryTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testCreateWithDsn()
|
public function testCreateWithDsn()
|
||||||
{
|
{
|
||||||
$factory = new SlackTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$transport = $factory->create(Dsn::fromString('slack://testUser@testHost/?channel=testChannel'));
|
$transport = $factory->create(Dsn::fromString('slack://testUser@host.test/?channel=testChannel'));
|
||||||
|
|
||||||
$this->assertSame('slack://testHost?channel=testChannel', (string) $transport);
|
$this->assertSame('slack://host.test?channel=testChannel', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithDeprecatedDsn()
|
public function testCreateWithDeprecatedDsn()
|
||||||
{
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
$this->expectExceptionMessage('Support for Slack webhook DSN has been dropped since 5.2 (maybe you haven\'t updated the DSN when upgrading from 5.1).');
|
$this->expectExceptionMessage('Support for Slack webhook DSN has been dropped since 5.2 (maybe you haven\'t updated the DSN when upgrading from 5.1).');
|
||||||
|
|
||||||
$factory = new SlackTransportFactory();
|
|
||||||
$factory->create(Dsn::fromString('slack://default/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX'));
|
$factory->create(Dsn::fromString('slack://default/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithNoTokenThrowsMalformed()
|
public function testCreateWithNoTokenThrowsInclompleteDsnException()
|
||||||
{
|
{
|
||||||
$factory = new SlackTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
$factory->create(Dsn::fromString(sprintf('slack://%s/?channel=%s', 'testHost', 'testChannel')));
|
$factory->create(Dsn::fromString('slack://host.test?channel=testChannel'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsScheme()
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new SlackTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->assertTrue($factory->supports(Dsn::fromString('slack://host/?channel=testChannel')));
|
$this->assertTrue($factory->supports(Dsn::fromString('slack://host?channel=testChannel')));
|
||||||
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/?channel=testChannel')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNonSlackSchemeThrows()
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
{
|
{
|
||||||
$factory = new SlackTransportFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host?channel=testChannel')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(UnsupportedSchemeException::class);
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://host?channel=testChannel'));
|
||||||
|
}
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('somethingElse://user:pwd@host/?channel=testChannel'));
|
private function createFactory(): SlackTransportFactory
|
||||||
|
{
|
||||||
|
return new SlackTransportFactory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,9 @@ final class SlackTransportTest extends TestCase
|
|||||||
$channel = 'test Channel'; // invalid channel name to test url encoding of the channel
|
$channel = 'test Channel'; // invalid channel name to test url encoding of the channel
|
||||||
|
|
||||||
$transport = new SlackTransport('testToken', $channel, $this->createMock(HttpClientInterface::class));
|
$transport = new SlackTransport('testToken', $channel, $this->createMock(HttpClientInterface::class));
|
||||||
$transport->setHost('testHost');
|
$transport->setHost('host.test');
|
||||||
|
|
||||||
$this->assertSame('slack://testHost?channel=test+Channel', (string) $transport);
|
$this->assertSame('slack://host.test?channel=test+Channel', (string) $transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportsChatMessage()
|
public function testSupportsChatMessage()
|
||||||
@ -46,10 +46,10 @@ final class SlackTransportTest extends TestCase
|
|||||||
|
|
||||||
public function testSendNonChatMessageThrowsLogicException()
|
public function testSendNonChatMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$this->expectException(LogicException::class);
|
|
||||||
|
|
||||||
$transport = new SlackTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
|
$transport = new SlackTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
|
||||||
|
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
$transport->send($this->createMock(MessageInterface::class));
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
SMSAPI Notifier
|
SMSAPI Notifier
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Provides Smsapi integration for Symfony Notifier.
|
Provides [Smsapi](https://ssl.smsapi.pl) integration for Symfony Notifier.
|
||||||
|
|
||||||
DSN example
|
DSN example
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
|
||||||
SMSAPI_DSN=smsapi://TOKEN@default?from=FROM
|
SMSAPI_DSN=smsapi://TOKEN@default?from=FROM
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `TOKEN` is API Token (OAuth)
|
- `TOKEN` is your API Token (OAuth)
|
||||||
- `FROM` is sender name
|
- `FROM` is the sender name
|
||||||
|
|
||||||
See your account info at https://ssl.smsapi.pl/
|
See your account info at https://ssl.smsapi.pl/
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Marcin Szepczynski <szepczynski@gmail.com>
|
* @author Marcin Szepczynski <szepczynski@gmail.com>
|
||||||
|
*
|
||||||
* @experimental in 5.2
|
* @experimental in 5.2
|
||||||
*/
|
*/
|
||||||
final class SmsapiTransport extends AbstractTransport
|
final class SmsapiTransport extends AbstractTransport
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Notifier\Bridge\Smsapi;
|
namespace Symfony\Component\Notifier\Bridge\Smsapi;
|
||||||
|
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
||||||
use Symfony\Component\Notifier\Transport\Dsn;
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
@ -18,6 +19,7 @@ use Symfony\Component\Notifier\Transport\TransportInterface;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Marcin Szepczynski <szepczynski@gmail.com>
|
* @author Marcin Szepczynski <szepczynski@gmail.com>
|
||||||
|
*
|
||||||
* @experimental in 5.2
|
* @experimental in 5.2
|
||||||
*/
|
*/
|
||||||
class SmsapiTransportFactory extends AbstractTransportFactory
|
class SmsapiTransportFactory extends AbstractTransportFactory
|
||||||
@ -28,16 +30,22 @@ class SmsapiTransportFactory extends AbstractTransportFactory
|
|||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
$authToken = $dsn->getUser();
|
|
||||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
|
||||||
$from = $dsn->getOption('from');
|
|
||||||
$port = $dsn->getPort();
|
|
||||||
|
|
||||||
if ('smsapi' === $scheme) {
|
if ('smsapi' !== $scheme) {
|
||||||
return (new SmsapiTransport($authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
throw new UnsupportedSchemeException($dsn, 'smsapi', $this->getSupportedSchemes());
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'smsapi', $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 SmsapiTransport($authToken, $from, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
<?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\Smsapi\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory;
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
|
|
||||||
|
final class SmsapiTransportFactoryTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCreateWithDsn()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$transport = $factory->create(Dsn::fromString('smsapi://token@host.test?from=testFrom'));
|
||||||
|
|
||||||
|
$this->assertSame('smsapi://host.test?from=testFrom', (string) $transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithMissingOptionFromThrowsIncompleteDsnException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
|
$factory->create(Dsn::fromString('smsapi://token@host'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithNoTokenThrowsIncompleteDsnException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
$factory->create(Dsn::fromString('smsapi://host.test?from=testFrom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertTrue($factory->supports(Dsn::fromString('smsapi://host?from=testFrom')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host?from=testFrom')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://token@host?from=testFrom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
|
// unsupported scheme and missing "from" option
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://token@host'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createFactory(): SmsapiTransportFactory
|
||||||
|
{
|
||||||
|
return new SmsapiTransportFactory();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?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\Smsapi\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransport;
|
||||||
|
use Symfony\Component\Notifier\Exception\LogicException;
|
||||||
|
use Symfony\Component\Notifier\Message\MessageInterface;
|
||||||
|
use Symfony\Component\Notifier\Message\SmsMessage;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
final class SmsapiTransportTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testToStringContainsProperties()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->assertSame('smsapi://test.host?from=testFrom', (string) $transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsMessageInterface()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->assertTrue($transport->supports(new SmsMessage('0611223344', 'Hello!')));
|
||||||
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSendNonChatMessageThrows()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createTransport(): SmsapiTransport
|
||||||
|
{
|
||||||
|
return (new SmsapiTransport('testToken', 'testFrom', $this->createMock(HttpClientInterface::class)))->setHost('test.host');
|
||||||
|
}
|
||||||
|
}
|
@ -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 Smsapi 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>
|
@ -21,10 +21,9 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
|||||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TelegramTransport.
|
|
||||||
*
|
|
||||||
* To get the chat id, send a message in Telegram with the user you want
|
* To get the chat id, send a message in Telegram with the user you want
|
||||||
* and then curl 'https://api.telegram.org/bot%token%/getUpdates' | json_pp
|
* and then execute curl 'https://api.telegram.org/bot%token%/getUpdates' | json_pp
|
||||||
|
* command.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*
|
*
|
||||||
@ -96,9 +95,9 @@ final class TelegramTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['result']['message_id']);
|
$sentMessage->setMessageId($success['result']['message_id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ final class TelegramTransportFactoryTest extends TestCase
|
|||||||
$factory = $this->createFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('telegram://simpleToken@host.test?channel=testChannel'));
|
$factory->create(Dsn::fromString('telegram://simpleToken@host.test?channel=testChannel'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ final class TelegramTransportFactoryTest extends TestCase
|
|||||||
$factory = $this->createFactory();
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
$this->expectException(IncompleteDsnException::class);
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
$factory->create(Dsn::fromString('telegram://host.test?channel=testChannel'));
|
$factory->create(Dsn::fromString('telegram://host.test?channel=testChannel'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ final class TwilioTransportTest extends TestCase
|
|||||||
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendNonSmsMessageThrowsException()
|
public function testSendNonSmsMessageThrowsLogicException()
|
||||||
{
|
{
|
||||||
$transport = $this->createTransport();
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ final class TwilioTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['sid']);
|
$sentMessage->setMessageId($success['sid']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
Zulip Notifier
|
Zulip Notifier
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Provides Zulip integration for Symfony Notifier.
|
Provides [Zulip](https://zulip.comw) integration for Symfony Notifier.
|
||||||
|
|
||||||
DSN example
|
DSN example
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
```
|
```
|
||||||
// .env file
|
ZULIP_DSN=zulip://EMAIL:TOKEN@default?channel=CHANNEL
|
||||||
ZULIP_DSN=zulip://EMAIL:TOKEN@default?channel=Channel
|
|
||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
- `EMAIL` is your Zulip email
|
- `EMAIL` is your Zulip email
|
||||||
- `TOKEN` is your Zulip token
|
- `TOKEN` is your Zulip token
|
||||||
- `Channel` is the channel
|
- `CHANNEL` is the channel
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
<?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\Zulip\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory;
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
|
|
||||||
|
final class ZulipTransportFactoryTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCreateWithDsn()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$transport = $factory->create(Dsn::fromString('zulip://email:token@host.test?channel=testChannel'));
|
||||||
|
|
||||||
|
$this->assertSame('zulip://host.test?channel=testChannel', (string) $transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithMissingOptionChannelThrowsIncompleteDsnException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
|
||||||
|
$factory->create(Dsn::fromString('zulip://email:token@host'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithOnlyEmailOrTokenThrowsIncompleteDsnException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(IncompleteDsnException::class);
|
||||||
|
$factory->create(Dsn::fromString('zulip://testOneOfEmailOrToken@host.test?channel=testChannel'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsTrueWithSupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertTrue($factory->supports(Dsn::fromString('zulip://host?channel=testChannel')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsReturnsFalseWithUnsupportedScheme()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host?channel=testChannel')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeException()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://email:token@host?channel=testChannel'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedSchemeThrowsUnsupportedSchemeExceptionEvenIfRequiredOptionIsMissing()
|
||||||
|
{
|
||||||
|
$factory = $this->createFactory();
|
||||||
|
|
||||||
|
$this->expectException(UnsupportedSchemeException::class);
|
||||||
|
|
||||||
|
// unsupported scheme and missing "channel" option
|
||||||
|
$factory->create(Dsn::fromString('somethingElse://email:token@host'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createFactory(): ZulipTransportFactory
|
||||||
|
{
|
||||||
|
return new ZulipTransportFactory();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?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\Zulip\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransport;
|
||||||
|
use Symfony\Component\Notifier\Exception\LogicException;
|
||||||
|
use Symfony\Component\Notifier\Message\ChatMessage;
|
||||||
|
use Symfony\Component\Notifier\Message\MessageInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
final class ZulipTransportTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testToStringContainsProperties()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->assertSame('zulip://test.host?channel=testChannel', (string) $transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsChatMessage()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
|
||||||
|
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSendNonChatMessageThrows()
|
||||||
|
{
|
||||||
|
$transport = $this->createTransport();
|
||||||
|
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
$transport->send($this->createMock(MessageInterface::class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createTransport(): ZulipTransport
|
||||||
|
{
|
||||||
|
return (new ZulipTransport('testEmail', 'testToken', 'testChannel', $this->createMock(HttpClientInterface::class)))->setHost('test.host');
|
||||||
|
}
|
||||||
|
}
|
@ -93,9 +93,9 @@ class ZulipTransport extends AbstractTransport
|
|||||||
|
|
||||||
$success = $response->toArray(false);
|
$success = $response->toArray(false);
|
||||||
|
|
||||||
$message = new SentMessage($message, (string) $this);
|
$sentMessage = new SentMessage($message, (string) $this);
|
||||||
$message->setMessageId($success['id']);
|
$sentMessage->setMessageId($success['id']);
|
||||||
|
|
||||||
return $message;
|
return $sentMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Notifier\Bridge\Zulip;
|
namespace Symfony\Component\Notifier\Bridge\Zulip;
|
||||||
|
|
||||||
|
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
|
||||||
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
|
||||||
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
|
||||||
use Symfony\Component\Notifier\Transport\Dsn;
|
use Symfony\Component\Notifier\Transport\Dsn;
|
||||||
@ -24,27 +25,30 @@ use Symfony\Component\Notifier\Transport\TransportInterface;
|
|||||||
class ZulipTransportFactory extends AbstractTransportFactory
|
class ZulipTransportFactory extends AbstractTransportFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* @return ZulipTransport
|
||||||
*/
|
*/
|
||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$scheme = $dsn->getScheme();
|
$scheme = $dsn->getScheme();
|
||||||
|
|
||||||
|
if ('zulip' !== $scheme) {
|
||||||
|
throw new UnsupportedSchemeException($dsn, 'zulip', $this->getSupportedSchemes());
|
||||||
|
}
|
||||||
|
|
||||||
$email = $this->getUser($dsn);
|
$email = $this->getUser($dsn);
|
||||||
$token = $this->getPassword($dsn);
|
$token = $this->getPassword($dsn);
|
||||||
$channel = $dsn->getOption('channel');
|
$channel = $dsn->getOption('channel');
|
||||||
|
|
||||||
|
if (!$channel) {
|
||||||
|
throw new IncompleteDsnException('Missing channel.', $dsn->getOriginalDsn());
|
||||||
|
}
|
||||||
|
|
||||||
$host = $dsn->getHost();
|
$host = $dsn->getHost();
|
||||||
$port = $dsn->getPort();
|
$port = $dsn->getPort();
|
||||||
|
|
||||||
if ('zulip' === $scheme) {
|
return (new ZulipTransport($email, $token, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
||||||
return (new ZulipTransport($email, $token, $channel, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, 'zulip', $this->getSupportedSchemes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function getSupportedSchemes(): array
|
protected function getSupportedSchemes(): array
|
||||||
{
|
{
|
||||||
return ['zulip'];
|
return ['zulip'];
|
||||||
|
31
src/Symfony/Component/Notifier/Bridge/Zulip/phpunit.xml.dist
Normal file
31
src/Symfony/Component/Notifier/Bridge/Zulip/phpunit.xml.dist
Normal file
@ -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 Zulip 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>
|
Reference in New Issue
Block a user