RequestHandlerMiddleware::requestedWith()   B
last analyzed

Complexity

Conditions 10
Paths 7

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
cc 10
nc 7
nop 1
dl 0
loc 25
rs 7.6666
c 0
b 0
f 0
ccs 0
cts 17
cp 0
crap 110

How to fix   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
 * Copyright 2016 - 2018, Cake Development Corporation (http://cakedc.com)
4
 *
5
 * Licensed under The MIT License
6
 * Redistributions of files must retain the above copyright notice.
7
 *
8
 * @copyright Copyright 2016 - 2018, Cake Development Corporation (http://cakedc.com)
9
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
10
 */
11
12
namespace CakeDC\Api\Middleware;
13
14
use Cake\Utility\Exception\XmlException;
15
use Cake\Utility\Xml;
16
use Psr\Http\Message\ResponseInterface;
17
use Psr\Http\Message\ServerRequestInterface;
18
use RuntimeException;
19
20
/**
21
 * Applies routing rules to the request and creates the controller
22
 * instance if possible.
23
 */
24
class RequestHandlerMiddleware
25
{
26
27
    /**
28
     * Request object
29
     *
30
     * @var \Cake\Http\ServerRequest
31
     */
32
    public $request;
33
34
    /**
35
     * Response object
36
     *
37
     * @var \Cake\Http\Response
38
     */
39
    public $response;
40
41
    /**
42
     * @param \Psr\Http\Message\ServerRequestInterface $request The request.
43
     * @param \Psr\Http\Message\ResponseInterface $response The response.
44
     * @param callable $next The next middleware to call.
45
     * @return \Psr\Http\Message\ResponseInterface A response.
46
     */
47
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
48
    {
49
        $inputTypeMap = [
50
            'json' => ['json_decode', true],
51
            'xml' => [[$this, 'convertXml']],
52
        ];
53
54
        $this->request = $request;
0 ignored issues
show
Documentation Bug introduced by
$request is of type object<Psr\Http\Message\ServerRequestInterface>, but the property $request was declared to be of type object<Cake\Http\ServerRequest>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
55
        $this->response = $response;
0 ignored issues
show
Documentation Bug introduced by
$response is of type object<Psr\Http\Message\ResponseInterface>, but the property $response was declared to be of type object<Cake\Http\Response>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
56
        $parsedBody = $request->getParsedBody();
57
58
        foreach ($inputTypeMap as $type => $handler) {
59
            if (!is_callable($handler[0])) {
60
                throw new RuntimeException(sprintf("Invalid callable for '%s' type.", $type));
61
            }
62
            if (empty($parsedBody) && $this->requestedWith($type)) {
63
                $input = call_user_func_array([$this->request, 'input'], $handler);
64
65
                return $next($request->withParsedBody($input), $response);
66
            }
67
        }
68
69
        return $next($request, $response);
70
    }
71
72
    /**
73
     * Determines the content type of the data the client has sent (i.e. in a POST request)
74
     *
75
     * @param string|array|null $type Can be null (or no parameter), a string type name, or an array of types
76
     * @return mixed If a single type is supplied a boolean will be returned. If no type is provided
77
     *   The mapped value of CONTENT_TYPE will be returned. If an array is supplied the first type
78
     *   in the request content type will be returned.
79
     */
80
    public function requestedWith($type = null)
81
    {
82
        $request = $this->request;
83
        if (!$request->is('post') && !$request->is('put') && !$request->is('patch') && !$request->is('delete')) {
84
            return null;
85
        }
86
        if (is_array($type)) {
87
            foreach ($type as $t) {
88
                if ($this->requestedWith($t)) {
89
                    return $t;
90
                }
91
            }
92
93
            return false;
94
        }
95
96
        list($contentType) = explode(';', $request->contentType());
97
        $response = $this->response;
98
        if ($type === null) {
99
            return $response->mapType($contentType);
100
        }
101
        if (is_string($type)) {
102
            return ($type === $response->mapType($contentType));
103
        }
104
    }
105
106
    /**
107
     * Helper method to parse xml input data, due to lack of anonymous functions
108
     * this lives here.
109
     *
110
     * @param string $xml XML string.
111
     * @return array Xml array data
112
     */
113
    public function convertXml($xml)
114
    {
115
        try {
116
            $xml = Xml::build($xml, ['readFile' => false]);
117
            if (isset($xml->data)) {
118
                return Xml::toArray($xml->data);
119
            }
120
121
            return Xml::toArray($xml);
122
        } catch (XmlException $e) {
123
            return [];
124
        }
125
    }
126
}
127