From ce8388a2797508bd69bc72d7a1892e0479bc007a Mon Sep 17 00:00:00 2001 From: Alden Weddleton Date: Wed, 13 Mar 2019 11:01:52 -0400 Subject: [PATCH] allow setting sns message attributes, other fields --- pkg/sns/SnsMessage.php | 194 +++++++++++++++++++++++++++++- pkg/sns/SnsProducer.php | 20 +++ pkg/sns/Tests/SnsProducerTest.php | 61 ++++++++++ 3 files changed, 273 insertions(+), 2 deletions(-) diff --git a/pkg/sns/SnsMessage.php b/pkg/sns/SnsMessage.php index 7eb3c0d83..f7311d0b0 100644 --- a/pkg/sns/SnsMessage.php +++ b/pkg/sns/SnsMessage.php @@ -6,28 +6,218 @@ use Interop\Queue\Impl\MessageTrait; use Interop\Queue\Message; +use Psr\Http\Message\StreamInterface; class SnsMessage implements Message { use MessageTrait; + /** + * @var string|null + */ private $snsMessageId; - public function __construct(string $body = '', array $properties = [], array $headers = []) - { + /** + * @var string|null + */ + private $messageStructure; + + /** + * @var string|null + */ + private $phoneNumber; + + /** + * @var string|null + */ + private $subject; + + /** + * @var array|null + */ + private $messageAttributes; + + /** + * @var string|null + */ + private $targetArn; + + /** + * SnsMessage constructor. + * + * See AWS documentation for message attribute structure. + * + * @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sns-2010-03-31.html#shape-messageattributevalue + * + * @param string $body + * @param array $properties + * @param array $headers + * @param array|null $messageAttributes + * @param string|null $messageStructure + * @param string|null $phoneNumber + * @param string|null $subject + * @param string|null $targetArn + */ + public function __construct( + string $body = '', + array $properties = [], + array $headers = [], + array $messageAttributes = null, + string $messageStructure = null, + string $phoneNumber = null, + string $subject = null, + string $targetArn = null + ) { $this->body = $body; $this->properties = $properties; $this->headers = $headers; + $this->messageAttributes = $messageAttributes; + $this->messageStructure = $messageStructure; + $this->phoneNumber = $phoneNumber; + $this->subject = $subject; + $this->targetArn = $targetArn; $this->redelivered = false; } + /** + * @return string|null + */ public function getSnsMessageId(): ?string { return $this->snsMessageId; } + /** + * @param string|null $snsMessageId + */ public function setSnsMessageId(?string $snsMessageId): void { $this->snsMessageId = $snsMessageId; } + + /** + * @return string|null + */ + public function getMessageStructure(): ?string + { + return $this->messageStructure; + } + + /** + * @param string|null $messageStructure + */ + public function setMessageStructure(?string $messageStructure): void + { + $this->messageStructure = $messageStructure; + } + + /** + * @return string|null + */ + public function getPhoneNumber(): ?string + { + return $this->phoneNumber; + } + + /** + * @param string|null $phoneNumber + */ + public function setPhoneNumber(?string $phoneNumber): void + { + $this->phoneNumber = $phoneNumber; + } + + /** + * @return string|null + */ + public function getSubject(): ?string + { + return $this->subject; + } + + /** + * @param string|null $subject + */ + public function setSubject(?string $subject): void + { + $this->subject = $subject; + } + + /** + * @return array|null + */ + public function getMessageAttributes(): ?array + { + return $this->messageAttributes; + } + + /** + * @param array|null $messageAttributes + */ + public function setMessageAttributes(?array $messageAttributes): void + { + $this->messageAttributes = $messageAttributes; + } + + /** + * @param string $name + * @param null $default + * + * @return array|null + */ + public function getAttribute(string $name, $default = null) + { + return array_key_exists($name, $this->messageAttributes) ? $this->messageAttributes[$name] : $default; + } + + /** + * Attribute array format: + * [ + * 'BinaryValue' => , + * 'DataType' => '', // REQUIRED + * 'StringValue' => '', + * ]. + * + * @param string $name + * @param array|null $attribute + */ + public function setAttribute(string $name, ?array $attribute): void + { + if (null === $attribute) { + unset($this->messageAttributes[$name]); + } else { + $this->messageAttributes[$name] = $attribute; + } + } + + /** + * @param string $name + * @param string $dataType String, String.Array, Number, or Binary + * @param string|resource|StreamInterface $value + */ + public function addAttribute(string $name, string $dataType, $value): void + { + $valueKey = 'Binary' === $dataType ? 'BinaryValue' : 'StringValue'; + + $this->messageAttributes[$name] = [ + 'DataType' => $dataType, + $valueKey => $value, + ]; + } + + /** + * @return string|null + */ + public function getTargetArn(): ?string + { + return $this->targetArn; + } + + /** + * @param string|null $targetArn + */ + public function setTargetArn(?string $targetArn): void + { + $this->targetArn = $targetArn; + } } diff --git a/pkg/sns/SnsProducer.php b/pkg/sns/SnsProducer.php index b702d10c3..7f440c77b 100644 --- a/pkg/sns/SnsProducer.php +++ b/pkg/sns/SnsProducer.php @@ -57,6 +57,26 @@ public function send(Destination $destination, Message $message): void 'TopicArn' => $topicArn, ]; + if (null !== $message->getMessageAttributes()) { + $arguments['MessageAttributes'] = array_merge( + $arguments['MessageAttributes'], + $message->getMessageAttributes() + ); + } + + if (null !== ($structure = $message->getMessageStructure())) { + $arguments['MessageStructure'] = $structure; + } + if (null !== ($phone = $message->getPhoneNumber())) { + $arguments['PhoneNumber'] = $phone; + } + if (null !== ($subject = $message->getSubject())) { + $arguments['Subject'] = $subject; + } + if (null !== ($targetArn = $message->getTargetArn())) { + $arguments['TargetArn'] = $targetArn; + } + $result = $this->context->getSnsClient()->publish($arguments); if (false == $result->hasKey('MessageId')) { diff --git a/pkg/sns/Tests/SnsProducerTest.php b/pkg/sns/Tests/SnsProducerTest.php index f5a039702..4850b5c1d 100644 --- a/pkg/sns/Tests/SnsProducerTest.php +++ b/pkg/sns/Tests/SnsProducerTest.php @@ -126,6 +126,67 @@ public function testShouldPublish() $producer->send($destination, $message); } + /** + * @throws InvalidMessageException + */ + public function testShouldPublishWithMergedAttributes() + { + $context = $this->createSnsContextMock(); + $client = $this->createSnsClientMock(); + + $context + ->expects($this->once()) + ->method('getSnsClient') + ->will($this->returnValue($client)); + + $expectedArgument = [ + 'Message' => 'message', + 'MessageAttributes' => [ + 'Headers' => [ + 'DataType' => 'String', + 'StringValue' => '[[],[]]', + ], + 'Foo' => [ + 'DataType' => 'String', + 'StringValue' => 'foo-value', + ], + 'Bar' => [ + 'DataType' => 'Binary', + 'BinaryValue' => 'bar-val', + ], + ], + 'TopicArn' => '', + 'MessageStructure' => 'structure', + 'PhoneNumber' => 'phone', + 'Subject' => 'subject', + 'TargetArn' => 'target_arn', + ]; + + $client + ->expects($this->once()) + ->method('publish') + ->with($this->identicalTo($expectedArgument)) + ->willReturn(new Result(['MessageId' => 'theMessageId'])); + + $attributes = [ + 'Foo' => [ + 'DataType' => 'String', + 'StringValue' => 'foo-value', + ], + ]; + + $message = new SnsMessage( + 'message', [], [], $attributes, 'structure', 'phone', + 'subject', 'target_arn' + ); + $message->addAttribute('Bar', 'Binary', 'bar-val'); + + $destination = new SnsDestination('queue-name'); + + $producer = new SnsProducer($context); + $producer->send($destination, $message); + } + /** * @return \PHPUnit_Framework_MockObject_MockObject|SnsContext */