Failed Conditions
Pull Request — master (#1)
by Arnold
05:51
created

Connector::getBaseRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Jasny\Codeception;
4
5
use Psr\Http\Message\ServerRequestInterface;
6
use Psr\Http\Message\ResponseInterface;
7
use Psr\Http\Message\UploadedFileInterface;
8
use Psr\Http\Message\UriInterface;
9
use Jasny\HttpMessage\Response;
10
use Jasny\HttpMessage\ServerRequest;
11
use Jasny\HttpMessage\UploadedFile;
12
use Jasny\HttpMessage\Uri;
13
use Jasny\HttpMessage\Stream;
14
use Jasny\HttpMessage\OutputBufferStream;
15
use Jasny\Router;
16
use Symfony\Component\BrowserKit\Client;
17
use Symfony\Component\BrowserKit\Request as BrowserKitRequest;
18
use Symfony\Component\BrowserKit\Response as BrowserKitResponse;
19
20
/**
21
 * Codeception connector for Jasny\MVC
22
 */
23
class Connector extends Client
24
{
25
    /**
26
     * @var Router
27
     */
28
    protected $router;
29
    
30
    /**
31
     * Request with the current global environent
32
     * @var ServerRequestInterface
33
     */
34
    protected $baseRequest;
35
    
36
    /**
37
     * Request with the current global environent
38
     * @var ResponseInterface
39
     */
40
    protected $baseResponse;
41
    
42
    
43
    /**
44
     * Set the router
45
     * 
46
     * @param Router $router
47
     * @param string $legacy
0 ignored issues
show
Bug introduced by
There is no parameter named $legacy. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
48
     */
49 3
    public function setRouter(Router $router)
50
    {
51 3
        $this->router = $router;
52 3
    }
53
    
54
    /**
55
     * Get the router
56
     * 
57
     * @return Router
58
     */
59 4
    public function getRouter()
60
    {
61 4
        return $this->router;
62
    }
63
    
64
    
65
    /**
66
     * Set the base request
67
     * 
68
     * @param ServerRequestInterface $request
69
     */
70 3
    public function setBaseRequest(ServerRequestInterface $request)
71
    {
72 3
        if ($request instanceof ServerRequest && $request->isStale()) {
73 1
            throw new \RuntimeException("Unable to set base request: ServerRequest is stale");
74
        }
75
        
76 2
        $this->baseRequest = $request;
77 2
    }
78
    
79
    /**
80
     * Get the base request
81
     * 
82
     * @return ServerRequestInterface
83
     */
84 4
    public function getBaseRequest()
85
    {
86 4
        if (!isset($this->baseRequest)) {
87 2
            $this->baseRequest = new ServerRequest();
88 2
        }
89
        
90 4
        return $this->baseRequest;
91
    }
92
    
93
    
94
    /**
95
     * Set the base response
96
     * 
97
     * @param ResponseInterface $response
98
     */
99 3
    public function setBaseResponse(ResponseInterface $response)
100
    {
101 3
        if ($response instanceof Response && $response->isStale()) {
102 1
            throw new \RuntimeException("Unable to set base response: Response is stale");
103
        }
104
        
105 2
        $this->baseResponse = $response;
106 2
    }
107
    
108
    /**
109
     * Get the base response
110
     * 
111
     * @return ResponseInterface
112
     */
113 4
    public function getBaseResponse()
114
    {
115 4
        if (!isset($this->baseResponse)) {
116 2
            $this->baseResponse = new Response();
117 2
        }
118
        
119 4
        return $this->baseResponse;
120
    }
121
    
122
    /**
123
     * Reset the request and response.
124
     * This is only required when the request and/or response are bound to the global environment.
125
     */
126 3
    public function reset()
127
    {
128 3
        if (isset($this->baseRequest) && $this->baseRequest instanceof ServerRequest && $this->baseRequest->isStale()) {
129 1
            $this->baseRequest = $this->baseRequest->revive();
130 1
        }
131
132 3
        if (isset($this->baseResponse) && $this->baseResponse instanceof Response && $this->baseResponse->isStale()) {
133 1
            $this->baseResponse = $this->baseResponse->revive();
134 1
        }
135
        
136
        // Clear output buffer
137 3
        if (isset($this->baseResponse) && $this->baseResponse->getBody() instanceof OutputBufferStream) {
138 1
            $this->baseResponse = $this->baseResponse->withBody(clone $this->baseResponse->getBody());
139 1
        }
140 3
    }
141
142
143
    /**
144
     * Build a full URI from a request
145
     * 
146
     * @param BrowserKitRequest $request
147
     * @return array [Uri, queryParams]
148
     */
149 2
    protected function buildFullUri(BrowserKitRequest $request)
150
    {
151 2
        $uri = new Uri($request->getUri());
152
        
153 2
        $queryParams = null;
154 2
        parse_str($uri->getQuery(), $queryParams);
155
        
156 2
        if ($request->getMethod() === 'GET') {
157 1
            $queryParams = array_merge($queryParams, $request->getParameters());
158 1
            $uri = $uri->withQuery(http_build_query($queryParams));
159 1
        }
160
        
161 2
        return [$uri, $queryParams];
162
    }
163
    
164
    /**
165
     * Get additional server params from request.
166
     * @internal It would be nicer if this was solved by Jasny Http Message
167
     * 
168
     * @param BrowserKitRequest $request
169
     * @param UriInterface      $uri
170
     * @param array             $queryParams
171
     * @return array
172
     */
173 2
    protected function determineServerParams(BrowserKitRequest $request, UriInterface $uri, array $queryParams)
174
    {
175
        return [
176 2
            'REQUEST_METHOD' => $request->getMethod(),
177 2
            'QUERY_STRING' => http_build_query($queryParams),
178 2
            'REQUEST_URI' => (string)($uri->withScheme('')->withHost('')->withPort('')->withUserInfo(''))
179 2
        ];
180
    }
181
    
182
    /**
183
     * Convert a codeception request to a Jasny PSR-7 server request
184
     * 
185
     * @param BrowserKitRequest $request
186
     * @return ServerRequest
187
     */
188 2
    protected function convertRequest(BrowserKitRequest $request)
189
    {
190 2
        list($uri, $queryParams) = $this->buildFullUri($request);
191
        
192 2
        $stream = fopen('php://temp', 'r+');
193 2
        fwrite($stream, $request->getContent());
194 2
        fseek($stream, 0);
195
        
196 2
        $baseRequest = $this->getBaseRequest();
197
        
198 2
        if ($baseRequest instanceof ServerRequest) {
199 2
            $serverParams = $this->determineServerParams($request, $uri, $queryParams);
0 ignored issues
show
Bug introduced by
It seems like $queryParams can also be of type null; however, Jasny\Codeception\Connec...determineServerParams() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
200 2
            $baseRequest = $baseRequest->withServerParams($request->getServer() + $serverParams);
201 2
        }
202
        
203
        $psrRequest = $baseRequest
204 2
            ->withBody(new Stream($stream))
205 2
            ->withMethod($request->getMethod())
206 2
            ->withRequestTarget((string)($uri->withScheme('')->withHost('')->withPort('')->withUserInfo('')))
207 2
            ->withCookieParams($request->getCookies())
208 2
            ->withUri($uri)
209 2
            ->withQueryParams($queryParams)
0 ignored issues
show
Bug introduced by
It seems like $queryParams can also be of type null; however, Psr\Http\Message\ServerR...face::withQueryParams() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
210 2
            ->withUploadedFiles($this->convertUploadedFiles($request->getFiles()));
211
        
212 2
        if ($request->getMethod() !== 'GET' && !empty($request->getParameters())) {
213 1
            $psrRequest = $psrRequest->withParsedBody($request->getParameters());
214 1
        }
215
        
216 2
        return $psrRequest;
217
    }
218
    
219
    /**
220
     * Convert a Jasny PSR-7 response to a codeception response
221
     * 
222
     * @param ResponseInterface $psrResponse
223
     * @return BrowserKitResponse
224
     */
225 2
    protected function convertResponse(ResponseInterface $psrResponse)
226
    {
227 2
        return new BrowserKitResponse(
228 2
            (string)$psrResponse->getBody(),
229 2
            $psrResponse->getStatusCode() ?: 200,
230 2
            $psrResponse->getHeaders()
231 2
        );
232
    }
233
    
234
    /**
235
     * Convert a list of uploaded files to a Jasny PSR-7 uploaded files
236
     * 
237
     * @param array $files
238
     * @return UploadedFile[]|array
239
     */
240 2
    protected function convertUploadedFiles(array $files)
241
    {
242 2
        $fileObjects = [];
243
        
244 2
        foreach ($files as $fieldName => $file) {
245 1
            if ($file instanceof UploadedFileInterface) {
246
                $fileObjects[$fieldName] = $file;
247 1
            } elseif (!isset($file['tmp_name']) && !isset($file['name'])) {
248
                $fileObjects[$fieldName] = $this->convertUploadedFiles($file);
249
            } else {
250 1
                $fileObjects[$fieldName] = new UploadedFile($file);
251
            }
252 2
        }
253
        
254 2
        return $fileObjects;
255
    }
256
    
257
    
258
    /**
259
     * Makes a request.
260
     * 
261
     * @param BrowserKitRequest $request
262
     * @return BrowserKitResponse
263
     */
264 3
    protected function doRequest($request)
265
    {
266 3
        if ($this->getRouter() === null) {
267 1
            throw new \BadMethodCallException("Router not set");
268
        }
269
        
270 2
        $this->reset(); // Reset before each HTTP request
271
        
272 2
        $psrRequest = $this->convertRequest($request);
273
        
274 2
        $router = $this->getRouter();
275 2
        $psrResponse = $router->handle($psrRequest, $this->getBaseResponse());
276
        
277 2
        return $this->convertResponse($psrResponse);
278
    }
279
}
280