Completed
Push — master ( 611a4d...0d4705 )
by Artem
11:18 queued 04:23
created

ResponseProcessor::getBodyAsArray()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
/*
3
 * This file is part of the FirebaseCloudMessagingBundle.
4
 *
5
 * (c) Artem Henvald <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fresh\FirebaseCloudMessagingBundle\Response;
14
15
use Fresh\FirebaseCloudMessagingBundle\Exception\AuthenticationException;
16
use Fresh\FirebaseCloudMessagingBundle\Exception\ExceptionInterface;
17
use Fresh\FirebaseCloudMessagingBundle\Exception\InternalServerErrorException;
18
use Fresh\FirebaseCloudMessagingBundle\Exception\InvalidJsonException;
19
use Fresh\FirebaseCloudMessagingBundle\Exception\UnsupportedResponseException;
20
use Fresh\FirebaseCloudMessagingBundle\Message\Part\Target\TokenTargetInterface;
21
use Fresh\FirebaseCloudMessagingBundle\Message\Type\AbstractMessage;
22
use Fresh\FirebaseCloudMessagingBundle\Response\MessageResult\CanonicalTokenMessageResult;
23
use Fresh\FirebaseCloudMessagingBundle\Response\MessageResult\Collection\CanonicalTokenMessageResultCollection;
24
use Fresh\FirebaseCloudMessagingBundle\Response\MessageResult\Collection\FailedMessageResultCollection;
25
use Fresh\FirebaseCloudMessagingBundle\Response\MessageResult\Collection\SuccessfulMessageResultCollection;
26
use Fresh\FirebaseCloudMessagingBundle\Response\MessageResult\FailedMessageResult;
27
use Fresh\FirebaseCloudMessagingBundle\Response\MessageResult\SuccessfulMessageResult;
28
use Psr\Http\Message\ResponseInterface;
29
use Symfony\Component\HttpFoundation\Response;
30
31
/**
32
 * Class ResponseProcessor.
33
 *
34
 * @author Artem Henvald <[email protected]>
35
 */
36
class ResponseProcessor
37
{
38
    private array $jsonContentTypes = [
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_ARRAY, expecting T_FUNCTION or T_CONST
Loading history...
39
        'application/json',
40
        'application/json; charset=UTF-8',
41
    ];
42
43
    private AbstractMessage $message;
44
45
    /**
46
     * @param AbstractMessage   $message
47
     * @param ResponseInterface $response
48
     *
49
     * @throws ExceptionInterface
50
     *
51
     * @return FirebaseResponseInterface
52
     */
53
    public function processResponse(AbstractMessage $message, ResponseInterface $response): FirebaseResponseInterface
54
    {
55
        $this->message = $message;
56
57
        if (Response::HTTP_OK === $response->getStatusCode()) {
58
            $result = $this->processHttpOkResponse($response);
59
        } elseif (Response::HTTP_BAD_REQUEST === $response->getStatusCode()) {
60
            throw new InvalidJsonException();
61
        } elseif (Response::HTTP_UNAUTHORIZED === $response->getStatusCode()) {
62
            throw new AuthenticationException();
63
        } elseif (Response::HTTP_INTERNAL_SERVER_ERROR === $response->getStatusCode()) {
64
            throw new InternalServerErrorException();
65
        } else {
66
            throw new UnsupportedResponseException();
67
        }
68
69
        return $result;
70
    }
71
72
    /**
73
     * @param ResponseInterface $response
74
     *
75
     * @return FirebaseResponseInterface
76
     */
77
    private function processHttpOkResponse(ResponseInterface $response)
78
    {
79
        $body = $this->getBodyAsArray($response);
80
81
        if (isset($body['error'])) {
82
            $response = $this->processHttpOkResponseWithError($body);
83
        } else {
84
            $response = $this->processHttpOkResponseWithoutError($body);
85
        }
86
87
        return $response;
88
    }
89
90
    /**
91
     * @param array $body
92
     *
93
     * @return MulticastMessageResponse
94
     */
95
    private function processHttpOkResponseWithoutError(array $body): MulticastMessageResponse
96
    {
97
        $successfulMessageResults = new SuccessfulMessageResultCollection();
98
        $failedMessageResults = new FailedMessageResultCollection();
99
        $canonicalTokenMessageResults = new CanonicalTokenMessageResultCollection();
100
101
        if ($this->message->getTarget() instanceof TokenTargetInterface) {
102
            $numberOfSequentialSentTokens = $this->message->getTarget()->getNumberOfSequentialSentTokens();
103
104
            if (isset($body['results']) && \count($body['results']) !== $numberOfSequentialSentTokens) {
105
                throw new \Exception('Mismatch number of sent tokens and results');
106
            }
107
108
            for ($i = 0; $i < $numberOfSequentialSentTokens; ++$i) {
109
                $currentToken = $this->message->getTarget()->getSequentialSentTokens()[$i];
110
                $currentResult = $body['results'][$i];
111
112
                if (isset($currentResult['error'])) {
113
                    $messageResult = (new FailedMessageResult())
114
                        ->setError($currentResult['error']);
115
116
                    $failedMessageResults[] = $messageResult;
117
                } elseif (isset($currentResult['registration_id'])) {
118
                    $messageResult = (new CanonicalTokenMessageResult())
119
                        ->setMessageId($currentResult['message_id'])
120
                        ->setCanonicalToken($currentResult['registration_id']);
121
122
                    $canonicalTokenMessageResults[] = $messageResult;
123
                } else {
124
                    $messageResult = (new SuccessfulMessageResult())->setMessageId($currentResult['message_id']);
125
                    $successfulMessageResults[] = $messageResult;
126
                }
127
128
                $messageResult->setToken($currentToken);
129
            }
130
        }
131
132
        return (new MulticastMessageResponse())
133
            ->setMulticastId($body['multicast_id'])
134
            ->setSuccessfulMessageResults($successfulMessageResults)
135
            ->setFailedMessageResults($failedMessageResults)
136
            ->setCanonicalTokenMessageResults($canonicalTokenMessageResults);
137
    }
138
139
    /**
140
     * @param array $body
141
     */
142
    private function processHttpOkResponseWithError(array $body)
143
    {
144
        // @todo finish it
145
    }
146
147
    /**
148
     * @param ResponseInterface $response
149
     *
150
     * @throws \InvalidArgumentException
151
     *
152
     * @return array
153
     */
154
    private function getBodyAsArray(ResponseInterface $response): array
155
    {
156
        if ($this->responseContentTypeIsJson($response)) {
157
            $response->getBody()->rewind();
158
            $body = null;
159
160
            if ($response->getBody()->getSize() > 0) {
161
                $body = $response->getBody()->getContents();
162
            }
163
164
            return \json_decode($body, true);
165
        }
166
167
        throw new \InvalidArgumentException('Response from Firebase Cloud Messaging is not a JSON');
168
    }
169
170
    /**
171
     * @param ResponseInterface $response
172
     *
173
     * @return bool
174
     */
175
    private function responseContentTypeIsJson(ResponseInterface $response): bool
176
    {
177
        return $response->hasHeader('Content-Type')
178
               && \in_array($response->getHeader('Content-Type')[0], $this->jsonContentTypes, true);
179
    }
180
}
181