Completed
Push — master ( 24bb3c...b333c5 )
by Christopher
04:00
created

IncomingRequest::getAllInput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace POData\OperationContext\Web;
4
5
use POData\Common\NotImplementedException;
6
use POData\Common\ODataConstants;
7
use POData\HttpProcessUtility;
8
use POData\OperationContext\HTTPRequestMethod;
9
use POData\OperationContext\IHTTPRequest;
10
11
/**
12
 * Class IncomingRequest
13
 * Class represents HTTP methods,headers and stream associated with a HTTP request
14
 * Note: This class will not throw any error.
15
 */
16
class IncomingRequest implements IHTTPRequest
17
{
18
    /**
19
     * The request headers.
20
     *
21
     * @var array
22
     */
23
    private $_headers;
24
25
    /**
26
     * The incoming url in raw format.
27
     *
28
     * @var string
29
     */
30
    private $_rawUrl = null;
31
32
    /**
33
     * The request method (GET, POST, PUT, DELETE or MERGE).
34
     *
35
     * @var HTTPRequestMethod HttpVerb
36
     */
37
    private $_method;
38
39
    /**
40
     * The query options as key value.
41
     *
42
     * @var array(string, string);
43
     */
44
    private $_queryOptions;
45
46
    /**
47
     * A collection that represents mapping between query
48
     * option and its count.
49
     *
50
     * @var array(string, int)
51
     */
52
    private $_queryOptionsCount;
53
54
    /**
55
     * Initialize a new instance of IncomingWebRequestContext.
56
     */
57
    public function __construct()
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
58
    {
59
        $this->_method = new HTTPRequestMethod($_SERVER['REQUEST_METHOD']);
60
        $this->_queryOptions = null;
61
        $this->_queryOptionsCount = null;
62
        $this->_headers = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array of property $_headers.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
63
        $this->getHeaders();
64
    }
65
66
    /**
67
     * Get the request headers
68
     * By-default we will get the following headers:
69
     * HTTP_HOST
70
     * HTTP_USER_AGENT
71
     * HTTP_ACCEPT
72
     * HTTP_ACCEPT_LANGUAGE
73
     * HTTP_ACCEPT_ENCODING
74
     * HTTP_ACCEPT_CHARSET
75
     * HTTP_KEEP_ALIVE
76
     * HTTP_CONNECTION,
77
     * HTTP_CACHE_CONTROL
78
     * HTTP_USER_AGENT
79
     * HTTP_IF_MATCH
80
     * HTTP_IF_NONE_MATCH
81
     * HTTP_IF_MODIFIED
82
     * HTTP_IF_MATCH
83
     * HTTP_IF_NONE_MATCH
84
     * HTTP_IF_UNMODIFIED_SINCE
85
     * //TODO: these aren't really headers...
86
     * REQUEST_URI
87
     * REQUEST_METHOD
88
     * REQUEST_TIME
89
     * SERVER_NAME
90
     * SERVER_PORT
91
     * SERVER_PORT_SECURE
92
     * SERVER_PROTOCOL
93
     * SERVER_SOFTWARE
94
     * CONTENT_TYPE
95
     * CONTENT_LENGTH
96
     * We may get user defined customized headers also like
97
     * HTTP_DATASERVICEVERSION, HTTP_MAXDATASERVICEVERSION.
98
     *
99
     * @return string[]
100
     */
101
    private function getHeaders()
0 ignored issues
show
Coding Style introduced by
getHeaders uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
102
    {
103
        if (is_null($this->_headers)) {
104
            $this->_headers = array();
105
106
            foreach ($_SERVER as $key => $value) {
107
                if ((strpos($key, 'HTTP_') === 0)
108
                    || (strpos($key, 'REQUEST_') === 0)
109
                    || (strpos($key, 'SERVER_') === 0)
110
                    || (strpos($key, 'CONTENT_') === 0)
111
                ) {
112
                    $trimmedValue = trim($value);
113
                    $this->_headers[$key] = isset($trimmedValue) ? $trimmedValue : null;
114
                }
115
            }
116
        }
117
118
        return $this->_headers;
119
    }
120
121
    /**
122
     * get the raw incoming url.
123
     *
124
     * @return string RequestURI called by User with the value of QueryString
125
     */
126
    public function getRawUrl()
0 ignored issues
show
Coding Style introduced by
getRawUrl uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
127
    {
128
        if (is_null($this->_rawUrl)) {
129
            if (!preg_match('/^HTTTPS/', $_SERVER[ODataConstants::HTTPREQUEST_PROTOCOL])) {
130
                $this->_rawUrl = ODataConstants::HTTPREQUEST_PROTOCOL_HTTP;
131
            } else {
132
                $this->_rawUrl = ODataConstants::HTTPREQUEST_PROTOCOL_HTTPS;
133
            }
134
135
            $this->_rawUrl .= '://' . $_SERVER[HttpProcessUtility::headerToServerKey(ODataConstants::HTTPREQUEST_HEADER_HOST)];
136
            $this->_rawUrl .= utf8_decode(urldecode($_SERVER[ODataConstants::HTTPREQUEST_URI]));
137
        }
138
139
        return $this->_rawUrl;
140
    }
141
142
    /**
143
     * get the specific request headers.
144
     *
145
     * @param string $key The header name
146
     *
147
     * @return string|null value of the header, NULL if header is absent
148
     */
149
    public function getRequestHeader($key)
150
    {
151
        if (!$this->_headers) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_headers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
152
            $this->getHeaders();
153
        }
154
        //PHP normalizes header keys
155
        $trimmedKey = HttpProcessUtility::headerToServerKey(trim($key));
156
157
        if (array_key_exists($trimmedKey, $this->_headers)) {
158
            return $this->_headers[$trimmedKey];
159
        }
160
161
        return null;
162
    }
