diff --git a/src/EventSource.php b/src/EventSource.php index 0852fb8..1269ba4 100644 --- a/src/EventSource.php +++ b/src/EventSource.php @@ -211,12 +211,8 @@ private function request() $buffer = array_pop($messageEvents); foreach ($messageEvents as $data) { - $message = MessageEvent::parse($data); - if ($message->lastEventId === null) { - $message->lastEventId = $this->lastEventId; - } else { - $this->lastEventId = $message->lastEventId; - } + $message = MessageEvent::parse($data, $this->lastEventId); + $this->lastEventId = $message->lastEventId; if ($message->retry !== null) { $this->reconnectTime = $message->retry / 1000; diff --git a/src/MessageEvent.php b/src/MessageEvent.php index 222dc67..6490874 100644 --- a/src/MessageEvent.php +++ b/src/MessageEvent.php @@ -6,17 +6,22 @@ class MessageEvent { /** * @param string $data + * @param string $lastEventId * @return self * @internal */ - public static function parse($data) + public static function parse($data, $lastEventId) { - $message = new self(); - $lines = preg_split( '/\r\n|\r(?!\n)|\n/S', $data ); + + $data = ''; + $id = $lastEventId; + $type = 'message'; + $retry = null; + foreach ($lines as $line) { $name = strstr($line, ':', true); $value = substr(strstr($line, ':'), 1); @@ -24,21 +29,36 @@ public static function parse($data) $value = substr($value, 1); } if ($name === 'data') { - $message->data .= $value . "\n"; + $data .= $value . "\n"; } elseif ($name === 'id') { - $message->lastEventId .= $value; + $id = $value; } elseif ($name === 'event') { - $message->type = $value; + $type = $value; } elseif ($name === 'retry' && $value === (string)(int)$value && $value >= 0) { - $message->retry = (int)$value; + $retry = (int)$value; } } - if (substr($message->data, -1) === "\n") { - $message->data = substr($message->data, 0, -1); + if (substr($data, -1) === "\n") { + $data = substr($data, 0, -1); } - return $message; + return new self($data, $id, $type, $retry); + } + + /** + * @internal + * @param string $data + * @param string $lastEventId + * @param string $type + * @param ?int $retry + */ + private function __construct($data, $lastEventId, $type, $retry) + { + $this->data = $data; + $this->lastEventId = $lastEventId; + $this->type = $type; + $this->retry = $retry; } /** @@ -48,10 +68,10 @@ public static function parse($data) public $data = ''; /** - * @var ?string + * @var string * @readonly */ - public $lastEventId = null; + public $lastEventId = ''; /** * @var string diff --git a/tests/MessageEventTest.php b/tests/MessageEventTest.php index 16e03b3..84ef8ea 100644 --- a/tests/MessageEventTest.php +++ b/tests/MessageEventTest.php @@ -9,53 +9,85 @@ class MessageEventTest extends TestCase { public function testParseSimpleData() { - $message = MessageEvent::parse("data: hello"); + $message = MessageEvent::parse("data: hello", ''); $this->assertEquals('hello', $message->data); } public function testParseDataOverTwoLinesWillBeCombined() { - $message = MessageEvent::parse("data: hello\ndata: world"); + $message = MessageEvent::parse("data: hello\ndata: world", ''); $this->assertEquals("hello\nworld", $message->data); } public function testParseDataOverTwoLinesWithCarrigeReturnsWillBeCombinedWithNewline() { - $message = MessageEvent::parse("data: hello\rdata: world"); + $message = MessageEvent::parse("data: hello\rdata: world", ''); $this->assertEquals("hello\nworld", $message->data); } public function testParseDataOverTwoLinesWithCarrigeReturnsAndNewlinesWillBeCombinedWithNewline() { - $message = MessageEvent::parse("data: hello\r\ndata: world"); + $message = MessageEvent::parse("data: hello\r\ndata: world", ''); $this->assertEquals("hello\nworld", $message->data); } public function testParseDataWithTrailingNewlineOverTwoLines() { - $message = MessageEvent::parse("data: hello\ndata:"); + $message = MessageEvent::parse("data: hello\ndata:", ''); $this->assertEquals("hello\n", $message->data); } public function testParseDataWithCarrigeReturnOverTwoLines() { - $message = MessageEvent::parse("data: hello\rdata:"); + $message = MessageEvent::parse("data: hello\rdata:", ''); $this->assertEquals("hello\n", $message->data); } public function testParseDataWithCarrigeReturnAndNewlineOverTwoLines() { - $message = MessageEvent::parse("data: hello\r\ndata:"); + $message = MessageEvent::parse("data: hello\r\ndata:", ''); $this->assertEquals("hello\n", $message->data); } + public function testParseReturnsMessageWithIdFromStream() + { + $message = MessageEvent::parse("data: hello\r\nid: 1", ''); + + $this->assertEquals("hello", $message->data); + $this->assertEquals('1', $message->lastEventId); + } + + public function testParseWithoutIdReturnsMessageWithIdFromLastEventId() + { + $message = MessageEvent::parse("data: hello", '1'); + + $this->assertEquals("hello", $message->data); + $this->assertEquals('1', $message->lastEventId); + } + + public function testParseWithoutIdReturnsMessageWithEmptyIdIfLastEventIdIsEmpty() + { + $message = MessageEvent::parse("data: hello", ''); + + $this->assertEquals("hello", $message->data); + $this->assertEquals('', $message->lastEventId); + } + + public function testParseWithMultipleIdsReturnsMessageWithLastEventIdFromStream() + { + $message = MessageEvent::parse("data: hello\nid: 1\nid: 2", '0'); + + $this->assertEquals("hello", $message->data); + $this->assertEquals('2', $message->lastEventId); + } + public function retryTimeDataProvider() { return [ @@ -75,7 +107,7 @@ public function retryTimeDataProvider() */ public function testParseRetryTime($input, $expected) { - $message = MessageEvent::parse($input); + $message = MessageEvent::parse($input, ''); $this->assertSame($expected, $message->retry); }