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
}

Read our documentation on viewing source code .

Loading