163
164
    /**
165
     * Get the QUERY_STRING
166
     * Note: This method will return empty string if no query string present.
167
     *
168
     * @return string $_header[HttpRequestHeaderQueryString]
169
     */
170
    private function getQueryString()
0 ignored issues
show
Coding Style introduced by
getQueryString uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
171
    {
172
        if (array_key_exists(ODataConstants::HTTPREQUEST_QUERY_STRING, $_SERVER)) {
173
            return utf8_decode(trim($_SERVER[ODataConstants::HTTPREQUEST_QUERY_STRING]));
174
        } else {
175
            return '';
176
        }
177
    }
178
179
    /**
180
     * Split the QueryString and assigns them as array element in KEY=VALUE.
181
     *
182
     * @return string[]
183
     */
184
    public function getQueryParameters()
185
    {
186
        if (is_null($this->_queryOptions)) {
187
            $queryString = $this->getQueryString();
188
            $this->_queryOptions = array();
189
190
            foreach (explode('&', $queryString) as $queryOptionAsString) {
191
                $queryOptionAsString = trim($queryOptionAsString);
192
                if (!empty($queryOptionAsString)) {
193
                    $result = explode('=', $queryOptionAsString, 2);
194
                    $isNamedOptions = count($result) == 2;
195
                    if ($isNamedOptions) {
196
                        $this->_queryOptions[]
197
                            = array(rawurldecode($result[0]) => trim(rawurldecode($result[1])));
198
                    } else {
199
                        $this->_queryOptions[]
200
                            = array(null => trim(rawurldecode($result[0])));
201
                    }
202
                }
203
            }
204
        }
205
206
        return $this->_queryOptions;
207
    }
208
209
    /**
210
     * Get the HTTP method
211
     * Value will be set from the value of the HTTP method of the
212
     * incoming Web request.
213
     *
214
     * @return HTTPRequestMethod $_header[HttpRequestHeaderMethod]
215
     */
216
    public function getMethod()
217
    {
218
        return $this->_method;
219
    }
220
221
    public function getAllInput()
222
    {
223
        return file_get_contents("php://input");
224
    }
225
}
226