diff --git a/src/Lunr/Vortex/PushNotificationBroadcastResponseInterface.php b/src/Lunr/Vortex/PushNotificationBroadcastResponseInterface.php new file mode 100644 index 0000000..172745f --- /dev/null +++ b/src/Lunr/Vortex/PushNotificationBroadcastResponseInterface.php @@ -0,0 +1,27 @@ + diff --git a/src/Lunr/Vortex/PushNotificationDispatcher.php b/src/Lunr/Vortex/PushNotificationDispatcher.php index b4e389d..efc5251 100644 --- a/src/Lunr/Vortex/PushNotificationDispatcher.php +++ b/src/Lunr/Vortex/PushNotificationDispatcher.php @@ -30,6 +30,12 @@ class PushNotificationDispatcher */ protected array $statuses; + /** + * List of Push Notification status codes for every broadcast. + * @var array, string[]> + */ + protected array $broadcast_statuses; + /** * Constructor. */ @@ -42,6 +48,8 @@ public function __construct() { $this->statuses[$case->value] = []; } + + $this->broadcast_statuses = $this->statuses; } /** @@ -51,6 +59,7 @@ public function __destruct() { unset($this->dispatchers); unset($this->statuses); + unset($this->broadcast_statuses); } /** @@ -99,6 +108,11 @@ public function dispatch(array $endpoints, array $payloads): void $this->statuses[Status::NotHandled->value] = array_merge($this->statuses[Status::NotHandled->value], $payload_endpoints); } + foreach (array_filter($platform_payloads, fn($payload) => $payload->is_broadcast()) as $payload) + { + $this->broadcast_statuses[Status::NotHandled->value][] = $payload; + } + continue; } @@ -109,15 +123,17 @@ public function dispatch(array $endpoints, array $payloads): void continue; } - $endpoints = $grouped_endpoints[$platform][$payload_type] ?? []; - - if ($this->dispatchers[$platform] instanceof PushNotificationMultiDispatcherInterface) + if ($payload->is_broadcast()) { - $this->dispatch_multiple($platform, $endpoints, $payload); + $this->dispatch_broadcast($platform, $payload); + } + elseif ($this->dispatchers[$platform] instanceof PushNotificationMultiDispatcherInterface) + { + $this->dispatch_multiple($platform, $grouped_endpoints[$platform][$payload_type], $payload); } else { - $this->dispatch_single($platform, $endpoints, $payload); + $this->dispatch_single($platform, $grouped_endpoints[$platform][$payload_type], $payload); } } } @@ -194,6 +210,30 @@ protected function dispatch_multiple(string $platform, array &$endpoints, object } } + /** + * Push a notification payload to each endpoint in a multicast way + * + * @param string $platform Notification platform + * @param PushNotificationPayloadInterface $payload Payload to send + * + * @return void + */ + protected function dispatch_broadcast(string $platform, PushNotificationPayloadInterface $payload): void + { + $endpoints = []; + + $response = $this->dispatchers[$platform]->push($payload, $endpoints); + + $status = PushNotificationStatus::Unknown; + + if ($response instanceof PushNotificationBroadcastResponseInterface) + { + $status = $response->get_broadcast_status(); + } + + $this->broadcast_statuses[$status->value][] = $payload; + } + /** * Returns a list of endpoint & platform pairs for a given list of delivery status codes. * @@ -233,6 +273,16 @@ public function get_statuses(): array return $this->statuses; } + /** + * Return broadcast status information. + * + * @return PushNotificationStatus + */ + public function get_broadcast_statuses() + { + return $this->broadcast_statuses; + } + } ?> diff --git a/src/Lunr/Vortex/Tests/PushNotificationDispatcherDispatchTest.php b/src/Lunr/Vortex/Tests/PushNotificationDispatcherDispatchTest.php index 7df91b3..a20f6bc 100644 --- a/src/Lunr/Vortex/Tests/PushNotificationDispatcherDispatchTest.php +++ b/src/Lunr/Vortex/Tests/PushNotificationDispatcherDispatchTest.php @@ -936,7 +936,6 @@ public function testDispatchMultiCastWithDeferredResponse(): void public function testDispatchSendsCorrectBroadcastPayload(): void { $dispatchers = [ - 'apns' => $this->apns, 'fcm' => $this->fcm, 'email' => $this->email, ]; @@ -946,11 +945,29 @@ public function testDispatchSendsCorrectBroadcastPayload(): void ->disableOriginalConstructor() ->getMock(); + $apns_payload = $this->getMockBuilder(APNSPayload::class) + ->disableOriginalConstructor() + ->getMock(); + + $email_payload = $this->getMockBuilder(EmailPayload::class) + ->disableOriginalConstructor() + ->getMock(); + $payloads = [ - 'fcm' => [ 'data' => $data_payload ], + 'apns' => [ 'apns' => $apns_payload ], + 'fcm' => [ 'data' => $data_payload ], + 'email' => [ 'email' => $email_payload ], ]; - $data_payload->expects($this->exactly(2)) + $apns_payload->expects($this->exactly(2)) + ->method('is_broadcast') + ->willReturn(TRUE); + + $email_payload->expects($this->exactly(3)) + ->method('is_broadcast') + ->willReturn(TRUE); + + $data_payload->expects($this->exactly(3)) ->method('is_broadcast') ->willReturn(TRUE); @@ -963,6 +980,19 @@ public function testDispatchSendsCorrectBroadcastPayload(): void ->method('get_status'); $this->class->dispatch([], $payloads); + + $expected_statuses = [ + PushNotificationStatus::Unknown->value => [ $data_payload, $email_payload ], + PushNotificationStatus::Success->value => [], + PushNotificationStatus::TemporaryError->value => [], + PushNotificationStatus::InvalidEndpoint->value => [], + PushNotificationStatus::ClientError->value => [], + PushNotificationStatus::Error->value => [], + PushNotificationStatus::NotHandled->value => [ $apns_payload ], + PushNotificationStatus::Deferred->value => [], + ]; + + $this->assertPropertySame('broadcast_statuses', $expected_statuses); } } diff --git a/src/Lunr/Vortex/Tests/PushNotificationDispatcherGetTest.php b/src/Lunr/Vortex/Tests/PushNotificationDispatcherGetTest.php index 664763b..0182414 100644 --- a/src/Lunr/Vortex/Tests/PushNotificationDispatcherGetTest.php +++ b/src/Lunr/Vortex/Tests/PushNotificationDispatcherGetTest.php @@ -9,6 +9,8 @@ namespace Lunr\Vortex\Tests; +use Lunr\Vortex\APNS\APNSPayload; +use Lunr\Vortex\FCM\FCMPayload; use Lunr\Vortex\PushNotificationStatus; /** @@ -164,6 +166,37 @@ public function testGetStatusesReturnsStatuses(): void $this->assertSame($statuses, $this->class->get_statuses()); } + /** + * Test that get_broadcast_statuses() returns the entire broadcast status array. + * + * @covers Lunr\Vortex\PushNotificationDispatcher::get_broadcast_statuses + */ + public function testGetBroadcastStatusesReturnsBroadcastStatuses(): void + { + + $data_payload = $this->getMockBuilder(FCMPayload::class) + ->disableOriginalConstructor() + ->getMock(); + + $apns_payload = $this->getMockBuilder(APNSPayload::class) + ->disableOriginalConstructor() + ->getMock(); + + $broadcast_statuses = [ + PushNotificationStatus::TemporaryError->value => [ + $data_payload, + $apns_payload + ], + PushNotificationStatus::Error->value => [ + $data_payload + ], + ]; + + $this->set_reflection_property_value('broadcast_statuses', $broadcast_statuses); + + $this->assertSame($broadcast_statuses, $this->class->get_broadcast_statuses()); + } + } ?>