Skip to content

Commit

Permalink
General: Return PushNotificationStatus for broadcasts
Browse files Browse the repository at this point in the history
  • Loading branch information
brianstoop committed Dec 9, 2024
1 parent 197dc51 commit f73151f
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 10 deletions.
27 changes: 27 additions & 0 deletions src/Lunr/Vortex/PushNotificationBroadcastResponseInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* This file contains the PushNotificationBroadcastResponseInterface.
*
* SPDX-FileCopyrightText: Copyright 2024 Move Agency Group B.V., Zwolle, The Netherlands
* SPDX-License-Identifier: MIT
*/

namespace Lunr\Vortex;

/**
* Push notification Response interface.
*/
interface PushNotificationBroadcastResponseInterface
{

/**
* Get notification delivery status for the broadcast.
*
* @return PushNotificationStatus Delivery status for the broadcast
*/
public function get_broadcast_status(): PushNotificationStatus;

}

?>
68 changes: 61 additions & 7 deletions src/Lunr/Vortex/PushNotificationDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ class PushNotificationDispatcher
*/
protected array $statuses;

/**
* List of Push Notification status codes for every broadcast.
* @var array<value-of<PushNotificationStatus>, array<string, array<string, PushNotificationPayloadInterface>>>
*/
protected array $broadcast_statuses;

/**
* Constructor.
*/
Expand All @@ -42,6 +48,8 @@ public function __construct()
{
$this->statuses[$case->value] = [];
}

$this->broadcast_statuses = $this->statuses;
}

/**
Expand All @@ -51,6 +59,7 @@ public function __destruct()
{
unset($this->dispatchers);
unset($this->statuses);
unset($this->broadcast_statuses);
}

/**
Expand Down Expand Up @@ -94,9 +103,17 @@ public function dispatch(array $endpoints, array $payloads): void

if (!isset($this->dispatchers[$platform]))
{
foreach ($grouped_endpoints[$platform] as $payload_endpoints)
if (isset($grouped_endpoints[$platform]))
{
$this->statuses[Status::NotHandled->value] = array_merge($this->statuses[Status::NotHandled->value], $payload_endpoints);
foreach ($grouped_endpoints[$platform] as $payload_endpoints)
{
$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_type => $payload)
{
$this->broadcast_statuses[Status::NotHandled->value][$platform][$payload_type] = $payload;
}

continue;
Expand All @@ -109,15 +126,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_type, $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);
}
}
}
Expand Down Expand Up @@ -194,6 +213,31 @@ 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 string $payload_type Notification payload type
* @param PushNotificationPayloadInterface $payload Payload to send
*
* @return void
*/
protected function dispatch_broadcast(string $platform, string $payload_type, 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][$platform][$payload_type] = $payload;
}

/**
* Returns a list of endpoint & platform pairs for a given list of delivery status codes.
*
Expand Down Expand Up @@ -233,6 +277,16 @@ public function get_statuses(): array
return $this->statuses;
}

/**
* Return broadcast status information.
*
* @return array<value-of<PushNotificationStatus>, array<string, array<string, PushNotificationPayloadInterface>>>
*/
public function get_broadcast_statuses()
{
return $this->broadcast_statuses;
}

}

?>
36 changes: 33 additions & 3 deletions src/Lunr/Vortex/Tests/PushNotificationDispatcherDispatchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,6 @@ public function testDispatchMultiCastWithDeferredResponse(): void
public function testDispatchSendsCorrectBroadcastPayload(): void
{
$dispatchers = [
'apns' => $this->apns,
'fcm' => $this->fcm,
'email' => $this->email,
];
Expand All @@ -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);

Expand All @@ -963,6 +980,19 @@ public function testDispatchSendsCorrectBroadcastPayload(): void
->method('get_status');

$this->class->dispatch([], $payloads);

$expected_statuses = [
PushNotificationStatus::Unknown->value => [ 'fcm' => [ 'data' => $data_payload ], 'email' => [ 'email' => $email_payload ]],
PushNotificationStatus::Success->value => [],
PushNotificationStatus::TemporaryError->value => [],
PushNotificationStatus::InvalidEndpoint->value => [],
PushNotificationStatus::ClientError->value => [],
PushNotificationStatus::Error->value => [],
PushNotificationStatus::NotHandled->value => [ 'apns' => [ 'apns' => $apns_payload ]],
PushNotificationStatus::Deferred->value => [],
];

$this->assertPropertySame('broadcast_statuses', $expected_statuses);
}

}
Expand Down
33 changes: 33 additions & 0 deletions src/Lunr/Vortex/Tests/PushNotificationDispatcherGetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace Lunr\Vortex\Tests;

use Lunr\Vortex\APNS\APNSPayload;
use Lunr\Vortex\FCM\FCMPayload;
use Lunr\Vortex\PushNotificationStatus;

/**
Expand Down Expand Up @@ -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());
}

}

?>

0 comments on commit f73151f

Please sign in to comment.