ParameterReader   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 295
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 35
eloc 90
c 3
b 0
f 0
dl 0
loc 295
rs 9.6

12 Methods

Rating   Name   Duplication   Size   Complexity  
A convertStringToBool() 0 11 3
A setUtf8Decoder() 0 28 4
A setParamDecoder() 0 20 4
A __construct() 0 7 1
A getRequestParameters() 0 23 4
A args() 0 11 2
A parseUrl() 0 3 1
A convertValue() 0 15 6
A decodeRequestParameter() 0 15 4
A decodeUtf8Parameters() 0 12 3
A decodeUtf8Parameter() 0 9 2
A uri() 0 3 1
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
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
22
23
namespace Jaxon\Request\Handler;
24
25
use Jaxon\App\Config\ConfigManager;
26
use Jaxon\App\I18n\Translator;
27
use Jaxon\Di\Container;
28
use Jaxon\Exception\RequestException;
29
use Jaxon\Utils\Http\UriDetector;
30
use Jaxon\Utils\Http\UriException;
31
32
use function array_map;
33
use function call_user_func;
34
use function floor;
35
use function function_exists;
36
use function iconv;
37
use function intval;
38
use function is_array;
39
use function is_string;
40
use function json_decode;
41
use function mb_convert_encoding;
42
use function strcasecmp;
43
use function strlen;
44
use function substr;
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
            return $sValue;
201
        case 'B':
202
            return $this->convertStringToBool($sValue);
203
        case 'N':
204
            return ($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

204
            return ($sValue == floor(/** @scrutinizer ignore-type */ $sValue) ? (int)$sValue : (float)$sValue);
Loading history...
205
        case '*':
206
        default:
207
            return null;
208
        }
209
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
210
211
    /**
212
     * Decode and convert a Jaxon request argument
213
     *
214
     * @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...
215
     *
216
     * @return mixed
217
     */
218
    private function decodeRequestParameter(string $sParam)
219
    {
220
        if($sParam === '')
221
        {
222
            return $sParam;
223
        }
224
225
        $sParam = call_user_func($this->cParamDecoder, $sParam);
226
227
        $xJson = json_decode($sParam, true);
228
        if($xJson !== null && $sParam != $xJson)
229
        {
230
            return $xJson;
231
        }
232
        return $this->convertValue($sParam);
233
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
234
235
    /**
236
     * @return array
237
     */
238
    private function getRequestParameters(): array
239
    {
240
        $aParams = [];
241
        $xRequest = $this->di->getRequest();
242
        $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...
243
        if(is_array($aBody))
244
        {
245
            if(isset($aBody['jxnargs']))
246
            {
247
                $aParams = $aBody['jxnargs'];
248
            }
249
        }
250
        else
251
        {
252
            $aParams = $xRequest->getQueryParams();
253
            if(isset($aParams['jxnargs']))
254
            {
255
                $aParams = $aParams['jxnargs'];
256
            }
257
        }
258
        return array_map(function($sParam) {
259
            return $this->decodeRequestParameter((string)$sParam);
260
        }, $aParams);
261
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
262
263
    /**
264
     * Decode a Jaxon request argument from UTF8
265
     *
266
     * @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...
267
     *
268
     * @return mixed
269
     */
270
    private function decodeUtf8Parameter($xValue)
271
    {
272
        if(is_string($xValue))
273
        {
274
            return call_user_func($this->cUtf8Decoder, $xValue);
275
        }
276
        // elseif(is_numeric($xValue) || is_bool($xValue))
277
        {
278
            return $xValue;
279
        }
280
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
281
282
    /**
283
     * Decode an array of Jaxon request arguments from UTF8
284
     *
285
     * @param array $aParams
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
286
     *
287
     * @return array
288
     */
289
    private function decodeUtf8Parameters(array $aParams): array
290
    {
291
        $aValues = [];
292
        foreach($aParams as $sKey => $xValue)
293
        {
294
            // Decode the key
295
            $sKey = call_user_func($this->cUtf8Decoder, $sKey);
296
            // Decode the value
297
            $aValues[$sKey] = is_array($xValue) ?
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "?"; newline found
Loading history...
298
                $this->decodeUtf8Parameters($xValue) : $this->decodeUtf8Parameter($xValue);
299
        }
300
        return $aValues;
301
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
302
303
    /**
304
     * Return the array of arguments from the GET or POST data
305
     *
306
     * @return array
307
     * @throws RequestException
308
     */
309
    public function args(): array
310
    {
311
        $this->setParamDecoder();
312
        $aParams = $this->getRequestParameters();
313
        if(!$this->xConfigManager->getOption('core.decode_utf8'))
314
        {
315
            return $aParams;
316
        }
317
        $this->setUtf8Decoder();
318
        $this->xConfigManager->setOption('core.decode_utf8', false);
319
        return $this->decodeUtf8Parameters($aParams);
320
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
321
322
    /**
323
     * Get the URI of the current request
324
     *
325
     * @throws UriException
326
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
327
    public function uri(): string
328
    {
329
        return $this->xUriDetector->detect($this->di->getRequest()->getServerParams());
330
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
331
332
    /**
333
     * Make the specified URL suitable for redirect
334
     *
335
     * @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...
336
     *
337
     * @return string
338
     */
339
    public function parseUrl(string $sURL): string
340
    {
341
        return $this->xUriDetector->redirect($sURL, $this->di->getRequest()->getServerParams());
342
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
343
}
344