Skip to content
Closed
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
32 changes: 32 additions & 0 deletions system/HTTP/SiteURIFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@
parse_str($this->superglobals->server('QUERY_STRING'), $get);
$this->superglobals->setGetArray($get);

// Keep $_REQUEST in sync with the parsed GET values, as getVar() and
// validation read from $_REQUEST rather than $_GET.
$this->syncRequestWithGet($get);

return URI::removeDotSegments($path);
}

Expand Down Expand Up @@ -205,9 +209,37 @@
parse_str($this->superglobals->server('QUERY_STRING'), $get);
$this->superglobals->setGetArray($get);

// Keep $_REQUEST in sync with the parsed GET values, as getVar() and
// validation read from $_REQUEST rather than $_GET.
$this->syncRequestWithGet($get);

return URI::removeDotSegments($path);
}

/**
* Keep $_REQUEST in sync with the latest parsed GET values.
*
* `getVar()` and validation read from $_REQUEST rather than $_GET, so when
* the query string is rewritten here (e.g. `/index.php?/ci/woot?code=good#pos`),
* the GET-originated keys must be reflected in $_REQUEST too. Otherwise
* `getVar('code')` returns the stale or unset value.
*
* Only GET-originated keys are updated; values from POST, COOKIE and other
* sources are left untouched.
*
* @param array<array-key, array|bool|float|int|string|null> $get The parsed GET values
*/
private function syncRequestWithGet(array $get): void

Check failure on line 232 in system/HTTP/SiteURIFactory.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Method CodeIgniter\HTTP\SiteURIFactory::syncRequestWithGet() has parameter $get with no value type specified in iterable type array.
{
$request = $this->superglobals->getRequestArray();

foreach ($get as $key => $value) {
$request[$key] = $value;
}

$this->superglobals->setRequestArray($request);
}

/**
* Create current URI object.
*
Expand Down
19 changes: 19 additions & 0 deletions tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,25 @@
$this->assertSame(['code' => 'good'], $_GET);
}

public function testQueryStringKeepsRequestInSyncWithGet(): void
{
// /index.php?/ci/woot?code=good#pos
service('superglobals')
->setServer('REQUEST_URI', '/index.php?/ci/woot?code=good')
->setServer('QUERY_STRING', '/ci/woot?code=good')
->setServer('SCRIPT_NAME', '/index.php')
->setGet('/ci/woot?code', 'good');

$factory = $this->createSiteURIFactory(service('superglobals')->getServerArray());

$expected = 'ci/woot';
$this->assertSame($expected, $factory->detectRoutePath('QUERY_STRING'));

// getVar() reads from $_REQUEST, so the corrected GET value must be
// reflected there too, not just in $_GET.
$this->assertSame(['code' => 'good'], $_REQUEST); // @phpstan-ignore codeigniter.superglobalsOffsetAccess (checks the live superglobal written by the factory)

Check failure on line 277 in tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

No error with identifier codeigniter.superglobalsOffsetAccess is reported on line 277.
}

public function testQueryStringEmpty(): void
{
// /index.php?
Expand Down
Loading