Passed
Pull Request — master (#255)
by Christopher
03:06
created

IncomingRequest::applyContentID()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace POData\OperationContext\Web;
6
7
use POData\Common\ODataConstants;
8
use POData\HttpProcessUtility;
9
use POData\OperationContext\HTTPRequestMethod;
10
use POData\OperationContext\IHTTPRequest;
11
12
/**
13
 * Class IncomingRequest
14
 * Class represents HTTP methods,headers and stream associated with a HTTP request
15
 * Note: This class will not throw any error.
16
 */
17
class IncomingRequest implements IHTTPRequest
18
{
19
    /**
20
     * The request headers.
21
     *
22
     * @var array
23
     */
24
    private $headers = [];
25
26
    /**
27
     * The incoming url in raw format.
28
     *
29
     * @var string|null
30
     */
31
    private $rawUrl = null;
32
33
    /**
34
     * The request method (GET, POST, PUT, DELETE or MERGE).
35
     *
36
     * @var HTTPRequestMethod HttpVerb
37
     */
38
    private $method;
39
40
    /**
41
     * The query options as key value.
42
     *
43
     * @var array(string, string);
44
     */
45
    private $queryOptions = [];
46
47
    /**
48
     * A collection that represents mapping between query option and its count.
49
     *
50
     * @var array(string, int)
51
     */
52
    private $queryOptionsCount = [];
53
54
    /**
55
     * The raw query string.
56
     *
57
     * @var string|null;
58
     */
59
    private $queryString = null;
60
61
    /**
62
     * The raw input.
63
     *
64
     * @var string|null;
65
     */
66
    private $rawInput = null;
67
68
    /**
69
     * Initialize a new instance of IHTTPRequest.
70
     *
71
     * @param HttpRequestMethod|null $method
72
     * @param array                  $queryOptions
73
     * @param array                  $queryOptionsCount
74
     * @param array                  $headers
75
     * @param string|null            $queryString
76
     * @param string|null            $rawInput
77
     * @param string|null            $rawUrl
78
     */
79
    public function __construct(
80
        HTTPRequestMethod $method = null,
81
        array $queryOptions = [],
82
        array $queryOptionsCount = [],
83
        array $headers = [],
84
        string $queryString = null,
85
        string $rawInput = null,
86
        string $rawUrl = null
87
    ) {
88
        $this->method            = $method ?? new HTTPRequestMethod($_SERVER['REQUEST_METHOD']);
89
        $this->queryOptions      = $queryOptions;
90
        $this->queryOptionsCount = $queryOptionsCount;
91
        $this->headers           = $headers;
92
        $this->queryString       = $queryString;
93
        $this->rawInput          = $rawInput;
94
        $this->rawUrl            = $rawUrl;
95
    }
96
97
    /**
98
     * get the raw incoming url.
99
     *
100
     * @return string RequestURI called by User with the value of QueryString
101
     */
102
    public function getRawUrl(): string
103
    {
104
        if (null === $this->rawUrl) {
105
            $rawProtocol = $_SERVER[ODataConstants::HTTPREQUEST_PROTOCOL] ?? '';
106
            if (false === stripos($rawProtocol, 'HTTPS')) {
107
                $this->rawUrl = ODataConstants::HTTPREQUEST_PROTOCOL_HTTP;
108
            } else {
109
                $this->rawUrl = ODataConstants::HTTPREQUEST_PROTOCOL_HTTPS;
110
            }
111
112
            $rawHost = $_SERVER[HttpProcessUtility::headerToServerKey(ODataConstants::HTTPREQUEST_HEADER_HOST)] ?? '';
113
            $rawUri  = $_SERVER[ODataConstants::HTTPREQUEST_URI] ?? '';
114
            $this->rawUrl .= '://' . $rawHost;
115
            $this->rawUrl .= utf8_decode(urldecode($rawUri));
116
        }
117
118
        return $this->rawUrl;
119
    }
120
121
    /**
122
     * get the specific request headers.
123
     *
124
     * @param string $key The header name
125
     *
126
     * @return string|null value of the header, NULL if header is absent
127
     */
128
    public function getRequestHeader(string $key): ?string
129
    {
130
        if (0 == count($this->headers)) {
131
            $this->getHeaders();
132
        }
133
        //PHP normalizes header keys
134
        $trimmedKey = HttpProcessUtility::headerToServerKey(trim($key));
135
136
        if (array_key_exists($trimmedKey, $this->headers)) {
137
            return $this->headers[$trimmedKey];
138
        }
139
        return null;
140
    }
141
142
    /**
143
     * Get the request headers
144
     * By-default we will get the following headers:
145
     * HTTP_HOST
146
     * HTTP_USER_AGENT
147
     * HTTP_ACCEPT
148
     * HTTP_ACCEPT_LANGUAGE
149
     * HTTP_ACCEPT_ENCODING
150
     * HTTP_ACCEPT_CHARSET
151
     * HTTP_KEEP_ALIVE
152
     * HTTP_CONNECTION,
153
     * HTTP_CACHE_CONTROL
154
     * HTTP_USER_AGENT
155
     * HTTP_IF_MATCH
156
     * HTTP_IF_NONE_MATCH
157
     * HTTP_IF_MODIFIED
158
     * HTTP_IF_MATCH
159
     * HTTP_IF_NONE_MATCH
160
     * HTTP_IF_UNMODIFIED_SINCE
161
     * //TODO: these aren't really headers...
162
     * REQUEST_URI
163
     * REQUEST_METHOD
164
     * REQUEST_TIME
165
     * SERVER_NAME
166
     * SERVER_PORT
167
     * SERVER_PORT_SECURE
168
     * SERVER_PROTOCOL
169
     * SERVER_SOFTWARE
170
     * CONTENT_TYPE
171
     * CONTENT_LENGTH
172
     * We may get user defined customized headers also like
173
     * HTTP_DATASERVICEVERSION, HTTP_MAXDATASERVICEVERSION.
174
     *
175
     * @return string[]
176
     */
177
    private function getHeaders(): array
178
    {
179
        if (0 == count($this->headers)) {
180
            $this->headers = [];
181
182
            foreach ($_SERVER as $key => $value) {
183
                if ((0 === strpos($key, 'HTTP_'))
184
                    || (0 === strpos($key, 'REQUEST_'))
185
                    || (0 === strpos($key, 'SERVER_'))
186
                    || (0 === strpos($key, 'CONTENT_'))
187
                ) {
188
                    $trimmedValue        = trim(strval($value));
189
                    $this->headers[$key] = isset($trimmedValue) ? $trimmedValue : null;
190
                }
191
            }
192
        }
193
194
        return $this->headers;
195
    }
196
197
    /**
198
     * Split the QueryString and assigns them as array element in KEY=VALUE.
199
     *
200
     * @return string[]|array[]
201
     */
202
    public function getQueryParameters(): array
203
    {
204
        if (0 == count($this->queryOptions)) {
205
            $queryString        = $this->getQueryString();
206
            $this->queryOptions = [];
207
208
            foreach (explode('&', $queryString) as $queryOptionAsString) {
209
                $queryOptionAsString = trim($queryOptionAsString);
210
                if (!empty($queryOptionAsString)) {
211
                    $result         = explode('=', $queryOptionAsString, 2);
212
                    $isNamedOptions = 2 == count($result);
213
                    $rawUrl         = rawurldecode($result[0]);
214
                    if ($isNamedOptions) {
215
                        $this->queryOptions[] = [$rawUrl => trim(rawurldecode($result[1]))];
216
                    } else {
217
                        $this->queryOptions[] = [null => trim($rawUrl)];
218
                    }
219
                }
220
            }
221
        }
222
223
        return $this->queryOptions;
224
    }
225
226
    /**
227
     * Get the QUERY_STRING
228
     * Note: This method will return empty string if no query string present.
229
     *
230
     * @return string $_header[HttpRequestHeaderQueryString]
231
     */
232
    private function getQueryString(): string
233
    {
234
        if (null === $this->queryString) {
235
            if (array_key_exists(ODataConstants::HTTPREQUEST_QUERY_STRING, $_SERVER)) {
236
                $rawString         = $_SERVER[ODataConstants::HTTPREQUEST_QUERY_STRING] ?? '';
237
                $this->queryString = utf8_decode(trim($rawString));
238
            } else {
239
                $this->queryString = '';
240
            }
241
        }
242
        return $this->queryString;
243
    }
244
245
    /**
246
     * Get the HTTP method
247
     * Value will be set from the value of the HTTP method of the
248
     * incoming Web request.
249
     *
250
     * @return HTTPRequestMethod $_header[HttpRequestHeaderMethod]
251
     */
252
    public function getMethod(): HTTPRequestMethod
253
    {
254
        return $this->method;
255
    }
256
257
    /**
258
     * @return string|null
259
     */
260
    public function getAllInput(): ?string
261
    {
262
        if (null === $this->rawInput) {
263
            $this->rawInput = file_get_contents('php://input');
264
        }
265
        return $this->rawInput;
266
    }
267
268
    /**
269
     * @param string $contentID
270
     */
271
    public function applyContentID(string $contentID, string $contentIdValue): void
272
    {
273
        $this->rawInput    = str_replace('$' . $contentID, $contentIdValue, $this->rawInput);
274
        $this->rawUrl      = str_replace('$' . $contentID, $contentIdValue, $this->rawUrl);
275
    }
276
}
277