Completed
Push — master ( 931ecb...01eb59 )
by Oscar
02:40
created

MethodOverride::get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
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|null
112
     */
113
    private function getOverrideMethod(ServerRequestInterface $request)
114
    {
115 View Code Duplication
        if ($request->getMethod() === 'POST' && $this->postParam !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
            $params = $request->getParsedBody();
117
118
            if (isset($params[$this->postParam])) {
119
                return strtoupper($params[$this->postParam]);
120
            }
121
        }
122
123 View Code Duplication
        if ($request->getMethod() === 'GET' && $this->getParam !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
            $params = $request->getQueryParams();
125
126
            if (isset($params[$this->getParam])) {
127
                return strtoupper($params[$this->getParam]);
128
            }
129
        }
130
131
        $method = $request->getHeaderLine(self::HEADER);
132
133
        if (!empty($method) && ($method !== $request->getMethod())) {
134
            return strtoupper($method);
135
        }
136
    }
137
138
    /**
139
     * Returns the allowed override methods.
140
     * 
141
     * @param ServerRequestInterface $request
142
     * 
143
     * @return array
144
     */
145
    private function getAllowedOverrideMethods(ServerRequestInterface $request)
146
    {
147
        switch ($request->getMethod()) {
148
            case 'GET':
149
                return $this->get;
150
151
            case 'POST':
152
                return $this->post;
153
154
            default:
155
                return [];
156
        }
157
    }
158
}
159