Skip to content

Commit

Permalink
Remove reliance on the CloudMessage class when handling messages (#934
Browse files Browse the repository at this point in the history
)
  • Loading branch information
jeromegamez authored Sep 16, 2024
1 parent d086c2f commit 45713e5
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 18 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Please read about the future of the Firebase Admin PHP SDK on the

## [Unreleased]

### Changed

* The Messaging component doesn't rely on the `CloudMessage` class for message handling anymore. If you provide a
message as an array and it has an error, the Firebase API will report it. You can still use the `CloudMessage`
class as a message builder

## [7.15.0] - 2024-09-11

### Added
Expand Down
63 changes: 49 additions & 14 deletions src/Firebase/Messaging.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
use Kreait\Firebase\Messaging\ApiClient;
use Kreait\Firebase\Messaging\AppInstance;
use Kreait\Firebase\Messaging\AppInstanceApiClient;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Message;
use Kreait\Firebase\Messaging\MessageTarget;
use Kreait\Firebase\Messaging\MulticastSendReport;
use Kreait\Firebase\Messaging\Processor\SetApnsContentAvailableIfNeeded;
use Kreait\Firebase\Messaging\Processor\SetApnsPushTypeIfNeeded;
use Kreait\Firebase\Messaging\RawMessageFromArray;
use Kreait\Firebase\Messaging\RegistrationToken;
use Kreait\Firebase\Messaging\RegistrationTokens;
use Kreait\Firebase\Messaging\SendReport;
Expand Down Expand Up @@ -68,15 +68,13 @@ public function send(Message|array $message, bool $validateOnly = false): array

public function sendMulticast($message, $registrationTokens, bool $validateOnly = false): MulticastSendReport
{
$message = CloudMessage::fromArray(
Json::decode(Json::encode($this->makeMessage($message)), true),
);
$message = $message instanceof Message ? $message : new RawMessageFromArray($message);
$registrationTokens = RegistrationTokens::fromValue($registrationTokens);

$messages = [];

foreach ($registrationTokens as $registrationToken) {
$messages[] = $message->withChangedTarget(MessageTarget::TOKEN, $registrationToken->value());
$messages[] = $this->withChangedTarget($message, MessageTarget::TOKEN, $registrationToken->value());
}

return $this->sendAll($messages, $validateOnly);
Expand All @@ -94,14 +92,14 @@ public function sendAll($messages, bool $validateOnly = false): MulticastSendRep

$json = Json::decode((string) $response->getBody(), true);

$sendReports[$index] = SendReport::success($message->target(), $json, $message);
$sendReports[$index] = SendReport::success($this->getTarget($message), $json, $message);
},
'rejected' => function (Throwable $reason, int $index) use ($messages, &$sendReports): void {
$message = $messages[$index];

$error = $this->exceptionConverter->convertException($reason);

$sendReports[$index] = SendReport::failure($message->target(), $error, $message);
$sendReports[$index] = SendReport::failure($this->getTarget($message), $error, $message);
},
];

