From 070174e877d2ce05efcccfaf5cdaf409f69a6c8a Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 20 Jun 2024 17:52:34 +0200 Subject: [PATCH 1/6] Prefix all sprintf() calls --- ClickSendTransport.php | 8 ++++---- Tests/ClickSendTransportTest.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ClickSendTransport.php b/ClickSendTransport.php index 76abd4b..8d8987e 100644 --- a/ClickSendTransport.php +++ b/ClickSendTransport.php @@ -51,7 +51,7 @@ public function __toString(): string 'from_email' => $this->fromEmail, ]); - return sprintf('clicksend://%s%s', $this->getEndpoint(), $query ? '?'.http_build_query($query, '', '&') : ''); + return \sprintf('clicksend://%s%s', $this->getEndpoint(), $query ? '?'.http_build_query($query, '', '&') : ''); } public function supports(MessageInterface $message): bool @@ -68,7 +68,7 @@ protected function doSend(MessageInterface $message): SentMessage throw new UnsupportedMessageTypeException(__CLASS__, SmsMessage::class, $message); } - $endpoint = sprintf('https://%s/v3/sms/send', $this->getEndpoint()); + $endpoint = \sprintf('https://%s/v3/sms/send', $this->getEndpoint()); $options = $message->getOptions()?->toArray() ?? []; $options['body'] = $message->getSubject(); @@ -78,7 +78,7 @@ protected function doSend(MessageInterface $message): SentMessage $options['from_email'] ?? $this->fromEmail; if (isset($options['from']) && !preg_match('/^[a-zA-Z0-9\s]{3,11}$/', $options['from']) && !preg_match('/^\+[1-9]\d{1,14}$/', $options['from'])) { - throw new InvalidArgumentException(sprintf('The "From" number "%s" is not a valid phone number, shortcode, or alphanumeric sender ID.', $options['from'])); + throw new InvalidArgumentException(\sprintf('The "From" number "%s" is not a valid phone number, shortcode, or alphanumeric sender ID.', $options['from'])); } if ($options['list_id'] ?? false) { @@ -98,7 +98,7 @@ protected function doSend(MessageInterface $message): SentMessage if (200 !== $statusCode) { $error = $response->getContent(false); - throw new TransportException(sprintf('Unable to send the SMS - "%s".', $error ?: 'unknown failure'), $response); + throw new TransportException(\sprintf('Unable to send the SMS - "%s".', $error ?: 'unknown failure'), $response); } return new SentMessage($message, (string) $this); diff --git a/Tests/ClickSendTransportTest.php b/Tests/ClickSendTransportTest.php index 166bb10..6afae44 100644 --- a/Tests/ClickSendTransportTest.php +++ b/Tests/ClickSendTransportTest.php @@ -49,7 +49,7 @@ public function testInvalidArgumentExceptionIsThrownIfFromIsInvalid(string $from $transport = $this->createTransport(null, $from); $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('The "From" number "%s" is not a valid phone number, shortcode, or alphanumeric sender ID.', $from)); + $this->expectExceptionMessage(\sprintf('The "From" number "%s" is not a valid phone number, shortcode, or alphanumeric sender ID.', $from)); $transport->send(new SmsMessage('+33612345678', 'Hello!')); } From c2d1ed54faa3eb02b96bc8626355c7f148b5f633 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Wed, 3 Jul 2024 16:05:29 +0200 Subject: [PATCH 2/6] [Notifier] Unify composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b3c7c27..d925ce6 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "symfony/event-dispatcher": "^6.4|^7.0" }, "autoload": { - "psr-4": {"Symfony\\Component\\Notifier\\Bridge\\ClickSend\\": ""}, + "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\ClickSend\\": "" }, "exclude-from-classmap": [ "/Tests/" ] From 06644ce3e3a5df69707275786cbc67bac11d85d1 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 22 Jul 2024 10:27:43 +0200 Subject: [PATCH 3/6] Use CPP where possible --- ClickSendOptions.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ClickSendOptions.php b/ClickSendOptions.php index ea9b71f..2995b73 100644 --- a/ClickSendOptions.php +++ b/ClickSendOptions.php @@ -18,11 +18,9 @@ */ final class ClickSendOptions implements MessageOptionsInterface { - private array $options; - - public function __construct(array $options = []) - { - $this->options = $options; + public function __construct( + private array $options = [], + ) { } public function getRecipientId(): ?string From 5d2486d96c1a4e3430a4ea163dba45737510b401 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 18 Sep 2024 13:58:19 +0200 Subject: [PATCH 4/6] deprecate the TransportFactoryTestCase --- Tests/ClickSendTransportFactoryTest.php | 7 +++++-- composer.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Tests/ClickSendTransportFactoryTest.php b/Tests/ClickSendTransportFactoryTest.php index 670447f..6640d0c 100644 --- a/Tests/ClickSendTransportFactoryTest.php +++ b/Tests/ClickSendTransportFactoryTest.php @@ -12,10 +12,13 @@ namespace Symfony\Component\Notifier\Bridge\ClickSend\Tests; use Symfony\Component\Notifier\Bridge\ClickSend\ClickSendTransportFactory; -use Symfony\Component\Notifier\Test\TransportFactoryTestCase; +use Symfony\Component\Notifier\Test\AbstractTransportFactoryTestCase; +use Symfony\Component\Notifier\Test\IncompleteDsnTestTrait; -final class ClickSendTransportFactoryTest extends TransportFactoryTestCase +final class ClickSendTransportFactoryTest extends AbstractTransportFactoryTestCase { + use IncompleteDsnTestTrait; + public function createFactory(): ClickSendTransportFactory { return new ClickSendTransportFactory(); diff --git a/composer.json b/composer.json index d925ce6..1676fea 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "require": { "php": ">=8.2", "symfony/http-client": "^6.4|^7.0", - "symfony/notifier": "^6.4|^7.0" + "symfony/notifier": "^7.2" }, "require-dev": { "symfony/event-dispatcher": "^6.4|^7.0" From 4e2dd71fa31111f0fec8b48b721aa3c4bab96e2d Mon Sep 17 00:00:00 2001 From: Fabien Salathe Date: Sat, 24 May 2025 01:18:01 +0900 Subject: [PATCH 5/6] [Notifier] Fix Clicksend transport --- ClickSendTransport.php | 2 +- Tests/ClickSendTransportTest.php | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ClickSendTransport.php b/ClickSendTransport.php index 0e5bd14..f60e4e2 100644 --- a/ClickSendTransport.php +++ b/ClickSendTransport.php @@ -87,7 +87,7 @@ protected function doSend(MessageInterface $message): SentMessage $response = $this->client->request('POST', $endpoint, [ 'auth_basic' => [$this->apiUsername, $this->apiKey], - 'json' => array_filter($options), + 'json' => ['messages' => [array_filter($options)]], ]); try { diff --git a/Tests/ClickSendTransportTest.php b/Tests/ClickSendTransportTest.php index 166bb10..ba7923a 100644 --- a/Tests/ClickSendTransportTest.php +++ b/Tests/ClickSendTransportTest.php @@ -63,10 +63,14 @@ public function testNoInvalidArgumentExceptionIsThrownIfFromIsValid(string $from $response = $this->createMock(ResponseInterface::class); $response->expects(self::exactly(2))->method('getStatusCode')->willReturn(200); $response->expects(self::once())->method('getContent')->willReturn(''); - $client = new MockHttpClient(function (string $method, string $url) use ($response): ResponseInterface { + $client = new MockHttpClient(function (string $method, string $url, array $options) use ($response): ResponseInterface { self::assertSame('POST', $method); self::assertSame('https://rest.clicksend.com/v3/sms/send', $url); + $body = json_decode($options['body'], true); + self::assertIsArray($body); + self::assertArrayHasKey('messages', $body); + return $response; }); $transport = $this->createTransport($client, $from); From b596938fc52f9f3377c6e9f304e90f597a0af71c Mon Sep 17 00:00:00 2001 From: alifanau Date: Fri, 30 May 2025 03:16:57 +0300 Subject: [PATCH 6/6] Fix: Lack of recipient in case DSN does not have optional LIST_ID parameter. According to https://developers.clicksend.com/docs/messaging/sms/other/send-sms#other/send-sms/t=request&path=messages/list_id we need to provide the "to" parameter or the "list_id" parameter. Also fixed forwarding FROM_EMAIL parameter to request. --- ClickSendTransport.php | 4 ++-- Tests/ClickSendTransportTest.php | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/ClickSendTransport.php b/ClickSendTransport.php index f60e4e2..13f839b 100644 --- a/ClickSendTransport.php +++ b/ClickSendTransport.php @@ -75,13 +75,13 @@ protected function doSend(MessageInterface $message): SentMessage $options['from'] = $message->getFrom() ?: $this->from; $options['source'] ??= $this->source; $options['list_id'] ??= $this->listId; - $options['from_email'] ?? $this->fromEmail; + $options['from_email'] ??= $this->fromEmail; if (isset($options['from']) && !preg_match('/^[a-zA-Z0-9\s]{3,11}$/', $options['from']) && !preg_match('/^\+[1-9]\d{1,14}$/', $options['from'])) { throw new InvalidArgumentException(sprintf('The "From" number "%s" is not a valid phone number, shortcode, or alphanumeric sender ID.', $options['from'])); } - if ($options['list_id'] ?? false) { + if (!$options['list_id']) { $options['to'] = $message->getPhone(); } diff --git a/Tests/ClickSendTransportTest.php b/Tests/ClickSendTransportTest.php index ba7923a..c7d1fa8 100644 --- a/Tests/ClickSendTransportTest.php +++ b/Tests/ClickSendTransportTest.php @@ -24,7 +24,7 @@ final class ClickSendTransportTest extends TransportTestCase { - public static function createTransport(?HttpClientInterface $client = null, string $from = 'test_from', string $source = 'test_source', int $listId = 99, string $fromEmail = 'foo@bar.com'): ClickSendTransport + public static function createTransport(?HttpClientInterface $client = null, ?string $from = 'test_from', ?string $source = 'test_source', ?int $listId = 99, ?string $fromEmail = 'foo@bar.com'): ClickSendTransport { return new ClickSendTransport('test_username', 'test_key', $from, $source, $listId, $fromEmail, $client ?? new MockHttpClient()); } @@ -70,6 +70,10 @@ public function testNoInvalidArgumentExceptionIsThrownIfFromIsValid(string $from $body = json_decode($options['body'], true); self::assertIsArray($body); self::assertArrayHasKey('messages', $body); + $message = reset($body['messages']); + self::assertArrayHasKey('from_email', $message); + self::assertArrayHasKey('list_id', $message); + self::assertArrayNotHasKey('to', $message); return $response; }); @@ -77,6 +81,29 @@ public function testNoInvalidArgumentExceptionIsThrownIfFromIsValid(string $from $transport->send($message); } + public function testNoInvalidArgumentExceptionIsThrownIfFromIsValidWithoutOptionalParameters() + { + $message = new SmsMessage('+33612345678', 'Hello!'); + $response = $this->createMock(ResponseInterface::class); + $response->expects(self::exactly(2))->method('getStatusCode')->willReturn(200); + $response->expects(self::once())->method('getContent')->willReturn(''); + $client = new MockHttpClient(function (string $method, string $url, array $options) use ($response): ResponseInterface { + self::assertSame('POST', $method); + self::assertSame('https://rest.clicksend.com/v3/sms/send', $url); + + $body = json_decode($options['body'], true); + self::assertIsArray($body); + self::assertArrayHasKey('messages', $body); + $message = reset($body['messages']); + self::assertArrayNotHasKey('list_id', $message); + self::assertArrayHasKey('to', $message); + + return $response; + }); + $transport = $this->createTransport($client, null, null, null, null); + $transport->send($message); + } + public static function toStringProvider(): iterable { yield ['clicksend://rest.clicksend.com?from=test_from&source=test_source&list_id=99&from_email=foo%40bar.com', self::createTransport()];