Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions system/HTTP/IncomingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,60 @@ public function getRawInput()
return $output;
}

/**
* Gets a specific variable from raw input stream (send method in PUT, PATCH, DELETE).
*
* @param array|string|null $index The variable that you want which can use dot syntax for getting specific values.
* @param int|null $filter Filter Constant
* @param array|int|null $flags Option
*
* @return mixed
*/
public function getRawInputVar($index = null, ?int $filter = null, $flags = null)
{
helper('array');

parse_str($this->body ?? '', $output);

if (is_string($index)) {
$output = dot_array_search($index, $output);
} elseif (is_array($index)) {
$data = [];

foreach ($index as $key) {
$data[$key] = dot_array_search($key, $output);
}

[$output, $data] = [$data, null];
}

$filter ??= FILTER_DEFAULT;
$flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);

if (is_array($output)
&& (
$filter !== FILTER_DEFAULT
|| (
(is_numeric($flags) && $flags !== 0)
|| is_array($flags) && $flags !== []
)
)
) {
// Iterate over array and append filter and flags
array_walk_recursive($output, static function (&$val) use ($filter, $flags) {
$val = filter_var($val, $filter, $flags);
});

return $output;
}

if (is_string($output)) {
return filter_var($output, $filter, $flags);
}

return $output;
}

/**
* Fetch an item from GET data.
*
Expand Down
98 changes: 98 additions & 0 deletions tests/system/HTTP/IncomingRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,104 @@ public function testCanGrabGetRawInput()
$this->assertSame($expected, $request->getRawInput());
}

public function provideRawInputVarChecks()
{
return [
[
'username=admin001&role=administrator&usepass=0',
'username',
'admin001',
null,
null,
],
[
'username=admin001&role=administrator&usepass=0',
['role', 'usepass'],
[
'role' => 'administrator',
'usepass' => '0',
],
null,
null,
],
[
'username=admin001&role=administrator&usepass=0',
'not_exists',
null,
null,
null,
],
[
'username=admin001&role=administrator&usepass=0',
null,
[
'username' => 'admin001',
'role' => 'administrator',
'usepass' => '0',
],
null,
null,
],
[
'',
null,
[],
null,
null,
],
[
'username=admin001&role=administrator&usepass=0&foo[]=one&foo[]=two',
['username', 'foo'],
[
'username' => 'admin001',
'foo' => ['one', 'two'],
],
null,
null,
],
[
'username=admin001&role=administrator&usepass=0&foo[]=one&foo[]=two',
'foo.0',
'one',
null,
null,
],
[
'username=admin001&role=administrator&usepass=0&foo[]=one&foo[]=two&bar[baz]=hello',
'bar.baz',
'hello',
null,
null,
],
[
'username=admin001&role=administrator&usepass=0&foo[]=one&foo[]=two&bar[baz]=hello6.5world',
'bar.baz',
'6.5',
FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_FRACTION,
],
];
}

/**
* @dataProvider provideRawInputVarChecks
*
* @param string $rawstring
* @param mixed $var
* @param mixed $expected
* @param mixed $filter
* @param mixed $flag
*/
public function testCanGrabGetRawInputVar($rawstring, $var, $expected, $filter, $flag)
{
$config = new App();
$config->baseURL = 'http://example.com/';

$request = new IncomingRequest($config, new URI(), $rawstring, new UserAgent());

$this->assertSame($expected, $request->getRawInputVar($var, $filter, $flag));
}

public function testIsCLI()
{
$this->assertFalse($this->request->isCLI());
Expand Down
1 change: 1 addition & 0 deletions user_guide_src/source/changelogs/v4.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ Others
- **View:** Added ``Controlled Cells`` that provide more structure and flexibility to your View Cells. See :ref:`View Cells <controlled-cells>` for details.
- **Config:** Now you can specify Composer packages to auto-discover manually. See :ref:`Code Modules <modules-specify-composer-packages>`.
- **Debug:** Kint has been updated to 5.0.1.
- **Request:** Added new ``$request->getRawInputVar()`` method to return a specified variable from raw stream. See :ref:`Retrieving Raw data <incomingrequest-retrieving-raw-data>`.

Message Changes
***************
Expand Down
6 changes: 5 additions & 1 deletion user_guide_src/source/incoming/incomingrequest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ This will retrieve data and convert it to an array. Like this:

.. literalinclude:: incomingrequest/013.php

You can also use ``getRawInputVar()``, to get the specified variable from raw stream and filter it.

.. literalinclude:: incomingrequest/039.php

Filtering Input Data
====================

Expand All @@ -168,7 +172,7 @@ Filtering a POST variable would look like this:
.. literalinclude:: incomingrequest/014.php

All of the methods mentioned above support the filter type passed in as the second parameter, with the
exception of ``getJSON()``.
exception of ``getJSON()`` and ``getRawInput()``.

Retrieving Headers
******************
Expand Down
29 changes: 29 additions & 0 deletions user_guide_src/source/incoming/incomingrequest/039.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

// When the request body is 'foo=one&bar=two&baz[]=10&baz[]=20'
var_dump($request->getRawInputVar('bar'));
// Outputs: two

// foo=one&bar=two&baz[]=10&baz[]=20
var_dump($request->getRawInputVar(['foo', 'bar']));
/*
* Outputs:
* [
* 'foo' => 'one',
* 'bar' => 'two'
* ]
*/

// foo=one&bar=two&baz[]=10&baz[]=20
var_dump($request->getRawInputVar('baz'));
/*
* Outputs:
* [
* '10',
* '20'
* ]
*/

// foo=one&bar=two&baz[]=10&baz[]=20
var_dump($request->getRawInputVar('baz.0'));
// Outputs: 10