Expand All @@ -124,7 +122,7 @@ public function validateRegistrationTokens($registrationTokenOrTokens): array
{
$tokens = RegistrationTokens::fromValue($registrationTokenOrTokens);

$report = $this->sendMulticast(CloudMessage::new(), $tokens, true);
$report = $this->sendMulticast(new RawMessageFromArray([]), $tokens, true);

return [
'valid' => $report->validTokens(),
Expand Down Expand Up @@ -220,7 +218,7 @@ public function getAppInstance(RegistrationToken|string $registrationToken): App
/**
* @param iterable<Message|array<non-empty-string, mixed>> $messages
*
* @return list<CloudMessage>
* @return list<Message>
*/
private function ensureMessages(iterable $messages): array
{
Expand All @@ -238,18 +236,17 @@ private function ensureMessages(iterable $messages): array
*
* @throws InvalidArgumentException
*/
private function makeMessage(Message|array $message): CloudMessage
private function makeMessage(Message|array $message): Message
{
$message = $message instanceof Message ? $message : CloudMessage::fromArray($message);
$message = $message instanceof Message ? $message : new RawMessageFromArray($message);

$message = (new SetApnsPushTypeIfNeeded())($message);
$message = (new SetApnsContentAvailableIfNeeded())($message);

return CloudMessage::fromArray(Json::decode(JSON::encode($message->jsonSerialize()), true));
return (new SetApnsContentAvailableIfNeeded())($message);
}

/**
* @param iterable<CloudMessage> $messages
* @param iterable<Message> $messages
* @return callable(): list<RequestInterface>
*/
private function createSendRequests(iterable $messages, bool $validateOnly): callable
Expand All @@ -269,4 +266,42 @@ private function messageHasTarget(Message $message): bool
|| array_key_exists(MessageTarget::TOKEN, $check)
|| array_key_exists(MessageTarget::TOPIC, $check);
}

private function withChangedTarget(Message $message, string $target, string $value): Message
{
$message = Json::decode(Json::encode($message), true);

unset(
$message[MessageTarget::CONDITION],
$message[MessageTarget::TOKEN],
$message[MessageTarget::TOPIC],
);

$message[$target] = $value;

return new RawMessageFromArray($message);
}

private function getTarget(Message $message): MessageTarget
{
$message = Json::decode(Json::encode($message), true);

$condition = $message[MessageTarget::CONDITION] ?? null;
$token = $message[MessageTarget::TOKEN] ?? null;
$topic = $message[MessageTarget::TOPIC] ?? null;

if (is_string($condition) && $condition !== '') {
return MessageTarget::with(MessageTarget::CONDITION, $condition);
}

if (is_string($token) && $token !== '') {
return MessageTarget::with(MessageTarget::TOKEN, $token);
}

if (is_string($topic) && $topic !== '') {
return MessageTarget::with(MessageTarget::TOPIC, $topic);
}

return MessageTarget::with(MessageTarget::UNKNOWN, 'unknown');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

use Beste\Json;
use Kreait\Firebase\Messaging\ApnsConfig;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Message;
use Kreait\Firebase\Messaging\MessageData;
use Kreait\Firebase\Messaging\Notification;
use Kreait\Firebase\Messaging\RawMessageFromArray;

use function is_array;

Expand Down Expand Up @@ -45,7 +45,9 @@ public function __invoke(Message $message): Message

$apnsConfig = $apnsConfig->withApsField('content-available', 1);

return CloudMessage::fromArray($payload)->withApnsConfig($apnsConfig);
$payload['apns'] = $apnsConfig->toArray();

return new RawMessageFromArray($payload);
}

/**
Expand Down
12 changes: 10 additions & 2 deletions src/Firebase/Messaging/Processor/SetApnsPushTypeIfNeeded.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

use Beste\Json;
use Kreait\Firebase\Messaging\ApnsConfig;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Message;
use Kreait\Firebase\Messaging\MessageData;
use Kreait\Firebase\Messaging\Notification;
use Kreait\Firebase\Messaging\RawMessageFromArray;

use function is_array;

Expand All @@ -25,6 +25,10 @@ public function __invoke(Message $message): Message
{
$payload = Json::decode(Json::encode($message), true);

if (!is_array($payload)) {
return $message;
}

$notification = $this->getNotification($payload);
$messageData = $this->getMessageData($payload);
$apnsConfig = $this->getApnsConfig($payload);
Expand All @@ -46,9 +50,13 @@ public function __invoke(Message $message): Message
$apnsConfig = $apnsConfig->withHeader('apns-push-type', 'alert');
} elseif ($isBackgroundMessage) {
$apnsConfig = $apnsConfig->withHeader('apns-push-type', 'background');
} else {
return $message;
}

return CloudMessage::fromArray($payload)->withApnsConfig($apnsConfig);
$payload['apns'] = $apnsConfig->toArray();

return new RawMessageFromArray($payload);
}

/**
Expand Down

2 comments on commit 45713e5

@dom976
Copy link

@dom976 dom976 commented on 45713e5 Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, I am using the notifyAll() method with this library version 7.15 but I am not receiving notifications on my device, even if no exceptions are raised. What am I doing wrong?

@jeromegamez
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no notifyAll() method in the SDK. If you want to ask a question on how to use the SDK, please use the Discussions on this repo, perhaps someone can help you. Individual commits are not the right place to raise topics.

Please sign in to comment.