From 22587623f0b3789c4d5a253a3d37eb7d71ed0cef Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Sat, 18 Mar 2017 22:46:10 +0200 Subject: [PATCH 1/3] [client] Allow send objects that implements \JsonSerializable interface. --- pkg/enqueue/Client/MessageProducer.php | 10 ++- .../Tests/Client/MessageProducerTest.php | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/pkg/enqueue/Client/MessageProducer.php b/pkg/enqueue/Client/MessageProducer.php index 820ae0d2d..c10d293ae 100644 --- a/pkg/enqueue/Client/MessageProducer.php +++ b/pkg/enqueue/Client/MessageProducer.php @@ -62,9 +62,6 @@ private function prepareBody(Message $message) $contentType = $contentType ?: 'text/plain'; $body = (string) $body; } elseif (is_array($body)) { - $body = $message->getBody(); - $contentType = $message->getContentType(); - if ($contentType && $contentType !== 'application/json') { throw new \LogicException(sprintf('Content type "application/json" only allowed when body is array')); } @@ -79,6 +76,13 @@ private function prepareBody(Message $message) } }); + $contentType = 'application/json'; + $body = JSON::encode($body); + } elseif ($body instanceof \JsonSerializable) { + if ($contentType && $contentType !== 'application/json') { + throw new \LogicException(sprintf('Content type "application/json" only allowed when body is array')); + } + $contentType = 'application/json'; $body = JSON::encode($body); } else { diff --git a/pkg/enqueue/Tests/Client/MessageProducerTest.php b/pkg/enqueue/Tests/Client/MessageProducerTest.php index b85aa1b98..232904794 100644 --- a/pkg/enqueue/Tests/Client/MessageProducerTest.php +++ b/pkg/enqueue/Tests/Client/MessageProducerTest.php @@ -339,6 +339,81 @@ public function testShouldThrowExceptionIfBodyIsArrayWithObjectsInSubArraysInsid $producer->send($queue, ['foo' => ['bar' => new \stdClass()]]); } + public function testShouldSendJsonSerializableObjectAsJsonString() + { + $object = new class implements \JsonSerializable { + public function jsonSerialize() + { + return ['foo' => 'fooVal']; + } + }; + + $driver = $this->createDriverStub(); + $driver + ->expects($this->once()) + ->method('sendToRouter') + ->willReturnCallback(function (Message $message) { + self::assertSame('{"foo":"fooVal"}', $message->getBody()); + self::assertSame('application/json', $message->getContentType()); + }) + ; + + $producer = new MessageProducer($driver); + $producer->send('topic', $object); + } + + public function testShouldSendMessageJsonSerializableBodyAsJsonString() + { + $object = new class implements \JsonSerializable { + public function jsonSerialize() + { + return ['foo' => 'fooVal']; + } + }; + + $message = new Message(); + $message->setBody($object); + + $driver = $this->createDriverStub(); + $driver + ->expects($this->once()) + ->method('sendToRouter') + ->willReturnCallback(function (Message $message) { + self::assertSame('{"foo":"fooVal"}', $message->getBody()); + self::assertSame('application/json', $message->getContentType()); + }) + ; + + $producer = new MessageProducer($driver); + $producer->send('topic', $message); + } + + public function testThrowIfNotApplicationJsonContentTypeSetWithJsonSerializableBody() + { + $object = new class implements \JsonSerializable { + public function jsonSerialize() + { + return ['foo' => 'fooVal']; + } + }; + + $message = new Message(); + $message->setBody($object); + $message->setContentType('foo/bar'); + + $driver = $this->createDriverStub(); + $driver + ->expects($this->never()) + ->method('sendToRouter') + ; + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Content type "application/json" only allowed when body is array'); + + $producer = new MessageProducer($driver); + $producer->send('topic', $message); + } + /** * @return \PHPUnit_Framework_MockObject_MockObject|DriverInterface */ From b929e81de32c4698daac04c92b78558650801bc6 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Sat, 18 Mar 2017 22:52:54 +0200 Subject: [PATCH 2/3] fix tests on pre 7.x php versions --- .../Tests/Client/MessageProducerTest.php | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/pkg/enqueue/Tests/Client/MessageProducerTest.php b/pkg/enqueue/Tests/Client/MessageProducerTest.php index 232904794..f7360c4ae 100644 --- a/pkg/enqueue/Tests/Client/MessageProducerTest.php +++ b/pkg/enqueue/Tests/Client/MessageProducerTest.php @@ -341,12 +341,7 @@ public function testShouldThrowExceptionIfBodyIsArrayWithObjectsInSubArraysInsid public function testShouldSendJsonSerializableObjectAsJsonString() { - $object = new class implements \JsonSerializable { - public function jsonSerialize() - { - return ['foo' => 'fooVal']; - } - }; + $object = new JsonSerializableObject(); $driver = $this->createDriverStub(); $driver @@ -364,12 +359,7 @@ public function jsonSerialize() public function testShouldSendMessageJsonSerializableBodyAsJsonString() { - $object = new class implements \JsonSerializable { - public function jsonSerialize() - { - return ['foo' => 'fooVal']; - } - }; + $object = new JsonSerializableObject(); $message = new Message(); $message->setBody($object); @@ -390,12 +380,7 @@ public function jsonSerialize() public function testThrowIfNotApplicationJsonContentTypeSetWithJsonSerializableBody() { - $object = new class implements \JsonSerializable { - public function jsonSerialize() - { - return ['foo' => 'fooVal']; - } - }; + $object = new JsonSerializableObject(); $message = new Message(); $message->setBody($object); @@ -422,3 +407,11 @@ protected function createDriverStub() return $this->createMock(DriverInterface::class); } } + +class JsonSerializableObject implements \JsonSerializable +{ + public function jsonSerialize() + { + return ['foo' => 'fooVal']; + } +}; From 1509ca18181c8a3977a4236a40ce306a96338a8e Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Sat, 18 Mar 2017 23:03:17 +0200 Subject: [PATCH 3/3] [client] Adjust exception message. add a note that object is also allowed. --- pkg/enqueue/Client/MessageProducer.php | 2 +- pkg/enqueue/Tests/Client/MessageProducerTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/enqueue/Client/MessageProducer.php b/pkg/enqueue/Client/MessageProducer.php index c10d293ae..39f64d397 100644 --- a/pkg/enqueue/Client/MessageProducer.php +++ b/pkg/enqueue/Client/MessageProducer.php @@ -87,7 +87,7 @@ private function prepareBody(Message $message) $body = JSON::encode($body); } else { throw new \InvalidArgumentException(sprintf( - 'The message\'s body must be either null, scalar or array. Got: %s', + 'The message\'s body must be either null, scalar, array or object (implements \JsonSerializable). Got: %s', is_object($body) ? get_class($body) : gettype($body) )); } diff --git a/pkg/enqueue/Tests/Client/MessageProducerTest.php b/pkg/enqueue/Tests/Client/MessageProducerTest.php index f7360c4ae..cab846c59 100644 --- a/pkg/enqueue/Tests/Client/MessageProducerTest.php +++ b/pkg/enqueue/Tests/Client/MessageProducerTest.php @@ -298,7 +298,7 @@ public function testShouldThrowExceptionIfBodyIsObjectOnSend() $producer = new MessageProducer($driver); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The message\'s body must be either null, scalar or array. Got: stdClass'); + $this->expectExceptionMessage('The message\'s body must be either null, scalar, array or object (implements \JsonSerializable). Got: stdClass'); $producer->send('topic', new \stdClass()); }