Passed
Pull Request — master (#2608)
by Kévin
04:09
created

Client::request()   C

Complexity

Conditions 12
Paths 81

Size

Total Lines 59
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 33
nc 81
nop 3
dl 0
loc 59
rs 6.9666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Bundle\FrameworkBundle\Client as FrameworkBundleClient;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
use Symfony\Component\HttpClient\HttpClientTrait;
19
use Symfony\Component\HttpKernel\KernelInterface;
20
use Symfony\Component\HttpKernel\Profiler\Profile as HttpProfile;
21
use Symfony\Contracts\HttpClient\HttpClientInterface;
22
use Symfony\Contracts\HttpClient\ResponseInterface;
23
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
24
25
/**
26
 * Convenient test client that makes requests to a Kernel object.
27
 *
28
 * @experimental
29
 *
30
 * @author Kévin Dunglas <[email protected]>
31
 */
32
final class Client implements HttpClientInterface
33
{
34
    public const OPTIONS_DEFAULT = [
35
        'auth_basic' => null,                               // array|string - an array containing the username as first value, and optionally the
36
                                                            //   password as the second one; or string like username:password - enabling HTTP Basic
37
                                                            //   authentication (RFC 7617)
38
        'auth_bearer' => null,                              // string - a token enabling HTTP Bearer authorization (RFC 6750)
39
        'query' => [],                                      // string[] - associative array of query string values to merge with the request's URL
40
        'headers' => ['accept' => ['application/ld+json']], // iterable|string[]|string[][] - headers names provided as keys or as part of values
41
        'body' => '',                                       // array|string|resource|\Traversable|\Closure - the callback SHOULD yield a string
42
        'json' => null,                                     // array|\JsonSerializable - when set, implementations MUST set the "body" option to
43
        //   the JSON-encoded value and set the "content-type" headers to a JSON-compatible
44
        'base_uri' => 'http://example.com',                 // string - the URI to resolve relative URLs, following rules in RFC 3986, section 2
45
    ];
46
47
    use HttpClientTrait;
48
49
    private $fwbClient;
50
51
    public function __construct(FrameworkBundleClient $fwbClient)
52
    {
53
        $this->fwbClient = $fwbClient;
54
        $fwbClient->followRedirects(false);
55
    }
56
57
    /**
58
     * @see Client::OPTIONS_DEFAULTS for available options
59
     *
60
     * {@inheritdoc}
61
     */
62
    public function request(string $method, string $url, array $options = []): ResponseInterface
63
    {
64
        if (isset($options['body'])) {
65
            if (isset($options['headers'])) {
66
                $options['headers'] = self::normalizeHeaders($options['headers']);
67
            }
68
69
            $json = false;
70
            if (!isset($options['headers']['content-type'][0])) {
71
                // Content-Type default to JSON-LD if a body is set, but no Content-Type is defined
72
                $options['headers']['content-type'] = $options['headers']['content-type'] ?? ['application/ld+json'];
73
                $json = true;
74
            }
75
76
            if (
77
                (\is_array($options['body']) || $options['body'] instanceof \JsonSerializable) &&
78
                (
79
                    $json ||
80
                    preg_match('/\bjson\b/i', $options['headers']['content-type'][0])
81
                )
82
            ) {
83
                // Encode the JSON
84
                $options['json'] = $options['body'];
85
            }
86
        }
87
88
        $basic = $options['auth_basic'] ?? null;
89
        [$url, $options] = $this->prepareRequest($method, $url, $options, self::OPTIONS_DEFAULT);
90
91
        $server = [];
92
        // Convert headers to a $_SERVER-like array
93
        foreach ($options['headers'] as $key => $value) {
94
            if ('content-type' === $key) {
95
                $server['CONTENT_TYPE'] = $value[0] ?? '';
96
97
                continue;
98
            }
99
100
            // BrowserKit doesn't support setting several headers with the same name
101
            $server['HTTP_'.strtoupper(str_replace('-', '_', $key))] = $value[0] ?? '';
102
        }
103
104
        if ($basic) {
105
            $credentials = is_array($basic) ? $basic : explode(':', $basic, 2);
106
            $server['PHP_AUTH_USER'] = $credentials[0];
107
            $server['PHP_AUTH_PW'] = $credentials[1] ?? '';
108
        }
109
110
        $info = [
111
            'redirect_count' => 0,
112
            'redirect_url' => null,
113
            'http_method' => $method,
114
            'start_time' => microtime(true),
115
            'data' => $options['data'] ?? null,
116
            'url' => $url,
117
        ];
118
        $this->fwbClient->request($method, implode('', $url), [], [], $server, $options['body'] ?? null);
119
120
        return new Response($this->fwbClient->getResponse(), $this->fwbClient->getInternalResponse(), $info);
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function stream($responses, float $timeout = null): ResponseStreamInterface
127
    {
128
        throw new \LogicException('Not implemented yet');
129
    }
130
131
    /**
132
     * Gets the underlying test client.
133
     */
134
    public function getFrameworkBundleClient(): FrameworkBundleClient
135
    {
136
        return $this->fwbClient;
137
    }
138
139
    // The following methods are proxy methods for FrameworkBundleClient's ones
140
141
    /**
142
     * Returns the container.
143
     *
144
     * @return ContainerInterface|null Returns null when the Kernel has been shutdown or not started yet
145
     */
146
    public function getContainer()
147
    {
148
        return $this->fwbClient->getContainer();
149
    }
150
151
    /**
152
     * Returns the kernel.
153
     *
154
     * @return KernelInterface
155
     */
156
    public function getKernel()
157
    {
158
        return $this->fwbClient->getKernel();
159
    }
160
161
    /**
162
     * Gets the profile associated with the current Response.
163
     *
164
     * @return HttpProfile|false A Profile instance
165
     */
166
    public function getProfile()
167
    {
168
        return $this->fwbClient->getProfile();
169
    }
170
171
    /**
172
     * Enables the profiler for the very next request.
173
     *
174
     * If the profiler is not enabled, the call to this method does nothing.
175
     */
176
    public function enableProfiler()
177
    {
178
        $this->fwbClient->enableProfiler();
179
    }
180
181
    /**
182
     * Disables kernel reboot between requests.
183
     *
184
     * By default, the Client reboots the Kernel for each request. This method
185
     * allows to keep the same kernel across requests.
186
     */
187
    public function disableReboot()
188
    {
189
        $this->fwbClient->disableReboot();
190
    }
191
192
    /**
193
     * Enables kernel reboot between requests.
194
     */
195
    public function enableReboot()
196
    {
197
        $this->fwbClient->enableReboot();
198
    }
199
}
200