Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into 4.4
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjis committed Feb 7, 2023
2 parents 0b989f1 + 315f8c6 commit 7ea9372
Show file tree
Hide file tree
Showing 19 changed files with 201 additions and 78 deletions.
2 changes: 1 addition & 1 deletion admin/framework/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"psr/log": "^1.1"
},
"require-dev": {
"kint-php/kint": "^5.0.1",
"kint-php/kint": "^5.0.3",
"codeigniter/coding-standard": "^1.5",
"fakerphp/faker": "^1.9",
"friendsofphp/php-cs-fixer": "3.13.0",
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"psr/log": "^1.1"
},
"require-dev": {
"kint-php/kint": "^5.0.1",
"kint-php/kint": "^5.0.3",
"codeigniter/coding-standard": "^1.5",
"fakerphp/faker": "^1.9",
"friendsofphp/php-cs-fixer": "3.13.0",
Expand All @@ -25,7 +25,7 @@
"phpunit/phpcov": "^8.2",
"phpunit/phpunit": "^9.1",
"predis/predis": "^1.1 || ^2.0",
"rector/rector": "0.15.11",
"rector/rector": "0.15.12",
"vimeo/psalm": "^5.0"
},
"suggest": {
Expand Down
4 changes: 4 additions & 0 deletions contributing/signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ bash shell to use the **-S** option to force the secure signing.

Regardless of how you sign a commit, commit messages are important too.
See [Contribution Workflow](./workflow.md#commit-messages) for details.

## GPG-Signing Old Commits

See [Contribution Workflow](./workflow.md#gpg-signing-old-commits).
2 changes: 1 addition & 1 deletion phpstan-baseline.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ parameters:

-
message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getDefaultNamespace\\(\\)\\.$#"
count: 3
count: 2
path: system/Router/Router.php

-
Expand Down
11 changes: 11 additions & 0 deletions system/Debug/Exceptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class Exceptions
*/
protected $response;

private ?Throwable $exceptionCaughtByExceptionHandler = null;

/**
* @param CLIRequest|IncomingRequest $request
*/
Expand Down Expand Up @@ -113,6 +115,8 @@ public function initialize()
*/
public function exceptionHandler(Throwable $exception)
{
$this->exceptionCaughtByExceptionHandler = $exception;

[$statusCode, $exitCode] = $this->determineCodes($exception);

if ($this->config->log === true && ! in_array($statusCode, $this->config->ignoreCodes, true)) {
Expand Down Expand Up @@ -191,6 +195,13 @@ public function shutdownHandler()

['type' => $type, 'message' => $message, 'file' => $file, 'line' => $line] = $error;

if ($this->exceptionCaughtByExceptionHandler) {
$message .= "\n【Previous Exception】\n"
. get_class($this->exceptionCaughtByExceptionHandler) . "\n"
. $this->exceptionCaughtByExceptionHandler->getMessage() . "\n"
. $this->exceptionCaughtByExceptionHandler->getTraceAsString();
}

if (in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE], true)) {
$this->exceptionHandler(new ErrorException($message, 0, $type, $file, $line));
}
Expand Down
2 changes: 1 addition & 1 deletion system/HTTP/IncomingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ protected function parseQueryString(): string
$uri = $_SERVER['QUERY_STRING'] ?? @getenv('QUERY_STRING');

if (trim($uri, '/') === '') {
return '';
return '/';
}

if (strncmp($uri, '/', 1) === 0) {
Expand Down
9 changes: 6 additions & 3 deletions system/Helpers/form_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -741,17 +741,20 @@ function validation_show_error(string $field, string $template = 'single'): stri
$config = config('Validation');
$view = Services::renderer();

$errors = validation_errors();
$errors = array_filter(validation_errors(), static fn ($key) => preg_match(
'/^' . str_replace(['\.\*', '\*\.'], ['\..+', '.+\.'], preg_quote($field, '/')) . '$/',
$key
), ARRAY_FILTER_USE_KEY);

if (! array_key_exists($field, $errors)) {
if ($errors === []) {
return '';
}

if (! array_key_exists($template, $config->templates)) {
throw ValidationException::forInvalidTemplate($template);
}

return $view->setVar('error', $errors[$field])
return $view->setVar('error', implode("\n", $errors))
->render($config->templates[$template]);
}
}
Expand Down
11 changes: 6 additions & 5 deletions system/Router/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,20 @@ public function __construct(RouteCollectionInterface $routes, ?Request $request
}

/**
* Finds the controller method corresponding to the URI.
*
* @param string|null $uri URI path relative to baseURL
*
* @return Closure|string Controller classname or Closure
*
* @throws PageNotFoundException
* @throws RedirectException
*/
public function handle(?string $uri = null)
{
// If we cannot find a URI to match against, then
// everything runs off of its default settings.
// If we cannot find a URI to match against, then set it to root (`/`).
if ($uri === null || $uri === '') {
return strpos($this->controller, '\\') === false
? $this->collection->getDefaultNamespace() . $this->controller
: $this->controller;
$uri = '/';
}

// Decode URL-encoded string
Expand Down
2 changes: 1 addition & 1 deletion system/Router/RouterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function __construct(RouteCollectionInterface $routes, ?Request $request
/**
* Finds the controller method corresponding to the URI.
*
* @param string $uri
* @param string|null $uri URI path relative to baseURL
*
* @return Closure|string Controller classname or Closure
*/
Expand Down
4 changes: 3 additions & 1 deletion system/ThirdParty/Kint/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ public static function composerGetExtras(string $key = 'kint'): array
continue;
}

foreach ($packages as $package) {
// Composer 2.0 Compatibility: packages are now wrapped into a "packages" top level key instead of the whole file being the package array
// @see https://getcomposer.org/upgrade/UPGRADE-2.0.md
foreach ($packages['packages'] ?? $packages as $package) {
if (isset($package['extra'][$key]) && \is_array($package['extra'][$key])) {
$extras = \array_replace($extras, $package['extra'][$key]);
}
Expand Down
91 changes: 61 additions & 30 deletions tests/system/HTTP/IncomingRequestDetectingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,127 +31,158 @@ protected function setUp(): void

$_POST = $_GET = $_SERVER = $_REQUEST = $_ENV = $_COOKIE = $_SESSION = [];

$origin = 'http://www.example.com/index.php/woot?code=good#pos';

// The URI object is not used in detectPath().
$origin = 'http://www.example.com/index.php/woot?code=good#pos';
$this->request = new IncomingRequest(new App(), new URI($origin), null, new UserAgent());
}

public function testPathDefault()
{
$this->request->uri = '/index.php/woot?code=good#pos';
// /index.php/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/index.php/woot';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'woot';

$expected = 'woot';
$this->assertSame($expected, $this->request->detectPath());
}

public function testPathEmpty()
public function testPathDefaultEmpty()
{
$this->request->uri = '/';
// /
$_SERVER['REQUEST_URI'] = '/';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = '/';

$expected = '/';
$this->assertSame($expected, $this->request->detectPath());
}

public function testPathRequestURI()
{
$this->request->uri = '/index.php/woot?code=good#pos';
// /index.php/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/index.php/woot';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'woot';

$expected = 'woot';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathRequestURINested()
{
$this->request->uri = '/ci/index.php/woot?code=good#pos';
// I'm not sure but this is a case of Apache config making such SERVER
// values?
// The current implementation doesn't use the value of the URI object.
// So I removed the code to set URI. Therefore, it's exactly the same as
// the method above as a test.
// But it may be changed in the future to use the value of the URI object.
// So I don't remove this test case.

// /ci/index.php/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/index.php/woot';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'woot';

$expected = 'woot';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathRequestURISubfolder()
{
$this->request->uri = '/ci/index.php/popcorn/woot?code=good#pos';
// /ci/index.php/popcorn/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/ci/index.php/popcorn/woot';
$_SERVER['SCRIPT_NAME'] = '/ci/index.php';
$expected = 'popcorn/woot';

$expected = 'popcorn/woot';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathRequestURINoIndex()
{
$this->request->uri = '/sub/example';
// /sub/example
$_SERVER['REQUEST_URI'] = '/sub/example';
$_SERVER['SCRIPT_NAME'] = '/sub/index.php';
$expected = 'example';

$expected = 'example';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathRequestURINginx()
{
$this->request->uri = '/ci/index.php/woot?code=good#pos';
// /ci/index.php/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/index.php/woot?code=good';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'woot';

$expected = 'woot';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathRequestURINginxRedirecting()
{
$this->request->uri = '/?/ci/index.php/woot';
// /?/ci/index.php/woot
$_SERVER['REQUEST_URI'] = '/?/ci/woot';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'ci/woot';

$expected = 'ci/woot';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathRequestURISuppressed()
{
$this->request->uri = '/woot?code=good#pos';
// /woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/woot';
$_SERVER['SCRIPT_NAME'] = '/';
$expected = 'woot';

$expected = 'woot';
$this->assertSame($expected, $this->request->detectPath('REQUEST_URI'));
}

public function testPathQueryString()
{
$this->request->uri = '/?/ci/index.php/woot';
$_SERVER['REQUEST_URI'] = '/?/ci/woot';
// /index.php?/ci/woot
$_SERVER['REQUEST_URI'] = '/index.php?/ci/woot';
$_SERVER['QUERY_STRING'] = '/ci/woot';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'ci/woot';

$expected = 'ci/woot';
$this->assertSame($expected, $this->request->detectPath('QUERY_STRING'));
}

public function testPathQueryStringWithQueryString()
{
// /index.php?/ci/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/index.php?/ci/woot?code=good';
$_SERVER['QUERY_STRING'] = '/ci/woot?code=good';
$_SERVER['SCRIPT_NAME'] = '/index.php';

$expected = 'ci/woot';
$this->assertSame($expected, $this->request->detectPath('QUERY_STRING'));
}

public function testPathQueryStringEmpty()
{
$this->request->uri = '/?/ci/index.php/woot';
$_SERVER['REQUEST_URI'] = '/?/ci/woot';
// /index.php?
$_SERVER['REQUEST_URI'] = '/index.php?';
$_SERVER['QUERY_STRING'] = '';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = '';

$expected = '/';
$this->assertSame($expected, $this->request->detectPath('QUERY_STRING'));
}

public function testPathPathInfo()
{
$this->request->uri = '/index.php/woot?code=good#pos';
// /index.php/woot?code=good#pos
$this->request->setGlobal('server', [
'PATH_INFO' => null,
]);
$_SERVER['REQUEST_URI'] = '/index.php/woot';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$expected = 'woot';

$expected = 'woot';
$this->assertSame($expected, $this->request->detectPath('PATH_INFO'));
}

public function testPathPathInfoGlobal()
{
$this->request->uri = '/index.php/woot?code=good#pos';
// /index.php/woot?code=good#pos
$this->request->setGlobal('server', [
'PATH_INFO' => 'silliness',
]);
Expand Down
19 changes: 19 additions & 0 deletions tests/system/Helpers/FormHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,25 @@ public function testValidationShowError()
$this->assertSame('<span class="help-block">The ID field is required.</span>' . "\n", $html);
}

public function testValidationShowErrorForWildcards()
{
$validation = Services::validation();
$validation->setRule('user.*.name', 'Name', 'required')
->run([
'user' => [
'friends' => [
['name' => 'Name1'],
['name' => ''],
['name' => 'Name2'],
],
],
]);

$html = validation_show_error('user.*.name');

$this->assertSame('<span class="help-block">The Name field is required.</span>' . "\n", $html);
}

public function testFormParseFormAttributesTrue()
{
$expected = 'readonly ';
Expand Down
Loading

0 comments on commit 7ea9372

Please sign in to comment.