Passed
Pull Request — master (#2608)
by Kévin
05:16
created

Response::getContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test;
15
16
use Symfony\Component\BrowserKit\Response as BrowserKitResponse;
17
use Symfony\Component\HttpClient\Exception\ClientException;
18
use Symfony\Component\HttpClient\Exception\JsonException;
19
use Symfony\Component\HttpClient\Exception\RedirectionException;
20
use Symfony\Component\HttpClient\Exception\ServerException;
21
use Symfony\Component\HttpFoundation\Response as HttpFoundationResponse;
22
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
23
use Symfony\Contracts\HttpClient\ResponseInterface;
24
25
/**
26
 * HTTP Response.
27
 *
28
 * @internal
29
 *
30
 * Partially copied from \Symfony\Component\HttpClient\Response\ResponseTrait
31
 *
32
 * @author Kévin Dunglas <[email protected]>
33
 */
34
final class Response implements ResponseInterface
35
{
36
    private $httpFoundationResponse;
37
    private $browserKitResponse;
38
    private $headers;
39
    private $info;
40
    private $content;
41
    private $jsonData;
42
43
    public function __construct(HttpFoundationResponse $httpFoundationResponse, BrowserKitResponse $browserKitResponse, array $info)
44
    {
45
        $this->httpFoundationResponse = $httpFoundationResponse;
46
        $this->browserKitResponse = $browserKitResponse;
47
48
        $this->headers = $httpFoundationResponse->headers->all();
49
50
        // Compute raw headers
51
        $responseHeaders = [];
52
        foreach ($this->headers as $key => $values) {
53
            foreach ($values as $value) {
54
                $responseHeaders[] = sprintf('%s: %s', $key, $value);
55
            }
56
        }
57
58
        $this->content = $httpFoundationResponse->getContent();
59
        $this->info = [
60
                'http_code' => $httpFoundationResponse->getStatusCode(),
61
                'error' => null,
62
                'response_headers' => $responseHeaders,
63
            ] + $info;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function getInfo(string $type = null)
70
    {
71
        if ($type) {
72
            return $this->info[$type] ?? null;
73
        }
74
75
        return $this->info;
76
    }
77
78
    /**
79
     * Checks the status, and try to extract message if appropriate.
80
     */
81
    private function checkStatusCode()
82
    {
83
        if (500 <= $this->info['http_code']) {
84
            throw new ServerException($this);
85
        }
86
87
        if (400 <= $this->info['http_code']) {
88
            throw new ClientException($this);
89
        }
90
91
        if (300 <= $this->info['http_code']) {
92
            throw new RedirectionException($this);
93
        }
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99
    public function getContent(bool $throw = true): string
100
    {
101
        if ($throw) {
102
            $this->checkStatusCode();
103
        }
104
105
        return $this->content;
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function getStatusCode(): int
112
    {
113
        return $this->info['http_code'];
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function getHeaders(bool $throw = true): array
120
    {
121
        if ($throw) {
122
            $this->checkStatusCode();
123
        }
124
125
        return $this->headers;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function toArray(bool $throw = true): array
135
    {
136
        if ('' === $content = $this->getContent($throw)) {
137
            throw new TransportException('Response body is empty.');
0 ignored issues
show
Bug introduced by
The type ApiPlatform\Core\Bridge\...Test\TransportException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
138
        }
139
140
        if (null !== $this->jsonData) {
141
            return $this->jsonData;
142
        }
143
144
        $contentType = $this->headers['content-type'][0] ?? 'application/json';
145
146
        if (!preg_match('/\bjson\b/i', $contentType)) {
147
            throw new JsonException(sprintf('Response content-type is "%s" while a JSON-compatible one was expected.', $contentType));
148
        }
149
150
        try {
151
            $content = json_decode($content, true, 512, JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0));
152
        } catch (\JsonException $e) {
153
            throw new JsonException($e->getMessage(), $e->getCode());
154
        }
155
156
        if (\PHP_VERSION_ID < 70300 && JSON_ERROR_NONE !== json_last_error()) {
157
            throw new JsonException(json_last_error_msg(), json_last_error());
158
        }
159
160
        if (!\is_array($content)) {
161
            throw new JsonException(sprintf('JSON content was expected to decode to an array, %s returned.', \gettype($content)));
162
        }
163
164
        return $this->jsonData = $content;
165
    }
166
167
    /**
168
     * Returns the internal HttpKernel response.
169
     */
170
    public function getKernelResponse(): HttpFoundationResponse
171
    {
172
        return $this->httpFoundationResponse;
173
    }
174
175
    /**
176
     * Returns the internal BrowserKit reponse.
177
     */
178
    public function getBrowserKitResponse(): BrowserKitResponse
179
    {
180
        return $this->browserKitResponse;
181
    }
182
183
    /**
184
     * {@inheritdoc}.
185
     */
186
    public function cancel(): void
187
    {
188
        $this->info['error'] = 'Response has been canceled.';
189
    }
190
}
191