Completed
Push — master ( 01eb59...230b2e )
by Oscar
02:45
created

MethodOverride::getOverrideMethod()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 18
rs 8.2222
cc 7
eloc 10
nc 5
nop 1
1
<?php
2
3
namespace Psr7Middlewares\Middleware;
4
5
use Psr\Http\Message\ServerRequestInterface;
6
use Psr\Http\Message\ResponseInterface;
7
8
/**
9
 * Middleware to override the request method using http headers.
10
 */
11
class MethodOverride
12
{
13
    const HEADER = 'X-Http-Method-Override';
14
15
    /**
16
     * @var array Allowed methods overrided in GET
17
     */
18
    private $get = ['HEAD', 'CONNECT', 'TRACE', 'OPTIONS'];
19
20
    /**
21
     * @var array Allowed methods overrided in POST
22
     */
23
    private $post = ['PATCH', 'PUT', 'DELETE', 'COPY', 'LOCK', 'UNLOCK'];
24
25
    /**
26
     * @var null|string The POST parameter name
27
     */
28
    private $postParam;
29
30
    /**
31
     * @var null|string The GET parameter name
32
     */
33
    private $getParam;
34
35
    /**
36
     * Set allowed method for GET.
37
     *
38
     * @return self
39
     */
40
    public function get(array $methods)
41
    {
42
        $this->get = $methods;
43
44
        return $this;
45
    }
46
47
    /**
48
     * Set allowed method for POST.
49
     *
50
     * @return self
51
     */
52
    public function post(array $methods)
53
    {
54
        $this->post = $methods;
55
56
        return $this;
57
    }
58
59
    /**
60
     * Configure the parameters.
61
     * 
62
     * @param string $name
63
     * @param bool   $get
64
     *
65
     * @return self
66
     */
67
    public function parameter($name, $get = true)
68
    {
69
        $this->postParam = $name;
70
71
        if ($get) {
72
            $this->getParam = $name;
73
        }
74
75
        return $this;
76
    }
77
78
    /**
79
     * Execute the middleware.
80
     *
81
     * @param ServerRequestInterface $request
82
     * @param ResponseInterface      $response
83
     * @param callable               $next
84
     *
85
     * @return ResponseInterface
86
     */
87
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
88
    {
89
        $method = $this->getOverrideMethod($request);
90
91
        if (!empty($method) && $method !== $request->getMethod()) {
92
            $allowed = $this->getAllowedOverrideMethods($request);
93
94
            if (!empty($allowed)) {
95
                if (in_array($method, $allowed)) {
96
                    $request = $request->withMethod($method);
97
                } else {
98
                    return $response->withStatus(405);
99
                }
100
            }
101
        }
102
103
        return $next($request, $response);
104
    }
105
106
    /**
107
     * Returns the override method.
108
     * 
109
     * @param ServerRequestInterface $request
110
     * 
111
     * @return string
112
     */
113
    private function getOverrideMethod(ServerRequestInterface $request)
114
    {
115
        if ($request->getMethod() === 'POST' && $this->postParam !== null) {
116
            $params = $request->getParsedBody();
117
118
            if (isset($params[$this->postParam])) {
119
                return strtoupper($params[$this->postParam]);
120
            }
121
        } elseif ($request->getMethod() === 'GET' && $this->getParam !== null) {
122
            $params = $request->getQueryParams();
123
124
            if (isset($params[$this->getParam])) {
125
                return strtoupper($params[$this->getParam]);
126
            }
127
        }
128
129
        return strtoupper($request->getHeaderLine(self::HEADER));
130
    }
131
132
    /**
133
     * Returns the allowed override methods.
134
     * 
135
     * @param ServerRequestInterface $request
136
     * 
137
     * @return array
138
     */
139
    private function getAllowedOverrideMethods(ServerRequestInterface $request)
140
    {
141
        switch ($request->getMethod()) {
142
            case 'GET':
143
                return $this->get;
144
145
            case 'POST':
146
                return $this->post;
147
148
            default:
149
                return [];
150
        }
151
    }
152
}
153