Completed
Push — master ( 34bc1a...41d5a5 )
by Thierry
02:48 queued 02:48
created

ParameterReader::uri()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * ParameterReader.php
5
 *
6
 * This class processes the input arguments from the GET or POST data of the request.
7
 * If this is a request for the initial page load, no arguments will be processed.
8
 * During a jaxon request, any arguments found in the GET or POST will be converted to a PHP array.
9
 *
10
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
11
 * @author Jared White
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
12
 * @author J. Max Wilson
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
13
 * @author Joseph Woolley
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
14
 * @author Steffen Konerow
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
15
 * @author Thierry Feuzeu <[email protected]>
16
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
17
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
18
 * @copyright 2016 Thierry Feuzeu <[email protected]>
19
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
20
 * @link https://github.com/jaxon-php/jaxon-core
21
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
PHP version not specified
Loading history...
22
23
namespace Jaxon\Request\Handler;
24
25
use Jaxon\Di\Container;
26
use Jaxon\Config\ConfigManager;
27
use Jaxon\Exception\RequestException;
28
use Jaxon\Utils\Http\UriDetector;
29
use Jaxon\Utils\Http\UriException;
30
use Jaxon\Utils\Translation\Translator;
31
32
use function strcasecmp;
33
use function is_array;
34
use function is_string;
35
use function substr;
36
use function strlen;
37
use function floor;
38
use function json_decode;
39
use function call_user_func;
40
use function array_map;
41
use function function_exists;
42
use function iconv;
43
use function intval;
44
use function mb_convert_encoding;
45
use function utf8_decode;
46
47
class ParameterReader
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class ParameterReader
Loading history...
48
{
49
    /**
50
     * @var Container
51
     */
52
    protected $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
53
54
    /**
55
     * @var ConfigManager
56
     */
57
    protected $xConfigManager;
58
59
    /**
60
     * @var Translator
61
     */
62
    protected $xTranslator;
63
64
    /**
65
     * @var UriDetector
66
     */
67
    private $xUriDetector;
68
69
    /**
70
     * The function which decodes input parameters.
71
     *
72
     * @var callable
73
     */
74
    private $cParamDecoder;
75
76
    /**
77
     * The function which decodes utf8 string.
78
     *
79
     * @var callable
80
     */
81
    private $cUtf8Decoder;
82
83
    /**
84
     * The constructor
85
     *
86
     * @param Container $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
87
     * @param ConfigManager $xConfigManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
88
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
89
     * @param UriDetector $xUriDetector
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
90
     */
91
    public function __construct(Container $di, ConfigManager $xConfigManager,
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
92
        Translator $xTranslator, UriDetector $xUriDetector)
93
    {
94
        $this->di = $di;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 13 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
95
        $this->xConfigManager = $xConfigManager;
96
        $this->xTranslator = $xTranslator;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
97
        $this->xUriDetector = $xUriDetector;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
98
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
99
100
    /**
101
     * Choose the function to use to decode input data.
102
     *
103
     * @return void
104
     */
105
    private function setParamDecoder()
106
    {
107
        // Parameters are url encoded when uploading files
108
        $aServerParams = $this->di->getRequest()->getServerParams();
109
        $sContentType = '';
110
        if(isset($aServerParams['CONTENT_TYPE']))
111
        {
112
            $sContentType = $aServerParams['CONTENT_TYPE'];
113
        }
114
        elseif(isset($aServerParams['HTTP_CONTENT_TYPE']))
115
        {
116
            $sContentType = $aServerParams['HTTP_CONTENT_TYPE'];
117
        }
118
        $sType = 'multipart/form-data';
119
        if(strncmp($sContentType, $sType, strlen($sType)) !== 0)
120
        {
121
            $this->cParamDecoder = function($sParam) { return $sParam; };
122
            return;
123
        }
124
        $this->cParamDecoder = function($sParam) { return urldecode($sParam); };
125
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
126
127
    /**
128
     * Choose the function to use to decode input data.
129
     *
130
     * @return void
131
     * @throws RequestException
132
     */
133
    private function setUtf8Decoder()
134
    {
135
        // By default, no decoding
136
        $this->cUtf8Decoder = function($sStr) {
137
            return $sStr;
138
        };
139
        $sEncoding = $this->xConfigManager->getOption('core.encoding', '');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
140
        if(function_exists('iconv'))
141
        {
142
            $this->cUtf8Decoder = function($sStr) use($sEncoding) {
143
                return iconv("UTF-8", $sEncoding . '//TRANSLIT', $sStr);
144
            };
145
        }
146
        elseif(function_exists('mb_convert_encoding'))
147
        {
148
            $this->cUtf8Decoder = function($sStr) use($sEncoding) {
149
                return mb_convert_encoding($sStr, $sEncoding, "UTF-8");
150
            };
151
        }
152
        elseif($sEncoding === "ISO-8859-1")
153
        {
154
            $this->cUtf8Decoder = function($sStr) {
155
                return utf8_decode($sStr);
156
            };
157
        }
158
        else
159
        {
160
            throw new RequestException($this->xTranslator->trans('errors.request.conversion'));
161
        }
162
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
163
164
    /**
165
     * Converts a string to a bool var
166
     *
167
     * @param string $sValue    The string to be converted
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
168
     *
169
     * @return bool
170
     */
171
    private function convertStringToBool(string $sValue): bool
172
    {
173
        if(strcasecmp($sValue, 'true') === 0)
174
        {
175
            return true;
176
        }
177
        if(strcasecmp($sValue, 'false') === 0)
178
        {
179
            return false;
180
        }
181
        return (intval($sValue) !== 0);
182
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
183
184
    /**
185
     * Convert a Jaxon request argument to its value
186
     *
187
     * Depending on its first char, the Jaxon request argument is converted to a given type.
188
     *
189
     * @param string $sValue    The keys of the options in the file
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
190
     *
191
     * @return string|bool|integer|double|null
192
     */
193
    private function convertValue(string $sValue)
194
    {
195
        $cType = substr($sValue, 0, 1);
196
        $sValue = substr($sValue, 1);
197
        switch($cType)
198
        {
199
        case 'S':
200
            $value = !$sValue ? '' : $sValue;
201
            break;
202
        case 'B':
203
            $value = $this->convertStringToBool($sValue);
204
            break;
205
        case 'N':
206
            $value = ($sValue == floor($sValue) ? (int)$sValue : (float)$sValue);
0 ignored issues
show
Bug introduced by
$sValue of type string is incompatible with the type double|integer expected by parameter $num of floor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

206
            $value = ($sValue == floor(/** @scrutinizer ignore-type */ $sValue) ? (int)$sValue : (float)$sValue);
Loading history...
207
            break;
208
        case '*':
209
        default:
210
            $value = null;
211
            break;
212
        }
213
        return $value;
214
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
215
216
    /**
217
     * Decode and convert a Jaxon request argument
218
     *
219
     * @param string $sParam    The Jaxon request argument
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
220
     *
221
     * @return mixed
222
     */
223
    private function decodeRequestParameter(string $sParam)
224
    {
225
        if($sParam === '')
226
        {
227
            return $sParam;
228
        }
229
230
        $sParam = call_user_func($this->cParamDecoder, $sParam);
231
232
        $xJson = json_decode($sParam, true);
233
        if($xJson !== null && $sParam != $xJson)
234
        {
235
            return $xJson;
236
        }
237
        return $this->convertValue($sParam);
238
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
239
240
    /**
241
     * @return array
242
     */
243
    private function getRequestParameters(): array
244
    {
245
        $aParams = [];
246
        $xRequest = $this->di->getRequest();
247
        $aBody = $xRequest->getParsedBody();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
248
        if(is_array($aBody))
249
        {
250
            if(isset($aBody['jxnargs']))
251
            {
252
                $aParams = $aBody['jxnargs'];
253
            }
254
        }
255
        else
256
        {
257
            $aParams = $xRequest->getQueryParams();
258
            if(isset($aParams['jxnargs']))
259
            {
260
                $aParams = $aParams['jxnargs'];
261
            }
262
        }
263
        return array_map(function($sParam) {
264
            return $this->decodeRequestParameter((string)$sParam);
265
        }, $aParams);
266
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
267
268
    /**
269
     * Decode a Jaxon request argument from UTF8
270
     *
271
     * @param mixed $xValue    The value of the argument being decoded
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
272
     *
273
     * @return mixed
274
     */
275
    private function decodeUtf8Parameter($xValue)
276
    {
277
        if(is_string($xValue))
278
        {
279
            return call_user_func($this->cUtf8Decoder, $xValue);
280
        }
281
        // elseif(is_numeric($xValue) || is_bool($xValue))
282
        {
283
            return $xValue;
284
        }
285
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
286
287
    /**
288
     * Decode an array of Jaxon request arguments from UTF8
289
     *
290
     * @param array $aParams
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
291
     *
292
     * @return array
293
     */
294
    private function decodeUtf8Parameters(array $aParams): array
295
    {
296
        $aValues = [];
297
        foreach($aParams as $sKey => $xValue)
298
        {
299
            // Decode the key
300
            $sKey = call_user_func($this->cUtf8Decoder, $sKey);
301
            // Decode the value
302
            $aValues[$sKey] = is_array($xValue) ?
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "?"; newline found
Loading history...
303
                $this->decodeUtf8Parameters($xValue) : $this->decodeUtf8Parameter($xValue);
304
        }
305
        return $aValues;
306
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
307
308
    /**
309
     * Return the array of arguments from the GET or POST data
310
     *
311
     * @return array
312
     * @throws RequestException
313
     */
314
    public function args(): array
315
    {
316
        $this->setParamDecoder();
317
        $aParams = $this->getRequestParameters();
318
        if(!$this->xConfigManager->getOption('core.decode_utf8'))
319
        {
320
            return $aParams;
321
        }
322
        $this->setUtf8Decoder();
323
        $this->xConfigManager->setOption('core.decode_utf8', false);
324
        return $this->decodeUtf8Parameters($aParams);
325
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
326
327
    /**
328
     * Get the URI of the current request
329
     *
330
     * @throws UriException
331
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
332
    public function uri(): string
333
    {
334
        return $this->xUriDetector->detect($this->di->getRequest()->getServerParams());
335
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
336
337
    /**
338
     * Make the specified URL suitable for redirect
339
     *
340
     * @param string $sURL    The relative or fully qualified URL
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
341
     *
342
     * @return string
343
     */
344
    public function parseUrl(string $sURL): string
345
    {
346
        return $this->xUriDetector->redirect($sURL, $this->di->getRequest()->getServerParams());
347
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
348
}
349