1
|
|
<?php
|
2
|
|
|
3
|
|
declare(strict_types=1);
|
4
|
|
|
5
|
|
namespace Kreait\Firebase\Messaging;
|
6
|
|
|
7
|
|
use Countable;
|
8
|
|
use Kreait\Firebase\Exception\InvalidArgumentException;
|
9
|
|
use Kreait\Firebase\Exception\MessagingApiExceptionConverter;
|
10
|
|
use Kreait\Firebase\Http\Requests;
|
11
|
|
use Kreait\Firebase\Http\Responses;
|
12
|
|
use Kreait\Firebase\Util\JSON;
|
13
|
|
use Psr\Http\Message\RequestInterface;
|
14
|
|
|
15
|
|
final class MulticastSendReport implements Countable
|
16
|
|
{
|
17
|
|
/** @var SendReport[] */
|
18
|
|
private $items = [];
|
19
|
|
|
20
|
3
|
private function __construct()
|
21
|
|
{
|
22
|
|
}
|
23
|
|
|
24
|
|
/**
|
25
|
|
* @param SendReport[] $items
|
26
|
|
*/
|
27
|
3
|
public static function withItems(array $items): self
|
28
|
|
{
|
29
|
3
|
$report = new self();
|
30
|
|
|
31
|
3
|
foreach ($items as $item) {
|
32
|
3
|
$report = $report->withAdded($item);
|
33
|
|
}
|
34
|
|
|
35
|
3
|
return $report;
|
36
|
|
}
|
37
|
|
|
38
|
3
|
public static function fromRequestsAndResponses(Requests $requests, Responses $responses): self
|
39
|
|
{
|
40
|
3
|
$reports = [];
|
41
|
3
|
$errorHandler = new MessagingApiExceptionConverter();
|
42
|
|
|
43
|
3
|
foreach ($responses as $response) {
|
44
|
3
|
$contentIdHeader = $response->getHeaderLine('Content-ID');
|
45
|
3
|
$contentIdHeaderParts = \explode('-', $contentIdHeader);
|
46
|
|
|
47
|
3
|
if (!($responseId = \array_pop($contentIdHeaderParts) ?: null)) {
|
48
|
0
|
continue;
|
49
|
|
}
|
50
|
|
|
51
|
|
$matchingRequest = $requests->findBy(static function (RequestInterface $request) use ($responseId) {
|
52
|
3
|
$contentIdHeader = $request->getHeaderLine('Content-ID');
|
53
|
3
|
$contentIdHeaderParts = \explode('-', $contentIdHeader);
|
54
|
3
|
$contentId = \array_pop($contentIdHeaderParts);
|
55
|
|
|
56
|
3
|
return $contentId === $responseId;
|
57
|
3
|
});
|
58
|
|
|
59
|
3
|
if (!$matchingRequest) {
|
60
|
0
|
continue;
|
61
|
|
}
|
62
|
|
|
63
|
|
try {
|
64
|
3
|
$requestData = JSON::decode((string) $matchingRequest->getBody(), true);
|
65
|
0
|
} catch (InvalidArgumentException $e) {
|
66
|
0
|
continue;
|
67
|
|
}
|
68
|
|
|
69
|
3
|
$target = null;
|
70
|
|
|
71
|
3
|
if ($token = $requestData['message']['token'] ?? null) {
|
72
|
3
|
$target = MessageTarget::with(MessageTarget::TOKEN, (string) $token);
|
73
|
3
|
} elseif ($topic = $requestData['message']['topic'] ?? null) {
|
74
|
3
|
$target = MessageTarget::with(MessageTarget::TOPIC, (string) $topic);
|
75
|
3
|
} elseif ($condition = $requestData['message']['condition'] ?? null) {
|
76
|
3
|
$target = MessageTarget::with(MessageTarget::CONDITION, (string) $condition);
|
77
|
|
} else {
|
78
|
3
|
$target = MessageTarget::with(MessageTarget::UNKNOWN, 'unknown');
|
79
|
|
}
|
80
|
|
|
81
|
3
|
if ($response->getStatusCode() < 400) {
|
82
|
|
try {
|
83
|
3
|
$responseData = JSON::decode((string) $response->getBody(), true);
|
84
|
0
|
} catch (InvalidArgumentException $e) {
|
85
|
0
|
$responseData = [];
|
86
|
|
}
|
87
|
|
|
88
|
3
|
$reports[] = SendReport::success($target, $responseData);
|
89
|
|
} else {
|
90
|
3
|
$error = $errorHandler->convertResponse($response);
|
91
|
3
|
$reports[] = SendReport::failure($target, $error);
|
92
|
|
}
|
93
|
|
}
|
94
|
|
|
95
|
3
|
return self::withItems($reports);
|
96
|
|
}
|
97
|
|
|
98
|
3
|
public function withAdded(SendReport $report): self
|
99
|
|
{
|
100
|
3
|
$new = clone $this;
|
101
|
3
|
$new->items[] = $report;
|
102
|
|
|
103
|
3
|
return $new;
|
104
|
|
}
|
105
|
|
|
106
|
|
/**
|
107
|
|
* @return SendReport[]
|
108
|
|
*/
|
109
|
3
|
public function getItems(): array
|
110
|
|
{
|
111
|
3
|
return $this->items;
|
112
|
|
}
|
113
|
|
|
114
|
3
|
public function successes(): self
|
115
|
|
{
|
116
|
|
return $this->filter(static function (SendReport $item) {
|
117
|
3
|
return $item->isSuccess();
|
118
|
3
|
});
|
119
|
|
}
|
120
|
|
|
121
|
3
|
public function failures(): self
|
122
|
|
{
|
123
|
|
return $this->filter(static function (SendReport $item) {
|
124
|
3
|
return $item->isFailure();
|
125
|
3
|
});
|
126
|
|
}
|
127
|
|
|
128
|
3
|
public function hasFailures(): bool
|
129
|
|
{
|
130
|
3
|
return $this->failures()->count() > 0;
|
131
|
|
}
|
132
|
|
|
133
|
3
|
public function filter(callable $callback): self
|
134
|
|
{
|
135
|
3
|
return self::withItems(\array_filter($this->items, $callback));
|
136
|
|
}
|
137
|
|
|
138
|
|
/**
|
139
|
|
* @return array<int, mixed>
|
140
|
|
*/
|
141
|
3
|
public function map(callable $callback): array
|
142
|
|
{
|
143
|
3
|
return \array_map($callback, $this->items);
|
144
|
|
}
|
145
|
|
|
146
|
|
/**
|
147
|
|
* Returns all provided registration tokens that were not reachable.
|
148
|
|
*
|
149
|
|
* @return string[]
|
150
|
|
*/
|
151
|
0
|
public function unknownTokens(): array
|
152
|
|
{
|
153
|
|
return $this->filter(static function (SendReport $report) {
|
154
|
0
|
return $report->messageWasSentToUnknownToken();
|
155
|
|
})->map(static function (SendReport $report) {
|
156
|
0
|
return $report->target()->value();
|
157
|
0
|
});
|
158
|
|
}
|
159
|
|
|
160
|
|
/**
|
161
|
|
* Returns all provided registration tokens that were invalid.
|
162
|
|
*
|
163
|
|
* @return string[]
|
164
|
|
*/
|
165
|
3
|
public function invalidTokens(): array
|
166
|
|
{
|
167
|
|
return $this->filter(static function (SendReport $report) {
|
168
|
3
|
return $report->messageTargetWasInvalid();
|
169
|
|
})->map(static function (SendReport $report) {
|
170
|
3
|
return $report->target()->value();
|
171
|
3
|
});
|
172
|
|
}
|
173
|
|
|
174
|
3
|
public function count(): int
|
175
|
|
{
|
176
|
3
|
return \count($this->items);
|
177
|
|
}
|
178
|
|
}
|