diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Block/SlackPlainTextInputBlock.php b/src/Symfony/Component/Notifier/Bridge/Slack/Block/SlackPlainTextInputBlock.php new file mode 100644 index 0000000000000..22fcdcd3545ae --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Block/SlackPlainTextInputBlock.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Slack\Block; + +final class SlackPlainTextInputBlock extends AbstractSlackBlock +{ + private const LABEL_LIMIT = 150; + private const ACTION_ID_LIMIT = 255; + private const PLACEHOLDER_LIMIT = 150; + + public function __construct(string $labelText, string $actionId, ?string $placeholderText = null) + { + if (\strlen($labelText) > self::LABEL_LIMIT) { + throw new \LengthException(\sprintf('Maximum length for the label text is %d characters.', self::LABEL_LIMIT)); + } + + if (\strlen($actionId) > self::ACTION_ID_LIMIT) { + throw new \LengthException(\sprintf('Maximum length for the action ID is %d characters.', self::ACTION_ID_LIMIT)); + } + + if ($placeholderText && \strlen($placeholderText) > self::PLACEHOLDER_LIMIT) { + throw new \LengthException(\sprintf('Maximum length for the placeholder text is %d characters.', self::PLACEHOLDER_LIMIT)); + } + $this->options = [ + 'type' => 'input', + 'element' => [ + 'type' => 'plain_text_input', + 'action_id' => $actionId, + ], + 'label' => [ + 'type' => 'plain_text', + 'text' => $labelText, + ], + ]; + + if ($placeholderText) { + $this->options['element']['placeholder'] = [ + 'type' => 'plain_text', + 'text' => $placeholderText, + ]; + } + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/README.md b/src/Symfony/Component/Notifier/Bridge/Slack/README.md index 5e260b534e910..5c03b588ddea4 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/README.md +++ b/src/Symfony/Component/Notifier/Bridge/Slack/README.md @@ -242,6 +242,28 @@ $chatMessage->options($options); $chatter->send($chatMessage); ``` +Adding a Plain Text Input to a Message +---------------------------- +To add a simple text input field to your Slack message, use the `SlackPlainTextInputBlock` class. +```php +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackPlainTextInputBlock; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Enter your feedback'); + +$options = (new SlackOptions()) +->block( +new SlackPlainTextInputBlock('Your Feedback', 'feedback_action_id', 'Type your feedback here...') +); + +// Add the custom options to the chat message and send the message +$chatMessage->options($options); + +$chatter->send($chatMessage); +``` + + Sending a Message as a Reply ---------------------------- diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/Block/SlackPlainTextInputBlockTest.php b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/Block/SlackPlainTextInputBlockTest.php new file mode 100644 index 0000000000000..007a4640e9b56 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/Block/SlackPlainTextInputBlockTest.php @@ -0,0 +1,66 @@ +assertSame([ + 'type' => 'input', + 'element' => [ + 'type' => 'plain_text_input', + 'action_id' => 'time_spent_input', + 'placeholder' => [ + 'type' => 'plain_text', + 'text' => 'Enter some text here', + ], + ], + 'label' => [ + 'type' => 'plain_text', + 'text' => 'Time spent', + ], + ], $block->toArray()); + } + + public function testCanBeInstantiatedWithoutPlaceholder() + { + $block = new SlackPlainTextInputBlock('Time spent', 'time_spent_input'); + $this->assertSame([ + 'type' => 'input', + 'element' => [ + 'type' => 'plain_text_input', + 'action_id' => 'time_spent_input', + ], + 'label' => [ + 'type' => 'plain_text', + 'text' => 'Time spent', + ], + ], $block->toArray()); + } + + public function testThrowsWhenLabelExceedsCharacterLimit() + { + $this->expectException(\LengthException::class); + $this->expectExceptionMessage('Maximum length for the label text is 150 characters.'); + new SlackPlainTextInputBlock(str_repeat('a', 151), 'time_spent_input'); + } + + public function testThrowsWhenActionIdExceedsCharacterLimit() + { + $this->expectException(\LengthException::class); + $this->expectExceptionMessage('Maximum length for the action ID is 255 characters.'); + new SlackPlainTextInputBlock('Time spent', str_repeat('a', 256)); + } + + public function testThrowsWhenPlaceholderExceedsCharacterLimit() + { + $this->expectException(\LengthException::class); + $this->expectExceptionMessage('Maximum length for the placeholder text is 150 characters.'); + new SlackPlainTextInputBlock('Time spent', 'time_spent_input', str_repeat('a', 151)); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php index b0a54d5e0c611..9add78d0498eb 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Notifier\Bridge\Slack\Tests; use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackPlainTextInputBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock; use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; use Symfony\Component\Notifier\Bridge\Slack\SlackSentMessage; use Symfony\Component\Notifier\Bridge\Slack\SlackTransport; @@ -330,4 +332,44 @@ public function testUpdateMessage() $this->assertSame('1503435956.000247', $sentMessage->getMessageId()); } + + public function testSlackTransportSendsMessageWithInputBlock() + { + $channel = 'testChannel'; + $message = 'testMessage'; + + $response = $this->createMock(ResponseInterface::class); + + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['ok' => true, 'ts' => '1503435956.000247', 'channel' => 'C123456'])); + + $options = new SlackOptions(); + + $options->block((new SlackSectionBlock())->text($message)); + + $options->block((new SlackPlainTextInputBlock('Time spent', 'time_spent_input', 'Enter some text here'))); + + $expectedBody = json_encode([ + 'blocks' => $options->toArray()['blocks'], + 'channel' => $channel, + 'text' => $message, + ]); + + $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertJsonStringEqualsJsonString($expectedBody, $options['body']); + + return $response; + }); + + $transport = self::createTransport($client, $channel); + + $sentMessage = $transport->send(new ChatMessage('testMessage', $options)); + + $this->assertSame('1503435956.000247', $sentMessage->getMessageId()); + } }